SlideShare a Scribd company logo
A monad is a really simple concept.
Why do we have functions? Can’t we just write one big program, with loops, if statements, expressions, assignments?
Why do we need functions? We really need functions so that we can structure our programs. We need functions so that we can
decompose the program into smaller pieces and recompose it. This is what we have been talking about in category theory from the very
beginning: it is composition.
And the power of functions really is in the dot. That’s where the power sits. Dot is the composition operator in Haskell.
It combines two functions so the output of one function becomes the input of the other.
So that explains what functions are really, functions are about composition.
And so is the monad. People start by giving examples of monads, there is the state monad, there is the exception monad, these are so
completely different, what do exceptions have to do with state? What do they have to do with input/output?
Well, it’s just as with functions: functions can be used to implement so many different things, but really functons are about composition.
And so is the monad. The monad is all about composing stuff. It replaces this dot with the Kleisli arrow…The fish operator.
Dot is used for composing simple functions in which the output of one function matches the input of another function, and that’s the
most trivial way of composing stuff.
The fish operator is used to compose these functions whose output type is embellished. So if the output of a function would be B but
now we are embellishing it with some stuff, e.g. embellishing it with logging, by adding a string to it, the logging kleisli arrow, but then in
order to compose these things we have to unpack the return type before we can send it on to the next function. So actually not much is
happening inside the dot, a function is called and the result is passed to another function, but much more is happening inside the fish,
because there is the unpacking and the passing of the value to the next function, and also maybe some decision is taken, like in the
case of exceptions. Once we have this additional step of combining functions, we can make decisions, like maybe we don’t want to call
the next function at all, maybe we want to bypass it. So a lot of stuff may happen inside the fish.
And just like we have the identity function here, that’s an identity with respect to the dot, here we have this kleisli arrow that
represents identity, that returns this embellished result, but of the same type, and we call it return in Haskell. And it is called return
because at some point you want to be able to program like an imperative programmer. So it’s not that imperative programming is bad,
imperative programming could be good, as long as it is well controlled, and the monad lets you do programming that is kind of imperative
style. You don’t have to do this, but sometimes it is easier to understand your code when you write it in imperative style, even though it is
immediately translated into this style of composing functions. So this is just for our convenience, we want to be able to write something
that looks more imperative, but behind the scene it is still function composition upon function composition
Bartosz	Milewski introduces	the	need	for	Kleisli	composition,	in	his	lecture	on	Monads		
Category	Theory	10.1:	Monads @BartoszMilewski
That’s our problem. So what can we do?
What would it take to make them compose?
Here is our function diagram for pure function composition. And if we sort of replace things with effectful
functions, they look like this, so we have something like andThen, looks something like a fish, and every type
has an id, we are calling it pure. If we were able to define this and make it compose then we would get that
power that we were talking about. So how do we write this in Scala?
We can implement compose, the fish operator using flatMap, so the fish
operator is something we can derive later really, the operation we need is
flatMap.
Rob Norris
@tpolecat
Let’s recap, using material by Rob Norris, why we
need Kleisli composition (the fish operator),
which is defined in terms of flatMap (aka bind)
scale.bythebay.io:	Rob	Norris,	Functional	Programming	with	Effects
And there are lots of different
kinds of Functors like this, but I
want to also point out that with
functions, I am really talking
about pure functions.
Because composition breaks down if we have side effects. It no longer works. And so
what we want to do is we want to track the effects in the return type of the function.
Rather than having side effects, like returning nulls or throwing exceptions, or
something, we are going to track them in the return type of the function.
So here the effect is that the function f might
not return a B, it might return just a None.
Rúnar	Bjarnason	
@runarorama
But we run into a problem when we have functions
of this form, that we can no longer use regular
function composition. Like we can’t say f andThen
g, if we have both f and g that return Option,
because the types are no longer compatible.
But we can solve that just by writing a little more code. So we can say f andThen this
function that flatMaps g over the result of f. So we can actually write a composition
on these types of functions, that is not ordinary function composition, it is
composition on function and some additional structure.
But we can actually write that as an operator, and in both Scalaz and Cats it is
represented as this sort of fish operator >=>.
So if we have f that goes from A to Option[B] and g that goes from B to Option[C] we
have a composite function f fish g, that goes from A to Option[C].
And now this is starting to look like real composition.
And	in	fact,	once	
we	have	this,	we	
have	a	category.	
And	this	thing	is	
called	a	Kleisli
category,	named	
after	a	
mathematician	
called	Heinrich	
Kleisli.
So in general we have a Kleisli category like this, exactly
when the Functor M is a Monad.
And when we have this kind of thing, we have a Monad.
Let’s recap, using material by Rúnar
Bjarnason, why we need Kleisli
composition (the fish operator), which is
defined in terms of flatMap (aka bind)
Scala eXchange 2017 Keynote:
Composing Programs
https://skillsmatter.com/skillscasts/10746-keynote-composing-programs
If you ask someone to do monadic programming using just the fish operator (Kleisli
composition), that’s equivalent to using point-free style, and that is hard, and not very
readable. So the definition of monad using the fish operator is not the main definition used in
programming languages. And I’ll show you how to get from one definition to another very
easily, and I will call this next segment Fish Anatomy.
…
The fish operator >=> can be defined in terms of the bind operator >>=
…
So we have simplified the problem. We still have to implement bind
…
The interface of >=> is very symmetric, has meaning, looks very much like function composition.
>>= not so much.
…
So a lot of people will start by saying a monad is something that has this bind operator, and
then you ask yourself whoever came up with this weird signature of >>= ?
And it is not really weird, it comes from this [process we went through].
Bartosz	Milewski defines	Kleisli	composition	in	terms	of	bind,	in	his	lecture	on	Monads		
Category	Theory	10.1:	Monads @BartoszMilewski
class Monad m where
(>=>) :: (a -> m b) -> (b -> m c) -> (a -> m c)
return :: a -> m a
trait Monad[F[_]] {
def compose[A,B,C](f: A => F[B], g: B => F[C]): A => F[C]
def unit[A](a: => A): F[A]
}
Kleisli	composition	+	unit Kleisli	composition	+	return
Kleisli Composition (fish operator) >=> compose
Bind >>= flatMap
lifts a to m a (lifts A to F[A]) return unit/pure
(>=>)::(a ->mb)->(b->mb)->(a->mc)
(>=>) = a -> (f a) >>= g
def compose[A,B,C](f: A => F[B], g: B => F[C]): A => F[C]
a => flatMap(f(a))(g)
class Monad m where
(>>=) :: m a -> (a -> m b) -> m b
return :: a -> m a
-- can then implement Kleisli composition using bind
(>=>) :: (a -> m b) -> (b -> m c) -> (a -> m c)
(>=>) = a -> (f a) >>= g
trait Monad[F[_]] {
def flatMap[A,B](ma: F[A])(f: A => F[B]): F[B]
def unit[A](a: => A): F[A]
// can then implement Kleisli composition using flatMap
def compose[A,B,C](f: A => F[B], g: B => F[C]): A => F[C] =
a => flatMap(f(a))(g)
}
flatMap	+	unit bind	+	return	(Kleisli	composition	can	then	be	implemented	with	bind)
Defining	a	Monad	in	terms	of	Kleisli	composition	and	Kleisli	identity	function
Defining	Kleisli	composition	in	terms	of	flatMap	(bind)
Defining	a	Monad	in	terms	of	flatmap	(bind)	and	unit	(return)
Bartosz	Milewski	introduces	a	third	definition	of	Monad in	terms	of	join	and	return,	based	on	Functor	
So this (join and return) is an alternative definition of a monad. But in this case I have to specifically say that m is a Functor, which is actually a nice thing, that I have to explicitly specify it.
…
But remember, in this case (join and return) you really have to assume that it is a functor. In this way, join is the most basic thing. Using just join and return is really more atomic than using
either bind or the Kleisli arrow, because they additionally susbsume functoriality, whereas here, functoriality is separate, separately it is a functor and separately we define join, and
separately we define return.
…
So this definition (join and return) or the definition with the Kleisli arrow, they are not used in Haskell, although they could have been. But Haskell people decided to use this (>>= and return)
as their basic definition and then for every monad they separately define join and the Kleisli arrow. So if you have a monad you can use join and the Kleisli arrow because they are defined in
the library for you. So it’s always enough to define just bind, and then fish and join will be automatically defined for you, you don’t have to do it.
#1
#2
#3
Category	Theory	10.1:	Monads @BartoszMilewski
Functional Programming in Scala
In	’FP	in	Scala’	we	also	see	a	third	minimal	sets	of	primitive	Monad combinators
We’ve seen three minimal sets of primitive Monad combinators, and instances of
Monad will have to provide implementations of one of these sets:
• unit and flatMap
• unit and compose
• unit , map , and join
And we know that there are two monad laws to be satisfied, associativity and identity,
that can be formulated in various ways. So we can state plainly what a monad is :
A monad is an implementation of one of the minimal sets of monadic
combinators, satisfying the laws of associativity and identity.
That’s a perfectly respectable, precise, and terse definition. And if we’re being precise,
this is the only correct definition.
(by	Paul	Chiusano	and	Runar	Bjarnason)
@pchiusano @runarorama
trait Monad[F[_]] {
def flatMap[A,B](ma: F[A])(f: A => F[B]): F[B]
def unit[A](a: => A): F[A]
}
class Monad m where
(>=>) :: (a -> m b) -> (b -> m c) -> (a -> m c)
return :: a -> m a
class Monad m where
(>>=) :: m a -> (a -> m b) -> m b
return :: a -> m a
class Functor f where
fmap :: (a -> b) -> f a -> f b
class Functor m => Monad m where
join :: m(m a) -> ma
return :: a -> m a
trait Functor[F[_]] {
def map[A,B](m: F[A])(f: A => B): F[B]
}
trait Monad[F[_]] extends Functor[F] {
def join[A](mma: F[F[A]]): F[A]
def unit[A](a: => A): F[A]
}
trait Monad[F[_]] {
def compose[A,B,C](f: A => F[B], g: B => F[C]): A => F[C]
def unit[A](a: => A): F[A]
}
flatmap	+	unit
map +	join +	unit
Kleisli	composition	+	unit
bind	+	return
fmap	+	join +	return
Kleisli	composition	+	return
Defining	a	Monad	in	terms	of	map	(fmap),	join	and	unit	(return)
trait Monad[F[_]] {
def flatMap[A,B](ma: F[A])(f: A => F[B]): F[B]
def unit[A](a: => A): F[A]
def join[A](mma: F[F[A]]): F[A] = flatMap(mma)(ma => ma)
def map[A,B](m: F[A])(f: A => B): F[B] = flatMap(m)(a => unit(f(a)))
def compose[A,B,C](f: A => F[B], g: B => F[C]): A => F[C] = a => flatMap(f(a))(g)
}
trait Functor[F[_]] {
def map[A,B](m: F[A])(f: A => B): F[B]
}
trait Monad[F[_]] extends Functor[F] {
def join[A](mma: F[F[A]]): F[A]
def unit[A](a: => A): F[A]
def flatMap[A,B](ma: F[A])(f: A => F[B]): F[B] = join(map(ma)(f))
def compose[A,B,C](f: A => F[B], g: B => F[C]): A => F[C] = a => flatMap(f(a))(g)
}
trait Monad[F[_]] {
def compose[A,B,C](f: A => F[B], g: B => F[C]): A => F[C]
def unit[A](a: => A): F[A]
def flatMap[A,B](ma: F[A])(f: A => F[B]): F[B] = compose((_:Unit) => ma, f)(())
def map[A,B](m: F[A])(f: A => B): F[B] = flatMap(m)(a => unit(f(a)))
}
flatmap +	unit
map +	join +	unit
Kleisli	composition	+	unit
Functional Programming in Scala
defining	join,	map and	compose in	
terms	of	flatMap and	unit
defining	flatMap and	map in	terms	
of	compose	and	unit
defining	flatMap and	compose	in	
terms	of	join	and	map
Using primitive monad
combinators to define the
other key combinators
(by	Paul	Chiusano	and	Runar	Bjarnason)
@pchiusano @runarorama
Monads in Category Theory
In Category Theory, a Monad is a functor equipped with a pair of natural transformations satisfying the laws
of associativity and identity.
What does this mean? If we restrict ourselves to the category of Scala types (with Scala types as the objects
and functions as the arrows), we can state this in Scala terms.
A Functor is just a type constructor for which map can be implemented:
trait Functor[F[_]] {
def map[A,B](fa: F[A])(f: A => B): F[B]
}
A natural transformation from a functor F to a functor G is just a polymorphic function:
trait Transform[F[_], G[_]] {
def apply[A](fa: F[A]): G[A]
}
The natural transformations that form a monad for F are unit and join:
type Id[A] = A
def unit[F](implicit F: Monad[F]) = new Transform[Id, F] {
def apply(a: A): F[A] = F.unit(a)
}
def join[F](implicit F: Monad[F]) = new Transform[({type f[x] = F[F[x]]})#f, F] {
def apply(ffa: F[F[A]]): F[A] = F.join(ffa)
}
In	Category	Theory	a	Monad	is	a	functor	equipped	with	a	pair	of	natural	transformations satisfying	the	laws	of	associativity	and	identity
(by	Runar	Bjarnason)
@runarorama
All three definitions [of Monad] are used in category theory, but really, everybody uses the one with join, except that they don’t call it join and they don’t call it return. And they don’t call the functor M, they
call it T. So the translation is m goes to T, join goes to µ and return goes to η. They use Greek letters here and it makes sesne because they use Greek letters for natural transformations and you will see that
these (join and return) are natural transformations. So now I’ll switch notation to T, µ and η.
We already talked about return at some point, when I talked about natural transformations, I said that return really is a polymorphic function that goes from a to ma, in the old notation, but really, since it is a
polymorphic function, it is really a natural transformation a --> ma where a is the identity functor acting on a (Ida). So it is really a natural transformation between two functors, and Ida is a component of the
natural transformation, for some particular a. So return is a component of the natural transformation from the identity functor to m, and since we don‘t want to use m here, I am going to use T.
So we‘ll say that η (unit/return) is a natural transformation from the identity functor to T. And it means the same thing, except that in Haskell we use it in components, every natural transformation has
components, so for a particular a, Ida acting on a gives you a, T acting on a gives you ma.
Now what is µ?, µ (join) is also a natural transformation. Remember, join was going from m(m a) to ma. What is m(m a)? It means we take this functor, we act on a, and then we apply it to the result. So this is
double application of the functor. It is just composition of the functor with itself. So this in mathematical notation would be T ∘ T --> T. Double application ot T, in components, it will give you m(m a), double
application of a functor in components is m(m a). Single application of the functor is m a. It is a natural transformation.
So in category theory we have to say it is a natural transformation. In Haskell we didn‘t say it is natural transformation, we didn‘t mention the naturality condition for return. Why? Because of polymorphism,
because of ‘theorems for free‘, it is automatically a natural transformation, the naturality condition is automatic. But in category theory we have to say it is a natural transformation. So T ∘ T is usually written
simply as T2. T2 is just compositon of T with itself. That‘s shorthand notation.
So, a monad is a functor T and two natural transformations. Plus some laws, otherwise if we try to make a Kleisli category on top of this we wouldn‘t get associativity and identity laws.
Bartosz	Milewski	defines	a	monad	as	a	functor	and	two	natural	transformations,	plus	associativity	and	identity	laws
Category	Theory	10.1:	Monads
@BartoszMilewski
A B
f
FA FB
F(f)
GA GB
G(f)
F
G
C1
C1 and C2 are categories and ∘	denotes their composition operations.
F and G are functors from C1 to C2 which map each C1 object to a C2 object and map each C1 arrow to a C2 arrow
A natural transformation 𝜏	from F to G (either both covariant of both contravariant) is
a family of arrows 𝜏 𝑋: FX →	GX of C2 indexed by the object X of C1 such that for each arrow f: A →	B of C1, the appropriate square
in C2 commutes (depending on the variance)
Natural	Transformation
𝜏A 𝜏B
G(f)∘ 𝜏A
𝜏B∘F(f)
C2
𝜏
F G
natural	transformation	
𝜏	from	F to	G
𝜏A
FA GA
GB
𝜏B
GZ
𝜏Z
…… …
FA FB
F(f)
GA GB
G(f)
𝜏A 𝜏B
F(f)∘ 𝜏A
𝜏B∘G(f)
FB
FZ
covariant contravariant
the	square	commutes
G(f)∘ 𝜏A= 𝜏B∘F(f)
𝜏
F G
Naturality	
Condition
Let’s	recap	on	Natural	Transformations	(3	slides)
https://www.slideshare.net/pjschwarz/natural-transformations
@philip_schwarz
A B
f
F[A]
f↑F
f↑G
𝜏A 𝜏B
f↑G∘ 𝜏A
𝜏B∘f↑F
𝜏
F G
natural	transformation	
𝜏	from	F to	G
𝜏A
F[A] G[A]
F[B]
𝜏B
F[Z]
𝜏Z
…… …
F[A] F[B]
f↑F
G[A] G[B]
f↑G
𝜏A 𝜏B
F[B]
G[A] G[B]
G[B]
G[Z]
F(f)∘ 𝜏A
𝜏B∘G(f)
F
G
C1	=	C2	=	Scala	types	and	functions
• objects:	types
• arrows:	functions
• composition	operation:		compose function,	denoted	here	by	∘
• identity	arrows:	identity	function	T	=>	T
Functor F from	C1	to	C2	consisting	of	
• type	constructor	F that	maps	type	A	to	F[A]	
• a	map function	from	function	f:A=>B	to	function	f↑F	:F[A]	=>	F[B]	
Functor G from	C1	to	C2	consisting	of	
• type	constructor	G that	maps	type	A	to	G[A]	
• a	map function	from	function	f:A=>B	to	function	f↑G	:G[A]	=>	G[B]	
F[A] is	type	A	lifted	into	context	F
f↑F		is	function	f	lifted	into	context	F
Generic	Scala	Example:	Natural	Transformation	between	two	Functors	from	the	category	of	‘Scala	types	and	functions’	to	itself
the	square	commutes
f↑G	∘ 𝜏A = 𝜏B ∘	f↑F
mapG f ∘ 𝜏A = 𝜏B ∘ mapF f
𝜏
F G
covariant contravariant
map lifts	f	into	F
f↑F		is	map f
C1 = C2 = types	and	functions Naturality	
Condition
https://www.slideshare.net/pjschwarz/natural-transformations
@philip_schwarz
String
length
List[String] List[Int]
length↑List
Option[String] Option[Int]
Concrete	Scala	Example:	safeHead - natural	transformation	𝜏	from	List functor	to	Option functor
safeHead[String] =	𝜏StringInt
length↑Option
𝜏Int	=	safeHead[Int]
safeHead ∘length↑Option
Option
𝜏
List Option
natural	transformation	𝜏	from	List to	Option
𝜏String
List[String] Option[String]
List[Int]
𝜏Int
List[Char]
𝜏Char
…… …
Option[Int]
Option[Char]
length↑List	∘	safeHead
covariant
val length: String => Int = s => s.length
// a natural transformation
def safeHead[A]: List[A] => Option[A] = {
case head::_ => Some(head)
case Nil => None
}
the	square	commutes
length↑List	∘ safeHead = safeHead	∘	length↑Option
(mapList length)			∘ safeHead = safeHead	∘	(mapOption length)
𝜏
List Option
F[A] is	type	A	lifted	into	context	F
f↑F		is	function	f	lifted	into	context	F
map lifts	f	into	F
f↑F		is	map f
C1 = C2 = types	and	functions
List
Naturality	
Condition
https://www.slideshare.net/pjschwarz/natural-transformations
@philip_schwarz
FA FB
A B
FFA FFB
FA FB
GA GB
FA FB A
join join
unit
𝜏A
f
f↑F
(f↑F)↑F
f↑F
f↑G
(f↑F)↑F ∘ unit
unit ∘f↑F
𝜏B
trait Functor[F[_]] {
def map[A, B](f: A => B): F[A] => F[B]
}
trait Monad[F[_]] extends Functor[F] {
def join[A](mma: F[F[A]]): F[A]
def unit[A](a: => A): F[A]
def flatMap[A,B](f: A => F[B]): F[A] => F[B] = (ma:F[A]) => join(map(f)(ma))
def compose[A,B,C](f: A => F[B], g: B => F[C]): A => F[C] = a => flatMap(g)(f(a))
}
unit
unit unit
gg↑F
f↑F ∘ unit
unit ∘ f
f↑F ∘ join
join ∘(f↑F)↑F
f↑G∘ 𝜏A
𝜏B ∘	f↑F
flatMap g = join ∘ (map g)
= join ∘ g↑F
flatMap	g
map	g
FB A
FC
B g
h g compose h
calls	g	with	A,	then	flatMaps	h	over	
result	FB	(to	apply	h	to	its	contents),	
returning	result	FC.
f									pure function
g,h					effectful (kleisli)	functions
flatMap >>=
compose <=<
map <$>
natural	transformations:	
𝜏	
unit	aka	pure aka	η
join	aka	flatten aka	μ
map lifts	f	into	F
f↑F		is	map f
Note:	signatures	of	map	and	flatMap	
have	here	been	rearranged	(by	
swapping	parameters	around	and	
uncurrying):	they	now	return	a	function
Monadic	Combinators	in	Action	
primitive:	unit and	join – natural	transformations
derived:	flatMap and	compose	(Kleisli	composition)
Creates	a	function	which	
flatMap maps	given	function	over	its	argument	and	joins	the	result
compose calls	1st given	function	with	its	argument	and	flatMaps	
2nd given	function	over	the	result
maps	g	onto	FA,	then	flattens	
resulting	FFB,	returning	FA
FC
(flatMap h)	∘ g
flatMap	h
=		(flatMap h)	∘ gg compose h
List[String] List[int]
String Int
List[List[String]] List[List[Int]]
List[String] List[int]
Option[String] Option[Int]
List[String] List[Int] String
join join
unit
safeHeadList
length
length↑L
(length↑L)↑L
length↑L
length↑O
(length↑L)↑L ∘ unit
unit ∘length↑L
unit
unit unit
asciiascii	↑L
length↑L ∘ unit
unit ∘ length
length↑L ∘ join
join ∘(length↑L)↑L
length↑O∘ safeHeadList
safeHeadOption ∘	length↑L
flatMap ascii = join ∘ (map ascii)
= join ∘ ascii↑L
flatMap	ascii
map	ascii
calls	ascii with	a	String,	then	flatMaps	chars onto	result	List[Int]	
(producing	a	Char	for	each	Int),	returning	result	List[Char]
natural	transformations:	
safeHead	
unit	aka	pure aka	η
join	aka	flatten aka	μ
map lifts	f	into	F
f↑L		is	map f	for	F=List
f↑O		is	map f	for	F=Option
Concrete	Example	of	Monadic	Combinators	in	Action	
primitive:	unit	and	join	– natural	transformations
derived:	flatMap and	compose (Kleisli	composition)
Creates	a	function	which	
flatMap maps	given	function	over	its	argument	and	joins	the	result
compose calls	1st given	function	with	its	argument	and	flatMaps	
2nd given	function	over	the	result
maps	ascii onto	List[String],	then	flattens	
resulting	List[List[Int]],	returning	List[Int]
safeHeadOption
// a natural transformation
def safeHead[A]: List[A] => Option[A] = {
case head::_ => Some(head)
case Nil => None
}
// an effectful (Kleisli) function -
def ascii(s:String): List[Int] =
if(s.isEmpty) Nil else s.head.toInt :: ascii(s.tail)
// another effectful function -
def chars(n:Int): List[Char] = n.toString.toList
// a pure function
val length: String => Int =
s => s.length
List[Int] String
Int ascii
chars ascii compose chars
List[Char]
(flatMap chars)	∘ ascii
flatMap	chars
=		(flatMap chars)	∘ asciiascii compose chars
ascii("Abc") == List(65,98,99)
chars(65) == List('6','5')
List[Char]
ascii("Abc") == List(65,98,99)
chars(65) == List('6','5')
(ascii compose chars)("Abc") = List('6','5','9','8','9','9')
def safeHead[A]: List[A] => Option[A] = {
case head::_ => Some(head)
case Nil => None
}
def ascii(s:String):List[Int] =
if(s.isEmpty) Nil else s.head.toInt :: ascii(s.tail)
def chars(n:Int):List[Char] =
n.toString.toList
assert(ascii("Abc") == List(65,98,99))
assert(chars(65) == List('6','5'))
val listM = new Monad[List] {
def map[A, B](f: A => B): List[A] => List[B] = {
case head :: tail => f(head) :: map(f)(tail)
case Nil => Nil
}
def unit[A](a: => A): List[A] = List(a)
def join[A](mma: List[List[A]]): List[A] =
mma match {
case head::tail => head ::: join(tail)
case Nil => Nil
}
}
val optionM = new Monad[Option] {
def map[A,B](f: A => B): Option[A] => Option[B] = {
case Some(a) => Some(f(a))
case None => None
}
def unit[A](a: => A): Option[A] = Some(a)
def join[A](mma: Option[Option[A]]): Option[A] =
mma match {
case Some(a) => a
case None => None
}
}
trait Functor[F[_]] {
def map[A, B](f: A => B): F[A] => F[B]
}
trait Monad[F[_]] extends Functor[F] {
def join[A](mma: F[F[A]]): F[A]
def unit[A](a: => A): F[A]
def flatMap[A,B](f: A => F[B]): F[A] => F[B] =
(ma:F[A]) => join(map(f)(ma))
def compose[A,B,C](f: A => F[B], g: B => F[C]): A => F[C] =
a => flatMap(g)(f(a))
}
val length: String => Int = s => s.length
val lengthLiftedOnce: List[String] => List[Int] = (listM map length)
val lengthLiftedTwice: List[List[String]] => List[List[Int]] = listM map lengthLiftedOnce
assert(length("abcd") == 4)
assert(lengthLiftedOnce(List("abcd","efg","hi")) == List(4,3,2))
assert(lengthLiftedTwice(List(List("abcd","efg","hi"),List("jkl","mo","p"))) == List(List(4,3,2),List(3,2,1)))
val computeAndThenTransform: List[List[String]] => List[Int] = (listM.join[Int](_)) compose lengthLiftedTwice
val transformAndThenCompute: List[List[String]] => List[Int] = lengthLiftedOnce compose listM.join
assert(computeAndThenTransform(List(List("abcd","efg","hi"),List("jkl","mo","p"))) ==
transformAndThenCompute(List(List("abcd","efg","hi"),List("jkl","mo","p"))))
assert(computeAndThenTransform(List(List("abcd","efg","hi"),List("jkl","mo","p"))) == List(4,3,2,3,2,1))
assert(transformAndThenCompute(List(List("abcd","efg","hi"),List("jkl","mo","p"))) == List(4,3,2,3,2,1))
val computeAndThenTransform: List[String] => List[List[Int]] =
((x:List[Int]) => listM.unit(x)) compose lengthLiftedOnce
val transformAndThenCompute: List[String] => List[List[Int]] =
lengthLiftedTwice compose ((x:List[String]) => listM.unit(x))
assert(computeAndThenTransform(List("abcd","efg","hi")) == transformAndThenCompute(List("abcd","efg","hi")))
assert(computeAndThenTransform(List("abcd","efg","hi")) == List(List(4,3,2)))
assert(transformAndThenCompute(List("abcd","efg","hi")) == List(List(4,3,2)))
val computeAndThenTransform: String => List[Int] = ((x:Int) => listM.unit(x)) compose length
val transformAndThenCompute: String => List[Int] = lengthLiftedOnce compose ((x:String) => listM.unit(x))
assert(computeAndThenTransform("abcd") == transformAndThenCompute("abcd"))
assert(computeAndThenTransform("abcd") == List(4))
assert(transformAndThenCompute("abcd") == List(4))
List[String] List[int]
String Int
List[List[String]] List[List[Int]]
List[String] List[int]
join join
unit
length
length↑L
(length↑L)↑L
(length↑L)↑L ∘ unit
unit ∘length↑L
unit
unit unit
length↑L ∘ unit
unit ∘ length
length↑L ∘ join
join ∘(length↑L)↑L
val computeAndThenTransform: List[String] => Option[Int] = safeHead compose (listM map length)
val transformAndThenCompute: List[String] => Option[Int] = (optionM map length) compose safeHead
assert(computeAndThenTransform(List("abc", "d", "ef")) == transformAndThenCompute(List("abc", "d", "ef")))
assert(computeAndThenTransform(List("abc", "d", "ef")) == Some(3))
assert(transformAndThenCompute(List("abc", "d", "ef")) == Some(3))
assert(computeAndThenTransform(List()) == transformAndThenCompute(List()))
assert(computeAndThenTransform(List()) == None)
assert(transformAndThenCompute(List()) == None)
Option[String] Option[Int]
safeHeadList
length↑O
length↑O∘ safeHeadList
safeHeadOption ∘	length↑L
safeHeadOption
List[List[String]] List[List[Int]]
List[String] List[int]
List[String] List[Int] String
join join
(length↑L)↑L
length↑L
asciiascii	↑L
length↑L ∘ join
join ∘(length↑L)↑L
flatMap ascii = join ∘ (map ascii)
= join ∘ ascii↑L
flatMap	ascii
map	ascii
maps	ascii onto	List[String],	then	flattens	
resulting	List[List[Int]],	returning	List[Int]
def ascii(s:String):List[Int] = if(s.isEmpty) Nil else s.head.toInt :: ascii(s.tail)
assert(ascii("Abc") == List(65,98,99))
val mappedAscii: List[String] => List[List[Int]] = listM map ascii
val flatMappedAscii: List[String] => List[Int] = listM flatMap ascii
val compositionOfMappedAsciiAndJoin = (listM.join[Int](_)) compose mappedAscii
assert( compositionOfMappedAsciiAndJoin(List("abcd","efg","hi")) == flatMappedAscii(List("abcd","efg","hi")) )
assert( compositionOfMappedAsciiAndJoin(List("abcd","efg","hi")) == List(97, 98, 99, 100,101,102,103,104,105))
assert( flatMappedAscii(List("abcd","efg","hi")) == List(97, 98, 99, 100,101,102,103,104,105))
def ascii(s:String):List[Int] = if(s.isEmpty) Nil else s.head.toInt :: ascii(s.tail)
def chars(n:Int):List[Char] = n.toString.toList
assert(chars(65) == List('6','5'))
assert(ascii("Abc") == List(65,98,99))
def flatMappedChars = listM flatMap chars
def kleisliCompositionOfAsciiAndChars = listM.compose(ascii, chars)
assert( kleisliCompositionOfAsciiAndChars("Abc") == (flatMappedChars compose ascii)("Abc"))
assert( kleisliCompositionOfAsciiAndChars("Abc") == List('6','5','9','8','9','9'))
assert( (flatMappedChars compose ascii)("Abc") == List('6','5','9','8','9','9'))
calls	ascii with	a	String,	then	flatMaps	chars onto	result	List[Int]	
(producing	a	Char	for	each	Int),	returning	result	List[Char]
List[Int] String
Int ascii
chars ascii compose chars
List[Char]
(flatMap chars)	∘ ascii
flatMap	chars
=		(flatMap chars)	∘ asciiascii compose chars
List[Char]
Ad

More Related Content

What's hot (20)

The Functional Programmer's Toolkit (NDC London 2019)
The Functional Programmer's Toolkit (NDC London 2019)The Functional Programmer's Toolkit (NDC London 2019)
The Functional Programmer's Toolkit (NDC London 2019)
Scott Wlaschin
 
The aggregate function - from sequential and parallel folds to parallel aggre...
The aggregate function - from sequential and parallel folds to parallel aggre...The aggregate function - from sequential and parallel folds to parallel aggre...
The aggregate function - from sequential and parallel folds to parallel aggre...
Philip Schwarz
 
OOP and FP
OOP and FPOOP and FP
OOP and FP
Mario Fusco
 
Monad Laws Must be Checked
Monad Laws Must be CheckedMonad Laws Must be Checked
Monad Laws Must be Checked
Philip Schwarz
 
Python OOPs
Python OOPsPython OOPs
Python OOPs
Binay Kumar Ray
 
The Power of Composition
The Power of CompositionThe Power of Composition
The Power of Composition
Scott Wlaschin
 
The Functional Programming Triad of Folding, Scanning and Iteration - a first...
The Functional Programming Triad of Folding, Scanning and Iteration - a first...The Functional Programming Triad of Folding, Scanning and Iteration - a first...
The Functional Programming Triad of Folding, Scanning and Iteration - a first...
Philip Schwarz
 
Java 8 lambda
Java 8 lambdaJava 8 lambda
Java 8 lambda
Manav Prasad
 
Domain Modeling in a Functional World
Domain Modeling in a Functional WorldDomain Modeling in a Functional World
Domain Modeling in a Functional World
Debasish Ghosh
 
Functional Design Patterns (DevTernity 2018)
Functional Design Patterns (DevTernity 2018)Functional Design Patterns (DevTernity 2018)
Functional Design Patterns (DevTernity 2018)
Scott Wlaschin
 
Algebraic Data Types for Data Oriented Programming - From Haskell and Scala t...
Algebraic Data Types forData Oriented Programming - From Haskell and Scala t...Algebraic Data Types forData Oriented Programming - From Haskell and Scala t...
Algebraic Data Types for Data Oriented Programming - From Haskell and Scala t...
Philip Schwarz
 
Applicative Functor
Applicative FunctorApplicative Functor
Applicative Functor
Philip Schwarz
 
Java 8 lambda expressions
Java 8 lambda expressionsJava 8 lambda expressions
Java 8 lambda expressions
Logan Chien
 
Monoids - Part 1 - with examples using Scalaz and Cats
Monoids - Part 1 - with examples using Scalaz and CatsMonoids - Part 1 - with examples using Scalaz and Cats
Monoids - Part 1 - with examples using Scalaz and Cats
Philip Schwarz
 
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1
Philip Schwarz
 
Point free or die - tacit programming in Haskell and beyond
Point free or die - tacit programming in Haskell and beyondPoint free or die - tacit programming in Haskell and beyond
Point free or die - tacit programming in Haskell and beyond
Philip Schwarz
 
Taking your side effects aside
Taking your side effects asideTaking your side effects aside
Taking your side effects aside
💡 Tomasz Kogut
 
Haskell study 2
Haskell study 2Haskell study 2
Haskell study 2
Nam Hyeonuk
 
Identifiers
Identifiers Identifiers
Identifiers
Then Murugeshwari
 
Java 8 - An Overview
Java 8 - An OverviewJava 8 - An Overview
Java 8 - An Overview
Indrajit Das
 
The Functional Programmer's Toolkit (NDC London 2019)
The Functional Programmer's Toolkit (NDC London 2019)The Functional Programmer's Toolkit (NDC London 2019)
The Functional Programmer's Toolkit (NDC London 2019)
Scott Wlaschin
 
The aggregate function - from sequential and parallel folds to parallel aggre...
The aggregate function - from sequential and parallel folds to parallel aggre...The aggregate function - from sequential and parallel folds to parallel aggre...
The aggregate function - from sequential and parallel folds to parallel aggre...
Philip Schwarz
 
Monad Laws Must be Checked
Monad Laws Must be CheckedMonad Laws Must be Checked
Monad Laws Must be Checked
Philip Schwarz
 
The Power of Composition
The Power of CompositionThe Power of Composition
The Power of Composition
Scott Wlaschin
 
The Functional Programming Triad of Folding, Scanning and Iteration - a first...
The Functional Programming Triad of Folding, Scanning and Iteration - a first...The Functional Programming Triad of Folding, Scanning and Iteration - a first...
The Functional Programming Triad of Folding, Scanning and Iteration - a first...
Philip Schwarz
 
Domain Modeling in a Functional World
Domain Modeling in a Functional WorldDomain Modeling in a Functional World
Domain Modeling in a Functional World
Debasish Ghosh
 
Functional Design Patterns (DevTernity 2018)
Functional Design Patterns (DevTernity 2018)Functional Design Patterns (DevTernity 2018)
Functional Design Patterns (DevTernity 2018)
Scott Wlaschin
 
Algebraic Data Types for Data Oriented Programming - From Haskell and Scala t...
Algebraic Data Types forData Oriented Programming - From Haskell and Scala t...Algebraic Data Types forData Oriented Programming - From Haskell and Scala t...
Algebraic Data Types for Data Oriented Programming - From Haskell and Scala t...
Philip Schwarz
 
Java 8 lambda expressions
Java 8 lambda expressionsJava 8 lambda expressions
Java 8 lambda expressions
Logan Chien
 
Monoids - Part 1 - with examples using Scalaz and Cats
Monoids - Part 1 - with examples using Scalaz and CatsMonoids - Part 1 - with examples using Scalaz and Cats
Monoids - Part 1 - with examples using Scalaz and Cats
Philip Schwarz
 
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1
Philip Schwarz
 
Point free or die - tacit programming in Haskell and beyond
Point free or die - tacit programming in Haskell and beyondPoint free or die - tacit programming in Haskell and beyond
Point free or die - tacit programming in Haskell and beyond
Philip Schwarz
 
Taking your side effects aside
Taking your side effects asideTaking your side effects aside
Taking your side effects aside
💡 Tomasz Kogut
 
Java 8 - An Overview
Java 8 - An OverviewJava 8 - An Overview
Java 8 - An Overview
Indrajit Das
 

Similar to Monad as functor with pair of natural transformations (20)

Monad Fact #6
Monad Fact #6Monad Fact #6
Monad Fact #6
Philip Schwarz
 
Arriving at monads by going from pure-function composition to effectful-funct...
Arriving at monads by going from pure-function composition to effectful-funct...Arriving at monads by going from pure-function composition to effectful-funct...
Arriving at monads by going from pure-function composition to effectful-funct...
Philip Schwarz
 
Writer Monad for logging execution of functions
Writer Monad for logging execution of functionsWriter Monad for logging execution of functions
Writer Monad for logging execution of functions
Philip Schwarz
 
Compositionality and Category Theory - a montage of slides/transcript for sec...
Compositionality and Category Theory - a montage of slides/transcript for sec...Compositionality and Category Theory - a montage of slides/transcript for sec...
Compositionality and Category Theory - a montage of slides/transcript for sec...
Philip Schwarz
 
lec15 (1).pdf
lec15 (1).pdflec15 (1).pdf
lec15 (1).pdf
projectseasy
 
N-Queens Combinatorial Problem - Polyglot FP for Fun and Profit - Haskell and...
N-Queens Combinatorial Problem - Polyglot FP for Fun and Profit - Haskell and...N-Queens Combinatorial Problem - Polyglot FP for Fun and Profit - Haskell and...
N-Queens Combinatorial Problem - Polyglot FP for Fun and Profit - Haskell and...
Philip Schwarz
 
Functional Programming in Scala: Notes
Functional Programming in Scala: NotesFunctional Programming in Scala: Notes
Functional Programming in Scala: Notes
Roberto Casadei
 
Go Beyond Higher Order Functions: A Journey into Functional Programming
Go Beyond Higher Order Functions: A Journey into Functional ProgrammingGo Beyond Higher Order Functions: A Journey into Functional Programming
Go Beyond Higher Order Functions: A Journey into Functional Programming
Lex Sheehan
 
Functors
FunctorsFunctors
Functors
Philip Schwarz
 
Functional Programming in JavaScript
Functional Programming in JavaScriptFunctional Programming in JavaScript
Functional Programming in JavaScript
Will Livengood
 
lec14.pdf
lec14.pdflec14.pdf
lec14.pdf
projectseasy
 
Tagless Final Encoding - Algebras and Interpreters and also Programs
Tagless Final Encoding - Algebras and Interpreters and also ProgramsTagless Final Encoding - Algebras and Interpreters and also Programs
Tagless Final Encoding - Algebras and Interpreters and also Programs
Philip Schwarz
 
Functional programming is the most extreme programming
Functional programming is the most extreme programmingFunctional programming is the most extreme programming
Functional programming is the most extreme programming
samthemonad
 
Python Homework Help
Python Homework HelpPython Homework Help
Python Homework Help
Python Homework Help
 
Functor, Apply, Applicative And Monad
Functor, Apply, Applicative And MonadFunctor, Apply, Applicative And Monad
Functor, Apply, Applicative And Monad
Oliver Daff
 
C++ Tail Recursion Using 64-bit variables
C++ Tail Recursion Using 64-bit variablesC++ Tail Recursion Using 64-bit variables
C++ Tail Recursion Using 64-bit variables
PVS-Studio
 
State Monad
State MonadState Monad
State Monad
Philip Schwarz
 
Beyond Mere Actors
Beyond Mere ActorsBeyond Mere Actors
Beyond Mere Actors
Boston Area Scala Enthusiasts
 
Real World Haskell: Lecture 6
Real World Haskell: Lecture 6Real World Haskell: Lecture 6
Real World Haskell: Lecture 6
Bryan O'Sullivan
 
How to build a react native app with the help of react native hooks
How to build a react native app with the help of react native hooksHow to build a react native app with the help of react native hooks
How to build a react native app with the help of react native hooks
Katy Slemon
 
Arriving at monads by going from pure-function composition to effectful-funct...
Arriving at monads by going from pure-function composition to effectful-funct...Arriving at monads by going from pure-function composition to effectful-funct...
Arriving at monads by going from pure-function composition to effectful-funct...
Philip Schwarz
 
Writer Monad for logging execution of functions
Writer Monad for logging execution of functionsWriter Monad for logging execution of functions
Writer Monad for logging execution of functions
Philip Schwarz
 
Compositionality and Category Theory - a montage of slides/transcript for sec...
Compositionality and Category Theory - a montage of slides/transcript for sec...Compositionality and Category Theory - a montage of slides/transcript for sec...
Compositionality and Category Theory - a montage of slides/transcript for sec...
Philip Schwarz
 
N-Queens Combinatorial Problem - Polyglot FP for Fun and Profit - Haskell and...
N-Queens Combinatorial Problem - Polyglot FP for Fun and Profit - Haskell and...N-Queens Combinatorial Problem - Polyglot FP for Fun and Profit - Haskell and...
N-Queens Combinatorial Problem - Polyglot FP for Fun and Profit - Haskell and...
Philip Schwarz
 
Functional Programming in Scala: Notes
Functional Programming in Scala: NotesFunctional Programming in Scala: Notes
Functional Programming in Scala: Notes
Roberto Casadei
 
Go Beyond Higher Order Functions: A Journey into Functional Programming
Go Beyond Higher Order Functions: A Journey into Functional ProgrammingGo Beyond Higher Order Functions: A Journey into Functional Programming
Go Beyond Higher Order Functions: A Journey into Functional Programming
Lex Sheehan
 
Functional Programming in JavaScript
Functional Programming in JavaScriptFunctional Programming in JavaScript
Functional Programming in JavaScript
Will Livengood
 
Tagless Final Encoding - Algebras and Interpreters and also Programs
Tagless Final Encoding - Algebras and Interpreters and also ProgramsTagless Final Encoding - Algebras and Interpreters and also Programs
Tagless Final Encoding - Algebras and Interpreters and also Programs
Philip Schwarz
 
Functional programming is the most extreme programming
Functional programming is the most extreme programmingFunctional programming is the most extreme programming
Functional programming is the most extreme programming
samthemonad
 
Functor, Apply, Applicative And Monad
Functor, Apply, Applicative And MonadFunctor, Apply, Applicative And Monad
Functor, Apply, Applicative And Monad
Oliver Daff
 
C++ Tail Recursion Using 64-bit variables
C++ Tail Recursion Using 64-bit variablesC++ Tail Recursion Using 64-bit variables
C++ Tail Recursion Using 64-bit variables
PVS-Studio
 
Real World Haskell: Lecture 6
Real World Haskell: Lecture 6Real World Haskell: Lecture 6
Real World Haskell: Lecture 6
Bryan O'Sullivan
 
How to build a react native app with the help of react native hooks
How to build a react native app with the help of react native hooksHow to build a react native app with the help of react native hooks
How to build a react native app with the help of react native hooks
Katy Slemon
 
Ad

More from Philip Schwarz (20)

The Nature of Complexity in John Ousterhout’s Philosophy of Software Design
The Nature of Complexity in John Ousterhout’sPhilosophy of Software DesignThe Nature of Complexity in John Ousterhout’sPhilosophy of Software Design
The Nature of Complexity in John Ousterhout’s Philosophy of Software Design
Philip Schwarz
 
Drawing Heighway’s Dragon - Part 3 - Simplification Through Separation of Con...
Drawing Heighway’s Dragon - Part 3 - Simplification Through Separation of Con...Drawing Heighway’s Dragon - Part 3 - Simplification Through Separation of Con...
Drawing Heighway’s Dragon - Part 3 - Simplification Through Separation of Con...
Philip Schwarz
 
The Open-Closed Principle - Part 2 - The Contemporary Version - An Introduction
The Open-Closed Principle - Part 2 - The Contemporary Version - An IntroductionThe Open-Closed Principle - Part 2 - The Contemporary Version - An Introduction
The Open-Closed Principle - Part 2 - The Contemporary Version - An Introduction
Philip Schwarz
 
The Open-Closed Principle - Part 1 - The Original Version
The Open-Closed Principle - Part 1 - The Original VersionThe Open-Closed Principle - Part 1 - The Original Version
The Open-Closed Principle - Part 1 - The Original Version
Philip Schwarz
 
Drawing Heighway’s Dragon - Part II - Recursive Function Simplification - Fro...
Drawing Heighway’s Dragon - Part II - Recursive Function Simplification - Fro...Drawing Heighway’s Dragon - Part II - Recursive Function Simplification - Fro...
Drawing Heighway’s Dragon - Part II - Recursive Function Simplification - Fro...
Philip Schwarz
 
Drawing Heighway’s Dragon - Recursive Function Rewrite - From Imperative Styl...
Drawing Heighway’s Dragon - Recursive Function Rewrite - From Imperative Styl...Drawing Heighway’s Dragon - Recursive Function Rewrite - From Imperative Styl...
Drawing Heighway’s Dragon - Recursive Function Rewrite - From Imperative Styl...
Philip Schwarz
 
Fibonacci Function Gallery - Part 2 - One in a series
Fibonacci Function Gallery - Part 2 - One in a seriesFibonacci Function Gallery - Part 2 - One in a series
Fibonacci Function Gallery - Part 2 - One in a series
Philip Schwarz
 
Fibonacci Function Gallery - Part 1 (of a series) - with minor corrections
Fibonacci Function Gallery - Part 1 (of a series) - with minor correctionsFibonacci Function Gallery - Part 1 (of a series) - with minor corrections
Fibonacci Function Gallery - Part 1 (of a series) - with minor corrections
Philip Schwarz
 
Fibonacci Function Gallery - Part 1 (of a series)
Fibonacci Function Gallery - Part 1 (of a series)Fibonacci Function Gallery - Part 1 (of a series)
Fibonacci Function Gallery - Part 1 (of a series)
Philip Schwarz
 
The Debt Metaphor - Ward Cunningham in his 2009 YouTube video
The Debt Metaphor -Ward Cunningham in his 2009 YouTube videoThe Debt Metaphor -Ward Cunningham in his 2009 YouTube video
The Debt Metaphor - Ward Cunningham in his 2009 YouTube video
Philip Schwarz
 
Folding Cheat Sheet Series Titles (so far)
Folding Cheat Sheet Series Titles (so far)Folding Cheat Sheet Series Titles (so far)
Folding Cheat Sheet Series Titles (so far)
Philip Schwarz
 
From Subtype Polymorphism To Typeclass-based Ad hoc Polymorphism - An Example
From Subtype Polymorphism To Typeclass-based Ad hoc Polymorphism - An ExampleFrom Subtype Polymorphism To Typeclass-based Ad hoc Polymorphism - An Example
From Subtype Polymorphism To Typeclass-based Ad hoc Polymorphism - An Example
Philip Schwarz
 
Folding Cheat Sheet #8 - eighth in a series
Folding Cheat Sheet #8 - eighth in a seriesFolding Cheat Sheet #8 - eighth in a series
Folding Cheat Sheet #8 - eighth in a series
Philip Schwarz
 
Function Applicative for Great Good of Leap Year Function
Function Applicative for Great Good of Leap Year FunctionFunction Applicative for Great Good of Leap Year Function
Function Applicative for Great Good of Leap Year Function
Philip Schwarz
 
Folding Cheat Sheet #7 - seventh in a series
Folding Cheat Sheet #7 - seventh in a seriesFolding Cheat Sheet #7 - seventh in a series
Folding Cheat Sheet #7 - seventh in a series
Philip Schwarz
 
Folding Cheat Sheet #6 - sixth in a series
Folding Cheat Sheet #6 - sixth in a seriesFolding Cheat Sheet #6 - sixth in a series
Folding Cheat Sheet #6 - sixth in a series
Philip Schwarz
 
Folding Cheat Sheet #5 - fifth in a series
Folding Cheat Sheet #5 - fifth in a seriesFolding Cheat Sheet #5 - fifth in a series
Folding Cheat Sheet #5 - fifth in a series
Philip Schwarz
 
Hand Rolled Applicative User Validation Code Kata
Hand Rolled Applicative User ValidationCode KataHand Rolled Applicative User ValidationCode Kata
Hand Rolled Applicative User Validation Code Kata
Philip Schwarz
 
A Sighting of filterA in Typelevel Rite of Passage
A Sighting of filterA in Typelevel Rite of PassageA Sighting of filterA in Typelevel Rite of Passage
A Sighting of filterA in Typelevel Rite of Passage
Philip Schwarz
 
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidDirect Style Effect Systems -The Print[A] Example- A Comprehension Aid
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Philip Schwarz
 
The Nature of Complexity in John Ousterhout’s Philosophy of Software Design
The Nature of Complexity in John Ousterhout’sPhilosophy of Software DesignThe Nature of Complexity in John Ousterhout’sPhilosophy of Software Design
The Nature of Complexity in John Ousterhout’s Philosophy of Software Design
Philip Schwarz
 
Drawing Heighway’s Dragon - Part 3 - Simplification Through Separation of Con...
Drawing Heighway’s Dragon - Part 3 - Simplification Through Separation of Con...Drawing Heighway’s Dragon - Part 3 - Simplification Through Separation of Con...
Drawing Heighway’s Dragon - Part 3 - Simplification Through Separation of Con...
Philip Schwarz
 
The Open-Closed Principle - Part 2 - The Contemporary Version - An Introduction
The Open-Closed Principle - Part 2 - The Contemporary Version - An IntroductionThe Open-Closed Principle - Part 2 - The Contemporary Version - An Introduction
The Open-Closed Principle - Part 2 - The Contemporary Version - An Introduction
Philip Schwarz
 
The Open-Closed Principle - Part 1 - The Original Version
The Open-Closed Principle - Part 1 - The Original VersionThe Open-Closed Principle - Part 1 - The Original Version
The Open-Closed Principle - Part 1 - The Original Version
Philip Schwarz
 
Drawing Heighway’s Dragon - Part II - Recursive Function Simplification - Fro...
Drawing Heighway’s Dragon - Part II - Recursive Function Simplification - Fro...Drawing Heighway’s Dragon - Part II - Recursive Function Simplification - Fro...
Drawing Heighway’s Dragon - Part II - Recursive Function Simplification - Fro...
Philip Schwarz
 
Drawing Heighway’s Dragon - Recursive Function Rewrite - From Imperative Styl...
Drawing Heighway’s Dragon - Recursive Function Rewrite - From Imperative Styl...Drawing Heighway’s Dragon - Recursive Function Rewrite - From Imperative Styl...
Drawing Heighway’s Dragon - Recursive Function Rewrite - From Imperative Styl...
Philip Schwarz
 
Fibonacci Function Gallery - Part 2 - One in a series
Fibonacci Function Gallery - Part 2 - One in a seriesFibonacci Function Gallery - Part 2 - One in a series
Fibonacci Function Gallery - Part 2 - One in a series
Philip Schwarz
 
Fibonacci Function Gallery - Part 1 (of a series) - with minor corrections
Fibonacci Function Gallery - Part 1 (of a series) - with minor correctionsFibonacci Function Gallery - Part 1 (of a series) - with minor corrections
Fibonacci Function Gallery - Part 1 (of a series) - with minor corrections
Philip Schwarz
 
Fibonacci Function Gallery - Part 1 (of a series)
Fibonacci Function Gallery - Part 1 (of a series)Fibonacci Function Gallery - Part 1 (of a series)
Fibonacci Function Gallery - Part 1 (of a series)
Philip Schwarz
 
The Debt Metaphor - Ward Cunningham in his 2009 YouTube video
The Debt Metaphor -Ward Cunningham in his 2009 YouTube videoThe Debt Metaphor -Ward Cunningham in his 2009 YouTube video
The Debt Metaphor - Ward Cunningham in his 2009 YouTube video
Philip Schwarz
 
Folding Cheat Sheet Series Titles (so far)
Folding Cheat Sheet Series Titles (so far)Folding Cheat Sheet Series Titles (so far)
Folding Cheat Sheet Series Titles (so far)
Philip Schwarz
 
From Subtype Polymorphism To Typeclass-based Ad hoc Polymorphism - An Example
From Subtype Polymorphism To Typeclass-based Ad hoc Polymorphism - An ExampleFrom Subtype Polymorphism To Typeclass-based Ad hoc Polymorphism - An Example
From Subtype Polymorphism To Typeclass-based Ad hoc Polymorphism - An Example
Philip Schwarz
 
Folding Cheat Sheet #8 - eighth in a series
Folding Cheat Sheet #8 - eighth in a seriesFolding Cheat Sheet #8 - eighth in a series
Folding Cheat Sheet #8 - eighth in a series
Philip Schwarz
 
Function Applicative for Great Good of Leap Year Function
Function Applicative for Great Good of Leap Year FunctionFunction Applicative for Great Good of Leap Year Function
Function Applicative for Great Good of Leap Year Function
Philip Schwarz
 
Folding Cheat Sheet #7 - seventh in a series
Folding Cheat Sheet #7 - seventh in a seriesFolding Cheat Sheet #7 - seventh in a series
Folding Cheat Sheet #7 - seventh in a series
Philip Schwarz
 
Folding Cheat Sheet #6 - sixth in a series
Folding Cheat Sheet #6 - sixth in a seriesFolding Cheat Sheet #6 - sixth in a series
Folding Cheat Sheet #6 - sixth in a series
Philip Schwarz
 
Folding Cheat Sheet #5 - fifth in a series
Folding Cheat Sheet #5 - fifth in a seriesFolding Cheat Sheet #5 - fifth in a series
Folding Cheat Sheet #5 - fifth in a series
Philip Schwarz
 
Hand Rolled Applicative User Validation Code Kata
Hand Rolled Applicative User ValidationCode KataHand Rolled Applicative User ValidationCode Kata
Hand Rolled Applicative User Validation Code Kata
Philip Schwarz
 
A Sighting of filterA in Typelevel Rite of Passage
A Sighting of filterA in Typelevel Rite of PassageA Sighting of filterA in Typelevel Rite of Passage
A Sighting of filterA in Typelevel Rite of Passage
Philip Schwarz
 
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidDirect Style Effect Systems -The Print[A] Example- A Comprehension Aid
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Philip Schwarz
 
Ad

Recently uploaded (20)

Mastering Fluent Bit: Ultimate Guide to Integrating Telemetry Pipelines with ...
Mastering Fluent Bit: Ultimate Guide to Integrating Telemetry Pipelines with ...Mastering Fluent Bit: Ultimate Guide to Integrating Telemetry Pipelines with ...
Mastering Fluent Bit: Ultimate Guide to Integrating Telemetry Pipelines with ...
Eric D. Schabell
 
Adobe Illustrator Crack FREE Download 2025 Latest Version
Adobe Illustrator Crack FREE Download 2025 Latest VersionAdobe Illustrator Crack FREE Download 2025 Latest Version
Adobe Illustrator Crack FREE Download 2025 Latest Version
kashifyounis067
 
The Significance of Hardware in Information Systems.pdf
The Significance of Hardware in Information Systems.pdfThe Significance of Hardware in Information Systems.pdf
The Significance of Hardware in Information Systems.pdf
drewplanas10
 
Maxon CINEMA 4D 2025 Crack FREE Download LINK
Maxon CINEMA 4D 2025 Crack FREE Download LINKMaxon CINEMA 4D 2025 Crack FREE Download LINK
Maxon CINEMA 4D 2025 Crack FREE Download LINK
younisnoman75
 
Adobe Marketo Engage Champion Deep Dive - SFDC CRM Synch V2 & Usage Dashboards
Adobe Marketo Engage Champion Deep Dive - SFDC CRM Synch V2 & Usage DashboardsAdobe Marketo Engage Champion Deep Dive - SFDC CRM Synch V2 & Usage Dashboards
Adobe Marketo Engage Champion Deep Dive - SFDC CRM Synch V2 & Usage Dashboards
BradBedford3
 
How to Batch Export Lotus Notes NSF Emails to Outlook PST Easily?
How to Batch Export Lotus Notes NSF Emails to Outlook PST Easily?How to Batch Export Lotus Notes NSF Emails to Outlook PST Easily?
How to Batch Export Lotus Notes NSF Emails to Outlook PST Easily?
steaveroggers
 
Automation Techniques in RPA - UiPath Certificate
Automation Techniques in RPA - UiPath CertificateAutomation Techniques in RPA - UiPath Certificate
Automation Techniques in RPA - UiPath Certificate
VICTOR MAESTRE RAMIREZ
 
WinRAR Crack for Windows (100% Working 2025)
WinRAR Crack for Windows (100% Working 2025)WinRAR Crack for Windows (100% Working 2025)
WinRAR Crack for Windows (100% Working 2025)
sh607827
 
Salesforce Data Cloud- Hyperscale data platform, built for Salesforce.
Salesforce Data Cloud- Hyperscale data platform, built for Salesforce.Salesforce Data Cloud- Hyperscale data platform, built for Salesforce.
Salesforce Data Cloud- Hyperscale data platform, built for Salesforce.
Dele Amefo
 
Avast Premium Security Crack FREE Latest Version 2025
Avast Premium Security Crack FREE Latest Version 2025Avast Premium Security Crack FREE Latest Version 2025
Avast Premium Security Crack FREE Latest Version 2025
mu394968
 
EASEUS Partition Master Crack + License Code
EASEUS Partition Master Crack + License CodeEASEUS Partition Master Crack + License Code
EASEUS Partition Master Crack + License Code
aneelaramzan63
 
Requirements in Engineering AI- Enabled Systems: Open Problems and Safe AI Sy...
Requirements in Engineering AI- Enabled Systems: Open Problems and Safe AI Sy...Requirements in Engineering AI- Enabled Systems: Open Problems and Safe AI Sy...
Requirements in Engineering AI- Enabled Systems: Open Problems and Safe AI Sy...
Lionel Briand
 
Exploring Wayland: A Modern Display Server for the Future
Exploring Wayland: A Modern Display Server for the FutureExploring Wayland: A Modern Display Server for the Future
Exploring Wayland: A Modern Display Server for the Future
ICS
 
LEARN SEO AND INCREASE YOUR KNOWLDGE IN SOFTWARE INDUSTRY
LEARN SEO AND INCREASE YOUR KNOWLDGE IN SOFTWARE INDUSTRYLEARN SEO AND INCREASE YOUR KNOWLDGE IN SOFTWARE INDUSTRY
LEARN SEO AND INCREASE YOUR KNOWLDGE IN SOFTWARE INDUSTRY
NidaFarooq10
 
Douwan Crack 2025 new verson+ License code
Douwan Crack 2025 new verson+ License codeDouwan Crack 2025 new verson+ License code
Douwan Crack 2025 new verson+ License code
aneelaramzan63
 
Who Watches the Watchmen (SciFiDevCon 2025)
Who Watches the Watchmen (SciFiDevCon 2025)Who Watches the Watchmen (SciFiDevCon 2025)
Who Watches the Watchmen (SciFiDevCon 2025)
Allon Mureinik
 
Top 10 Client Portal Software Solutions for 2025.docx
Top 10 Client Portal Software Solutions for 2025.docxTop 10 Client Portal Software Solutions for 2025.docx
Top 10 Client Portal Software Solutions for 2025.docx
Portli
 
Revolutionizing Residential Wi-Fi PPT.pptx
Revolutionizing Residential Wi-Fi PPT.pptxRevolutionizing Residential Wi-Fi PPT.pptx
Revolutionizing Residential Wi-Fi PPT.pptx
nidhisingh691197
 
How Valletta helped healthcare SaaS to transform QA and compliance to grow wi...
How Valletta helped healthcare SaaS to transform QA and compliance to grow wi...How Valletta helped healthcare SaaS to transform QA and compliance to grow wi...
How Valletta helped healthcare SaaS to transform QA and compliance to grow wi...
Egor Kaleynik
 
Why Orangescrum Is a Game Changer for Construction Companies in 2025
Why Orangescrum Is a Game Changer for Construction Companies in 2025Why Orangescrum Is a Game Changer for Construction Companies in 2025
Why Orangescrum Is a Game Changer for Construction Companies in 2025
Orangescrum
 
Mastering Fluent Bit: Ultimate Guide to Integrating Telemetry Pipelines with ...
Mastering Fluent Bit: Ultimate Guide to Integrating Telemetry Pipelines with ...Mastering Fluent Bit: Ultimate Guide to Integrating Telemetry Pipelines with ...
Mastering Fluent Bit: Ultimate Guide to Integrating Telemetry Pipelines with ...
Eric D. Schabell
 
Adobe Illustrator Crack FREE Download 2025 Latest Version
Adobe Illustrator Crack FREE Download 2025 Latest VersionAdobe Illustrator Crack FREE Download 2025 Latest Version
Adobe Illustrator Crack FREE Download 2025 Latest Version
kashifyounis067
 
The Significance of Hardware in Information Systems.pdf
The Significance of Hardware in Information Systems.pdfThe Significance of Hardware in Information Systems.pdf
The Significance of Hardware in Information Systems.pdf
drewplanas10
 
Maxon CINEMA 4D 2025 Crack FREE Download LINK
Maxon CINEMA 4D 2025 Crack FREE Download LINKMaxon CINEMA 4D 2025 Crack FREE Download LINK
Maxon CINEMA 4D 2025 Crack FREE Download LINK
younisnoman75
 
Adobe Marketo Engage Champion Deep Dive - SFDC CRM Synch V2 & Usage Dashboards
Adobe Marketo Engage Champion Deep Dive - SFDC CRM Synch V2 & Usage DashboardsAdobe Marketo Engage Champion Deep Dive - SFDC CRM Synch V2 & Usage Dashboards
Adobe Marketo Engage Champion Deep Dive - SFDC CRM Synch V2 & Usage Dashboards
BradBedford3
 
How to Batch Export Lotus Notes NSF Emails to Outlook PST Easily?
How to Batch Export Lotus Notes NSF Emails to Outlook PST Easily?How to Batch Export Lotus Notes NSF Emails to Outlook PST Easily?
How to Batch Export Lotus Notes NSF Emails to Outlook PST Easily?
steaveroggers
 
Automation Techniques in RPA - UiPath Certificate
Automation Techniques in RPA - UiPath CertificateAutomation Techniques in RPA - UiPath Certificate
Automation Techniques in RPA - UiPath Certificate
VICTOR MAESTRE RAMIREZ
 
WinRAR Crack for Windows (100% Working 2025)
WinRAR Crack for Windows (100% Working 2025)WinRAR Crack for Windows (100% Working 2025)
WinRAR Crack for Windows (100% Working 2025)
sh607827
 
Salesforce Data Cloud- Hyperscale data platform, built for Salesforce.
Salesforce Data Cloud- Hyperscale data platform, built for Salesforce.Salesforce Data Cloud- Hyperscale data platform, built for Salesforce.
Salesforce Data Cloud- Hyperscale data platform, built for Salesforce.
Dele Amefo
 
Avast Premium Security Crack FREE Latest Version 2025
Avast Premium Security Crack FREE Latest Version 2025Avast Premium Security Crack FREE Latest Version 2025
Avast Premium Security Crack FREE Latest Version 2025
mu394968
 
EASEUS Partition Master Crack + License Code
EASEUS Partition Master Crack + License CodeEASEUS Partition Master Crack + License Code
EASEUS Partition Master Crack + License Code
aneelaramzan63
 
Requirements in Engineering AI- Enabled Systems: Open Problems and Safe AI Sy...
Requirements in Engineering AI- Enabled Systems: Open Problems and Safe AI Sy...Requirements in Engineering AI- Enabled Systems: Open Problems and Safe AI Sy...
Requirements in Engineering AI- Enabled Systems: Open Problems and Safe AI Sy...
Lionel Briand
 
Exploring Wayland: A Modern Display Server for the Future
Exploring Wayland: A Modern Display Server for the FutureExploring Wayland: A Modern Display Server for the Future
Exploring Wayland: A Modern Display Server for the Future
ICS
 
LEARN SEO AND INCREASE YOUR KNOWLDGE IN SOFTWARE INDUSTRY
LEARN SEO AND INCREASE YOUR KNOWLDGE IN SOFTWARE INDUSTRYLEARN SEO AND INCREASE YOUR KNOWLDGE IN SOFTWARE INDUSTRY
LEARN SEO AND INCREASE YOUR KNOWLDGE IN SOFTWARE INDUSTRY
NidaFarooq10
 
Douwan Crack 2025 new verson+ License code
Douwan Crack 2025 new verson+ License codeDouwan Crack 2025 new verson+ License code
Douwan Crack 2025 new verson+ License code
aneelaramzan63
 
Who Watches the Watchmen (SciFiDevCon 2025)
Who Watches the Watchmen (SciFiDevCon 2025)Who Watches the Watchmen (SciFiDevCon 2025)
Who Watches the Watchmen (SciFiDevCon 2025)
Allon Mureinik
 
Top 10 Client Portal Software Solutions for 2025.docx
Top 10 Client Portal Software Solutions for 2025.docxTop 10 Client Portal Software Solutions for 2025.docx
Top 10 Client Portal Software Solutions for 2025.docx
Portli
 
Revolutionizing Residential Wi-Fi PPT.pptx
Revolutionizing Residential Wi-Fi PPT.pptxRevolutionizing Residential Wi-Fi PPT.pptx
Revolutionizing Residential Wi-Fi PPT.pptx
nidhisingh691197
 
How Valletta helped healthcare SaaS to transform QA and compliance to grow wi...
How Valletta helped healthcare SaaS to transform QA and compliance to grow wi...How Valletta helped healthcare SaaS to transform QA and compliance to grow wi...
How Valletta helped healthcare SaaS to transform QA and compliance to grow wi...
Egor Kaleynik
 
Why Orangescrum Is a Game Changer for Construction Companies in 2025
Why Orangescrum Is a Game Changer for Construction Companies in 2025Why Orangescrum Is a Game Changer for Construction Companies in 2025
Why Orangescrum Is a Game Changer for Construction Companies in 2025
Orangescrum
 

Monad as functor with pair of natural transformations

  • 1. A monad is a really simple concept. Why do we have functions? Can’t we just write one big program, with loops, if statements, expressions, assignments? Why do we need functions? We really need functions so that we can structure our programs. We need functions so that we can decompose the program into smaller pieces and recompose it. This is what we have been talking about in category theory from the very beginning: it is composition. And the power of functions really is in the dot. That’s where the power sits. Dot is the composition operator in Haskell. It combines two functions so the output of one function becomes the input of the other. So that explains what functions are really, functions are about composition. And so is the monad. People start by giving examples of monads, there is the state monad, there is the exception monad, these are so completely different, what do exceptions have to do with state? What do they have to do with input/output? Well, it’s just as with functions: functions can be used to implement so many different things, but really functons are about composition. And so is the monad. The monad is all about composing stuff. It replaces this dot with the Kleisli arrow…The fish operator. Dot is used for composing simple functions in which the output of one function matches the input of another function, and that’s the most trivial way of composing stuff. The fish operator is used to compose these functions whose output type is embellished. So if the output of a function would be B but now we are embellishing it with some stuff, e.g. embellishing it with logging, by adding a string to it, the logging kleisli arrow, but then in order to compose these things we have to unpack the return type before we can send it on to the next function. So actually not much is happening inside the dot, a function is called and the result is passed to another function, but much more is happening inside the fish, because there is the unpacking and the passing of the value to the next function, and also maybe some decision is taken, like in the case of exceptions. Once we have this additional step of combining functions, we can make decisions, like maybe we don’t want to call the next function at all, maybe we want to bypass it. So a lot of stuff may happen inside the fish. And just like we have the identity function here, that’s an identity with respect to the dot, here we have this kleisli arrow that represents identity, that returns this embellished result, but of the same type, and we call it return in Haskell. And it is called return because at some point you want to be able to program like an imperative programmer. So it’s not that imperative programming is bad, imperative programming could be good, as long as it is well controlled, and the monad lets you do programming that is kind of imperative style. You don’t have to do this, but sometimes it is easier to understand your code when you write it in imperative style, even though it is immediately translated into this style of composing functions. So this is just for our convenience, we want to be able to write something that looks more imperative, but behind the scene it is still function composition upon function composition Bartosz Milewski introduces the need for Kleisli composition, in his lecture on Monads Category Theory 10.1: Monads @BartoszMilewski
  • 2. That’s our problem. So what can we do? What would it take to make them compose? Here is our function diagram for pure function composition. And if we sort of replace things with effectful functions, they look like this, so we have something like andThen, looks something like a fish, and every type has an id, we are calling it pure. If we were able to define this and make it compose then we would get that power that we were talking about. So how do we write this in Scala? We can implement compose, the fish operator using flatMap, so the fish operator is something we can derive later really, the operation we need is flatMap. Rob Norris @tpolecat Let’s recap, using material by Rob Norris, why we need Kleisli composition (the fish operator), which is defined in terms of flatMap (aka bind) scale.bythebay.io: Rob Norris, Functional Programming with Effects
  • 3. And there are lots of different kinds of Functors like this, but I want to also point out that with functions, I am really talking about pure functions. Because composition breaks down if we have side effects. It no longer works. And so what we want to do is we want to track the effects in the return type of the function. Rather than having side effects, like returning nulls or throwing exceptions, or something, we are going to track them in the return type of the function. So here the effect is that the function f might not return a B, it might return just a None. Rúnar Bjarnason @runarorama But we run into a problem when we have functions of this form, that we can no longer use regular function composition. Like we can’t say f andThen g, if we have both f and g that return Option, because the types are no longer compatible. But we can solve that just by writing a little more code. So we can say f andThen this function that flatMaps g over the result of f. So we can actually write a composition on these types of functions, that is not ordinary function composition, it is composition on function and some additional structure. But we can actually write that as an operator, and in both Scalaz and Cats it is represented as this sort of fish operator >=>. So if we have f that goes from A to Option[B] and g that goes from B to Option[C] we have a composite function f fish g, that goes from A to Option[C]. And now this is starting to look like real composition. And in fact, once we have this, we have a category. And this thing is called a Kleisli category, named after a mathematician called Heinrich Kleisli. So in general we have a Kleisli category like this, exactly when the Functor M is a Monad. And when we have this kind of thing, we have a Monad. Let’s recap, using material by Rúnar Bjarnason, why we need Kleisli composition (the fish operator), which is defined in terms of flatMap (aka bind) Scala eXchange 2017 Keynote: Composing Programs https://skillsmatter.com/skillscasts/10746-keynote-composing-programs
  • 4. If you ask someone to do monadic programming using just the fish operator (Kleisli composition), that’s equivalent to using point-free style, and that is hard, and not very readable. So the definition of monad using the fish operator is not the main definition used in programming languages. And I’ll show you how to get from one definition to another very easily, and I will call this next segment Fish Anatomy. … The fish operator >=> can be defined in terms of the bind operator >>= … So we have simplified the problem. We still have to implement bind … The interface of >=> is very symmetric, has meaning, looks very much like function composition. >>= not so much. … So a lot of people will start by saying a monad is something that has this bind operator, and then you ask yourself whoever came up with this weird signature of >>= ? And it is not really weird, it comes from this [process we went through]. Bartosz Milewski defines Kleisli composition in terms of bind, in his lecture on Monads Category Theory 10.1: Monads @BartoszMilewski
  • 5. class Monad m where (>=>) :: (a -> m b) -> (b -> m c) -> (a -> m c) return :: a -> m a trait Monad[F[_]] { def compose[A,B,C](f: A => F[B], g: B => F[C]): A => F[C] def unit[A](a: => A): F[A] } Kleisli composition + unit Kleisli composition + return Kleisli Composition (fish operator) >=> compose Bind >>= flatMap lifts a to m a (lifts A to F[A]) return unit/pure (>=>)::(a ->mb)->(b->mb)->(a->mc) (>=>) = a -> (f a) >>= g def compose[A,B,C](f: A => F[B], g: B => F[C]): A => F[C] a => flatMap(f(a))(g) class Monad m where (>>=) :: m a -> (a -> m b) -> m b return :: a -> m a -- can then implement Kleisli composition using bind (>=>) :: (a -> m b) -> (b -> m c) -> (a -> m c) (>=>) = a -> (f a) >>= g trait Monad[F[_]] { def flatMap[A,B](ma: F[A])(f: A => F[B]): F[B] def unit[A](a: => A): F[A] // can then implement Kleisli composition using flatMap def compose[A,B,C](f: A => F[B], g: B => F[C]): A => F[C] = a => flatMap(f(a))(g) } flatMap + unit bind + return (Kleisli composition can then be implemented with bind) Defining a Monad in terms of Kleisli composition and Kleisli identity function Defining Kleisli composition in terms of flatMap (bind) Defining a Monad in terms of flatmap (bind) and unit (return)
  • 6. Bartosz Milewski introduces a third definition of Monad in terms of join and return, based on Functor So this (join and return) is an alternative definition of a monad. But in this case I have to specifically say that m is a Functor, which is actually a nice thing, that I have to explicitly specify it. … But remember, in this case (join and return) you really have to assume that it is a functor. In this way, join is the most basic thing. Using just join and return is really more atomic than using either bind or the Kleisli arrow, because they additionally susbsume functoriality, whereas here, functoriality is separate, separately it is a functor and separately we define join, and separately we define return. … So this definition (join and return) or the definition with the Kleisli arrow, they are not used in Haskell, although they could have been. But Haskell people decided to use this (>>= and return) as their basic definition and then for every monad they separately define join and the Kleisli arrow. So if you have a monad you can use join and the Kleisli arrow because they are defined in the library for you. So it’s always enough to define just bind, and then fish and join will be automatically defined for you, you don’t have to do it. #1 #2 #3 Category Theory 10.1: Monads @BartoszMilewski
  • 7. Functional Programming in Scala In ’FP in Scala’ we also see a third minimal sets of primitive Monad combinators We’ve seen three minimal sets of primitive Monad combinators, and instances of Monad will have to provide implementations of one of these sets: • unit and flatMap • unit and compose • unit , map , and join And we know that there are two monad laws to be satisfied, associativity and identity, that can be formulated in various ways. So we can state plainly what a monad is : A monad is an implementation of one of the minimal sets of monadic combinators, satisfying the laws of associativity and identity. That’s a perfectly respectable, precise, and terse definition. And if we’re being precise, this is the only correct definition. (by Paul Chiusano and Runar Bjarnason) @pchiusano @runarorama
  • 8. trait Monad[F[_]] { def flatMap[A,B](ma: F[A])(f: A => F[B]): F[B] def unit[A](a: => A): F[A] } class Monad m where (>=>) :: (a -> m b) -> (b -> m c) -> (a -> m c) return :: a -> m a class Monad m where (>>=) :: m a -> (a -> m b) -> m b return :: a -> m a class Functor f where fmap :: (a -> b) -> f a -> f b class Functor m => Monad m where join :: m(m a) -> ma return :: a -> m a trait Functor[F[_]] { def map[A,B](m: F[A])(f: A => B): F[B] } trait Monad[F[_]] extends Functor[F] { def join[A](mma: F[F[A]]): F[A] def unit[A](a: => A): F[A] } trait Monad[F[_]] { def compose[A,B,C](f: A => F[B], g: B => F[C]): A => F[C] def unit[A](a: => A): F[A] } flatmap + unit map + join + unit Kleisli composition + unit bind + return fmap + join + return Kleisli composition + return Defining a Monad in terms of map (fmap), join and unit (return)
  • 9. trait Monad[F[_]] { def flatMap[A,B](ma: F[A])(f: A => F[B]): F[B] def unit[A](a: => A): F[A] def join[A](mma: F[F[A]]): F[A] = flatMap(mma)(ma => ma) def map[A,B](m: F[A])(f: A => B): F[B] = flatMap(m)(a => unit(f(a))) def compose[A,B,C](f: A => F[B], g: B => F[C]): A => F[C] = a => flatMap(f(a))(g) } trait Functor[F[_]] { def map[A,B](m: F[A])(f: A => B): F[B] } trait Monad[F[_]] extends Functor[F] { def join[A](mma: F[F[A]]): F[A] def unit[A](a: => A): F[A] def flatMap[A,B](ma: F[A])(f: A => F[B]): F[B] = join(map(ma)(f)) def compose[A,B,C](f: A => F[B], g: B => F[C]): A => F[C] = a => flatMap(f(a))(g) } trait Monad[F[_]] { def compose[A,B,C](f: A => F[B], g: B => F[C]): A => F[C] def unit[A](a: => A): F[A] def flatMap[A,B](ma: F[A])(f: A => F[B]): F[B] = compose((_:Unit) => ma, f)(()) def map[A,B](m: F[A])(f: A => B): F[B] = flatMap(m)(a => unit(f(a))) } flatmap + unit map + join + unit Kleisli composition + unit Functional Programming in Scala defining join, map and compose in terms of flatMap and unit defining flatMap and map in terms of compose and unit defining flatMap and compose in terms of join and map Using primitive monad combinators to define the other key combinators (by Paul Chiusano and Runar Bjarnason) @pchiusano @runarorama
  • 10. Monads in Category Theory In Category Theory, a Monad is a functor equipped with a pair of natural transformations satisfying the laws of associativity and identity. What does this mean? If we restrict ourselves to the category of Scala types (with Scala types as the objects and functions as the arrows), we can state this in Scala terms. A Functor is just a type constructor for which map can be implemented: trait Functor[F[_]] { def map[A,B](fa: F[A])(f: A => B): F[B] } A natural transformation from a functor F to a functor G is just a polymorphic function: trait Transform[F[_], G[_]] { def apply[A](fa: F[A]): G[A] } The natural transformations that form a monad for F are unit and join: type Id[A] = A def unit[F](implicit F: Monad[F]) = new Transform[Id, F] { def apply(a: A): F[A] = F.unit(a) } def join[F](implicit F: Monad[F]) = new Transform[({type f[x] = F[F[x]]})#f, F] { def apply(ffa: F[F[A]]): F[A] = F.join(ffa) } In Category Theory a Monad is a functor equipped with a pair of natural transformations satisfying the laws of associativity and identity (by Runar Bjarnason) @runarorama
  • 11. All three definitions [of Monad] are used in category theory, but really, everybody uses the one with join, except that they don’t call it join and they don’t call it return. And they don’t call the functor M, they call it T. So the translation is m goes to T, join goes to µ and return goes to η. They use Greek letters here and it makes sesne because they use Greek letters for natural transformations and you will see that these (join and return) are natural transformations. So now I’ll switch notation to T, µ and η. We already talked about return at some point, when I talked about natural transformations, I said that return really is a polymorphic function that goes from a to ma, in the old notation, but really, since it is a polymorphic function, it is really a natural transformation a --> ma where a is the identity functor acting on a (Ida). So it is really a natural transformation between two functors, and Ida is a component of the natural transformation, for some particular a. So return is a component of the natural transformation from the identity functor to m, and since we don‘t want to use m here, I am going to use T. So we‘ll say that η (unit/return) is a natural transformation from the identity functor to T. And it means the same thing, except that in Haskell we use it in components, every natural transformation has components, so for a particular a, Ida acting on a gives you a, T acting on a gives you ma. Now what is µ?, µ (join) is also a natural transformation. Remember, join was going from m(m a) to ma. What is m(m a)? It means we take this functor, we act on a, and then we apply it to the result. So this is double application of the functor. It is just composition of the functor with itself. So this in mathematical notation would be T ∘ T --> T. Double application ot T, in components, it will give you m(m a), double application of a functor in components is m(m a). Single application of the functor is m a. It is a natural transformation. So in category theory we have to say it is a natural transformation. In Haskell we didn‘t say it is natural transformation, we didn‘t mention the naturality condition for return. Why? Because of polymorphism, because of ‘theorems for free‘, it is automatically a natural transformation, the naturality condition is automatic. But in category theory we have to say it is a natural transformation. So T ∘ T is usually written simply as T2. T2 is just compositon of T with itself. That‘s shorthand notation. So, a monad is a functor T and two natural transformations. Plus some laws, otherwise if we try to make a Kleisli category on top of this we wouldn‘t get associativity and identity laws. Bartosz Milewski defines a monad as a functor and two natural transformations, plus associativity and identity laws Category Theory 10.1: Monads @BartoszMilewski
  • 12. A B f FA FB F(f) GA GB G(f) F G C1 C1 and C2 are categories and ∘ denotes their composition operations. F and G are functors from C1 to C2 which map each C1 object to a C2 object and map each C1 arrow to a C2 arrow A natural transformation 𝜏 from F to G (either both covariant of both contravariant) is a family of arrows 𝜏 𝑋: FX → GX of C2 indexed by the object X of C1 such that for each arrow f: A → B of C1, the appropriate square in C2 commutes (depending on the variance) Natural Transformation 𝜏A 𝜏B G(f)∘ 𝜏A 𝜏B∘F(f) C2 𝜏 F G natural transformation 𝜏 from F to G 𝜏A FA GA GB 𝜏B GZ 𝜏Z …… … FA FB F(f) GA GB G(f) 𝜏A 𝜏B F(f)∘ 𝜏A 𝜏B∘G(f) FB FZ covariant contravariant the square commutes G(f)∘ 𝜏A= 𝜏B∘F(f) 𝜏 F G Naturality Condition Let’s recap on Natural Transformations (3 slides) https://www.slideshare.net/pjschwarz/natural-transformations @philip_schwarz
  • 13. A B f F[A] f↑F f↑G 𝜏A 𝜏B f↑G∘ 𝜏A 𝜏B∘f↑F 𝜏 F G natural transformation 𝜏 from F to G 𝜏A F[A] G[A] F[B] 𝜏B F[Z] 𝜏Z …… … F[A] F[B] f↑F G[A] G[B] f↑G 𝜏A 𝜏B F[B] G[A] G[B] G[B] G[Z] F(f)∘ 𝜏A 𝜏B∘G(f) F G C1 = C2 = Scala types and functions • objects: types • arrows: functions • composition operation: compose function, denoted here by ∘ • identity arrows: identity function T => T Functor F from C1 to C2 consisting of • type constructor F that maps type A to F[A] • a map function from function f:A=>B to function f↑F :F[A] => F[B] Functor G from C1 to C2 consisting of • type constructor G that maps type A to G[A] • a map function from function f:A=>B to function f↑G :G[A] => G[B] F[A] is type A lifted into context F f↑F is function f lifted into context F Generic Scala Example: Natural Transformation between two Functors from the category of ‘Scala types and functions’ to itself the square commutes f↑G ∘ 𝜏A = 𝜏B ∘ f↑F mapG f ∘ 𝜏A = 𝜏B ∘ mapF f 𝜏 F G covariant contravariant map lifts f into F f↑F is map f C1 = C2 = types and functions Naturality Condition https://www.slideshare.net/pjschwarz/natural-transformations @philip_schwarz
  • 14. String length List[String] List[Int] length↑List Option[String] Option[Int] Concrete Scala Example: safeHead - natural transformation 𝜏 from List functor to Option functor safeHead[String] = 𝜏StringInt length↑Option 𝜏Int = safeHead[Int] safeHead ∘length↑Option Option 𝜏 List Option natural transformation 𝜏 from List to Option 𝜏String List[String] Option[String] List[Int] 𝜏Int List[Char] 𝜏Char …… … Option[Int] Option[Char] length↑List ∘ safeHead covariant val length: String => Int = s => s.length // a natural transformation def safeHead[A]: List[A] => Option[A] = { case head::_ => Some(head) case Nil => None } the square commutes length↑List ∘ safeHead = safeHead ∘ length↑Option (mapList length) ∘ safeHead = safeHead ∘ (mapOption length) 𝜏 List Option F[A] is type A lifted into context F f↑F is function f lifted into context F map lifts f into F f↑F is map f C1 = C2 = types and functions List Naturality Condition https://www.slideshare.net/pjschwarz/natural-transformations @philip_schwarz
  • 15. FA FB A B FFA FFB FA FB GA GB FA FB A join join unit 𝜏A f f↑F (f↑F)↑F f↑F f↑G (f↑F)↑F ∘ unit unit ∘f↑F 𝜏B trait Functor[F[_]] { def map[A, B](f: A => B): F[A] => F[B] } trait Monad[F[_]] extends Functor[F] { def join[A](mma: F[F[A]]): F[A] def unit[A](a: => A): F[A] def flatMap[A,B](f: A => F[B]): F[A] => F[B] = (ma:F[A]) => join(map(f)(ma)) def compose[A,B,C](f: A => F[B], g: B => F[C]): A => F[C] = a => flatMap(g)(f(a)) } unit unit unit gg↑F f↑F ∘ unit unit ∘ f f↑F ∘ join join ∘(f↑F)↑F f↑G∘ 𝜏A 𝜏B ∘ f↑F flatMap g = join ∘ (map g) = join ∘ g↑F flatMap g map g FB A FC B g h g compose h calls g with A, then flatMaps h over result FB (to apply h to its contents), returning result FC. f pure function g,h effectful (kleisli) functions flatMap >>= compose <=< map <$> natural transformations: 𝜏 unit aka pure aka η join aka flatten aka μ map lifts f into F f↑F is map f Note: signatures of map and flatMap have here been rearranged (by swapping parameters around and uncurrying): they now return a function Monadic Combinators in Action primitive: unit and join – natural transformations derived: flatMap and compose (Kleisli composition) Creates a function which flatMap maps given function over its argument and joins the result compose calls 1st given function with its argument and flatMaps 2nd given function over the result maps g onto FA, then flattens resulting FFB, returning FA FC (flatMap h) ∘ g flatMap h = (flatMap h) ∘ gg compose h
  • 16. List[String] List[int] String Int List[List[String]] List[List[Int]] List[String] List[int] Option[String] Option[Int] List[String] List[Int] String join join unit safeHeadList length length↑L (length↑L)↑L length↑L length↑O (length↑L)↑L ∘ unit unit ∘length↑L unit unit unit asciiascii ↑L length↑L ∘ unit unit ∘ length length↑L ∘ join join ∘(length↑L)↑L length↑O∘ safeHeadList safeHeadOption ∘ length↑L flatMap ascii = join ∘ (map ascii) = join ∘ ascii↑L flatMap ascii map ascii calls ascii with a String, then flatMaps chars onto result List[Int] (producing a Char for each Int), returning result List[Char] natural transformations: safeHead unit aka pure aka η join aka flatten aka μ map lifts f into F f↑L is map f for F=List f↑O is map f for F=Option Concrete Example of Monadic Combinators in Action primitive: unit and join – natural transformations derived: flatMap and compose (Kleisli composition) Creates a function which flatMap maps given function over its argument and joins the result compose calls 1st given function with its argument and flatMaps 2nd given function over the result maps ascii onto List[String], then flattens resulting List[List[Int]], returning List[Int] safeHeadOption // a natural transformation def safeHead[A]: List[A] => Option[A] = { case head::_ => Some(head) case Nil => None } // an effectful (Kleisli) function - def ascii(s:String): List[Int] = if(s.isEmpty) Nil else s.head.toInt :: ascii(s.tail) // another effectful function - def chars(n:Int): List[Char] = n.toString.toList // a pure function val length: String => Int = s => s.length List[Int] String Int ascii chars ascii compose chars List[Char] (flatMap chars) ∘ ascii flatMap chars = (flatMap chars) ∘ asciiascii compose chars ascii("Abc") == List(65,98,99) chars(65) == List('6','5') List[Char] ascii("Abc") == List(65,98,99) chars(65) == List('6','5') (ascii compose chars)("Abc") = List('6','5','9','8','9','9')
  • 17. def safeHead[A]: List[A] => Option[A] = { case head::_ => Some(head) case Nil => None } def ascii(s:String):List[Int] = if(s.isEmpty) Nil else s.head.toInt :: ascii(s.tail) def chars(n:Int):List[Char] = n.toString.toList assert(ascii("Abc") == List(65,98,99)) assert(chars(65) == List('6','5')) val listM = new Monad[List] { def map[A, B](f: A => B): List[A] => List[B] = { case head :: tail => f(head) :: map(f)(tail) case Nil => Nil } def unit[A](a: => A): List[A] = List(a) def join[A](mma: List[List[A]]): List[A] = mma match { case head::tail => head ::: join(tail) case Nil => Nil } } val optionM = new Monad[Option] { def map[A,B](f: A => B): Option[A] => Option[B] = { case Some(a) => Some(f(a)) case None => None } def unit[A](a: => A): Option[A] = Some(a) def join[A](mma: Option[Option[A]]): Option[A] = mma match { case Some(a) => a case None => None } } trait Functor[F[_]] { def map[A, B](f: A => B): F[A] => F[B] } trait Monad[F[_]] extends Functor[F] { def join[A](mma: F[F[A]]): F[A] def unit[A](a: => A): F[A] def flatMap[A,B](f: A => F[B]): F[A] => F[B] = (ma:F[A]) => join(map(f)(ma)) def compose[A,B,C](f: A => F[B], g: B => F[C]): A => F[C] = a => flatMap(g)(f(a)) } val length: String => Int = s => s.length val lengthLiftedOnce: List[String] => List[Int] = (listM map length) val lengthLiftedTwice: List[List[String]] => List[List[Int]] = listM map lengthLiftedOnce assert(length("abcd") == 4) assert(lengthLiftedOnce(List("abcd","efg","hi")) == List(4,3,2)) assert(lengthLiftedTwice(List(List("abcd","efg","hi"),List("jkl","mo","p"))) == List(List(4,3,2),List(3,2,1)))
  • 18. val computeAndThenTransform: List[List[String]] => List[Int] = (listM.join[Int](_)) compose lengthLiftedTwice val transformAndThenCompute: List[List[String]] => List[Int] = lengthLiftedOnce compose listM.join assert(computeAndThenTransform(List(List("abcd","efg","hi"),List("jkl","mo","p"))) == transformAndThenCompute(List(List("abcd","efg","hi"),List("jkl","mo","p")))) assert(computeAndThenTransform(List(List("abcd","efg","hi"),List("jkl","mo","p"))) == List(4,3,2,3,2,1)) assert(transformAndThenCompute(List(List("abcd","efg","hi"),List("jkl","mo","p"))) == List(4,3,2,3,2,1)) val computeAndThenTransform: List[String] => List[List[Int]] = ((x:List[Int]) => listM.unit(x)) compose lengthLiftedOnce val transformAndThenCompute: List[String] => List[List[Int]] = lengthLiftedTwice compose ((x:List[String]) => listM.unit(x)) assert(computeAndThenTransform(List("abcd","efg","hi")) == transformAndThenCompute(List("abcd","efg","hi"))) assert(computeAndThenTransform(List("abcd","efg","hi")) == List(List(4,3,2))) assert(transformAndThenCompute(List("abcd","efg","hi")) == List(List(4,3,2))) val computeAndThenTransform: String => List[Int] = ((x:Int) => listM.unit(x)) compose length val transformAndThenCompute: String => List[Int] = lengthLiftedOnce compose ((x:String) => listM.unit(x)) assert(computeAndThenTransform("abcd") == transformAndThenCompute("abcd")) assert(computeAndThenTransform("abcd") == List(4)) assert(transformAndThenCompute("abcd") == List(4)) List[String] List[int] String Int List[List[String]] List[List[Int]] List[String] List[int] join join unit length length↑L (length↑L)↑L (length↑L)↑L ∘ unit unit ∘length↑L unit unit unit length↑L ∘ unit unit ∘ length length↑L ∘ join join ∘(length↑L)↑L val computeAndThenTransform: List[String] => Option[Int] = safeHead compose (listM map length) val transformAndThenCompute: List[String] => Option[Int] = (optionM map length) compose safeHead assert(computeAndThenTransform(List("abc", "d", "ef")) == transformAndThenCompute(List("abc", "d", "ef"))) assert(computeAndThenTransform(List("abc", "d", "ef")) == Some(3)) assert(transformAndThenCompute(List("abc", "d", "ef")) == Some(3)) assert(computeAndThenTransform(List()) == transformAndThenCompute(List())) assert(computeAndThenTransform(List()) == None) assert(transformAndThenCompute(List()) == None) Option[String] Option[Int] safeHeadList length↑O length↑O∘ safeHeadList safeHeadOption ∘ length↑L safeHeadOption
  • 19. List[List[String]] List[List[Int]] List[String] List[int] List[String] List[Int] String join join (length↑L)↑L length↑L asciiascii ↑L length↑L ∘ join join ∘(length↑L)↑L flatMap ascii = join ∘ (map ascii) = join ∘ ascii↑L flatMap ascii map ascii maps ascii onto List[String], then flattens resulting List[List[Int]], returning List[Int] def ascii(s:String):List[Int] = if(s.isEmpty) Nil else s.head.toInt :: ascii(s.tail) assert(ascii("Abc") == List(65,98,99)) val mappedAscii: List[String] => List[List[Int]] = listM map ascii val flatMappedAscii: List[String] => List[Int] = listM flatMap ascii val compositionOfMappedAsciiAndJoin = (listM.join[Int](_)) compose mappedAscii assert( compositionOfMappedAsciiAndJoin(List("abcd","efg","hi")) == flatMappedAscii(List("abcd","efg","hi")) ) assert( compositionOfMappedAsciiAndJoin(List("abcd","efg","hi")) == List(97, 98, 99, 100,101,102,103,104,105)) assert( flatMappedAscii(List("abcd","efg","hi")) == List(97, 98, 99, 100,101,102,103,104,105))
  • 20. def ascii(s:String):List[Int] = if(s.isEmpty) Nil else s.head.toInt :: ascii(s.tail) def chars(n:Int):List[Char] = n.toString.toList assert(chars(65) == List('6','5')) assert(ascii("Abc") == List(65,98,99)) def flatMappedChars = listM flatMap chars def kleisliCompositionOfAsciiAndChars = listM.compose(ascii, chars) assert( kleisliCompositionOfAsciiAndChars("Abc") == (flatMappedChars compose ascii)("Abc")) assert( kleisliCompositionOfAsciiAndChars("Abc") == List('6','5','9','8','9','9')) assert( (flatMappedChars compose ascii)("Abc") == List('6','5','9','8','9','9')) calls ascii with a String, then flatMaps chars onto result List[Int] (producing a Char for each Int), returning result List[Char] List[Int] String Int ascii chars ascii compose chars List[Char] (flatMap chars) ∘ ascii flatMap chars = (flatMap chars) ∘ asciiascii compose chars List[Char]