why a monad is a monoid in the category of endofunctors

why a monad is a monoid in the category of endofunctors

Agenda

  • Category
  • Functor
  • Natural transformation
  • Bifunctor
  • Monoidal category
  • Monoid
  • Monad
  • Why a monad is ...

Bartosz Milewski

Category

  • objects
  • morphisms (arrows)
A
AA
B
BB
C
CC
f
ff
g
gg

Every object must have an identity morphism

id_A
idAid_A

A
AA
id_C
idCid_C

C
CC
id_B
idBid_B

B
BB

Morphisms must compose

A
AA
C
CC
g
gg
B
BB
f
ff
g \circ f
gfg \circ f

"g after f"

Composition must be associative

A
AA
C
CC
g
gg
B
BB
f
ff
g \circ f
gfg \circ f
D
DD
h
hh
h \circ g
hgh \circ g
h \circ (g \circ f) = (h \circ g) \circ f
h(gf)=(hg)fh \circ (g \circ f) = (h \circ g) \circ f

Example of a category: Set

\mathbb{N}
N\mathbb{N}
Bool
BoolBool
isEven
isEvenisEven
isLessThanFive
isLessThanFiveisLessThanFive
  • objects are sets
  • morphisms are functions between sets

Another example: Scala

Int
IntInt
String
StringString
length
lengthlength
  • objects are types
  • morphisms are Scala functions

Functor

  • Maps every object A to an object F(A)
  • Maps every morphism f: A -> B to a morphism F(f): F(A) -> F(B)
B
BB
A
AA
f
ff
F(B)
F(B)F(B)
F(A)
F(A)F(A)
F(f)
F(f)F(f)

Category C

Category D

Functor

Preserves identity:

B
BB
A
AA
f
ff
F(id_A) = id_{F(A)}
F(idA)=idF(A)F(id_A) = id_{F(A)}

Preserves composition:

F(g \circ f) = F(g) \circ F(f)
F(gf)=F(g)F(f)F(g \circ f) = F(g) \circ F(f)
C
CC
g
gg
g \circ f
gfg \circ f
F(B)
F(B)F(B)
F(A)
F(A)F(A)
F(f)
F(f)F(f)
F(C)
F(C)F(C)
F(g)
F(g)F(g)
F(g \circ f)
F(gf)F(g \circ f)

Endofunctor

A functor that maps from some category C

to the same category C

B
BB
A
AA
f
ff
F(B)
F(B)F(B)
F(A)
F(A)F(A)
F(f)
F(f)F(f)

Category C

(endo)functors in Scala

Pretty much anything with a map method

String
Int
length
"hello"
Option[String]
Option[Int]
Some("hello")
map(length)
5
Some(5)

Functors form a category

You can make a category Fun(C, D) of

all the functors between two categories C and D

 

  • objects are functors
  • morphisms are natural transformations

 

Can also have a category of endofunctors, Fun(C, C)

(in category theory, pretty much everything turns out to be a category)

Natural transformation

Given functors F and G from a category C to a category D, 

\eta: F \Rightarrow G
η:FG\eta: F \Rightarrow G

is a family of morphisms:

\eta_x : F(x) \rightarrow G(x)
ηx:F(x)G(x)\eta_x : F(x) \rightarrow G(x)

for each object x in C

such that

G(f) \circ \eta_x = \eta_y \circ F(f)
G(f)ηx=ηyF(f)G(f) \circ \eta_x = \eta_y \circ F(f)
F(x)
F(x)F(x)
F(f)
F(f)F(f)
F(y)
F(y)F(y)
G(x)
G(x)G(x)
G(y)
G(y)G(y)

"eta"

G(f)
G(f)G(f)
\eta_x
ηx\eta_x
\eta_y
ηy\eta_y
\forall f: x \rightarrow y \in C,
f:xyC,\forall f: x \rightarrow y \in C,

Natural transformations in Scala

trait NatTrans[F[_], G[_]] {

  def apply[A](fa: F[A]): G[A]

}

object OptToList extends NatTrans[Option, List] {

  def apply[A](fa: Option[A]): List[A] = fa match {
    case Some(a) => a :: Nil
    case None => Nil
  }

}

Recap

  • Category = objects + morphisms
    • every object has an identity morphism
    • morphisms compose associatively
  • Functor = mapping between categories
  • Endofunctor = mapping from a category to itself
  • Natural transformation = mapping between functors
  • Functors form a category

Bifunctor

A functor that takes a pair,

i.e. it maps some product category C x D to some category E

F: C \times D \rightarrow E
F:C×DEF: C \times D \rightarrow E
(C', D')
(C,D)(C', D')
(C, D)
(C,D)(C, D)
(f,g)
(f,g)(f,g)
F((C', D'))
F((C,D))F((C', D'))
F((C, D))
F((C,D))F((C, D))
F((f, g))
F((f,g))F((f, g))

Monoidal category

a.k.a tensor category

A category C with an associative bifunctor

\otimes: C \times C \rightarrow C
:C×CC\otimes: C \times C \rightarrow C

"tensor product"

and an object

I
II

"identity object"

"unit object"

that is both a left and right identity for

\otimes
\otimes
\forall x \in C, \otimes (I, x) = x
xC,(I,x)=x\forall x \in C, \otimes (I, x) = x
\forall x \in C, \otimes (x, I) = x
xC,(x,I)=x\forall x \in C, \otimes (x, I) = x

Monoid

In a monoidal category 

with tensor product

and identity object   

\otimes: C \times C \rightarrow C
:C×CC\otimes: C \times C \rightarrow C
I
II
C
CC

a monoid consists of:

  • an object 
  • a morphism
  • a morphism
\mu : M \otimes M \rightarrow M
μ:MMM\mu : M \otimes M \rightarrow M
\eta : I \rightarrow M
η:IM\eta : I \rightarrow M

"myu"

M
MM

"multiplication"

"eta"

"unit"

Monoids in Scala

trait Monoid[A] {
  def unit: A
  def multiply(a1: A, a2: A): A
}

object IntWithAddition extends Monoid[Int] {
  def unit: Int = 0
  def multiply(a1: Int, a2: Int): Int = a1 + a2
}

object IntWithMultiplication extends Monoid[Int] {
  def unit: Int = 1
  def multiply(a1: Int, a2: Int): Int = a1 * a2
}

Monad

A monad in a category C consists of:

  • An endofunctor 
  • A natural transformation 
  • A natural transformation
T: C \rightarrow C
T:CCT: C \rightarrow C
\mu : (T \circ T) \Rightarrow T
μ:(TT)T\mu : (T \circ T) \Rightarrow T
\eta : 1_C \Rightarrow T
η:1CT\eta : 1_C \Rightarrow T

"myu"

"join"

identity functor

"eta"

"return"

such that

\mu \circ T\mu = \mu \circ \mu T
μTμ=μμT\mu \circ T\mu = \mu \circ \mu T
\mu \circ T\eta = \mu \circ \eta T = 1_{T}
μTη=μηT=1T\mu \circ T\eta = \mu \circ \eta T = 1_{T}

(associativity law)

(left and right identity laws)

Monads in Scala

trait Monad[F[_]] extends Functor[F] {
  def unit(a: A): F[A]
  def join(ffa: F[F[A]]): F[A]

  def flatMap(fa: F[A])(f: A => F[A]): F[A] = 
    join(fa.map(f))
}

object MonadForList extends Monad[List] {

  def unit(a: A): List[A] = List(a)

  def join(lists: List[List[A]]) = lists.flatten
 
}

Recap

  • Bifunctor
    • functor that takes 2 arguments
  • Monoidal category
    • category with a bifunctor    
    • and a unit object
  • Monoid
    • object in monoidal category
    • multiplication morphism 
    • unit morphism
  • Monad
    • endofunctor
    • natural transformation
    • natural transformation
F: C \times D \rightarrow E
F:C×DEF: C \times D \rightarrow E
\otimes
\otimes
I
II
\mu
μ\mu
\eta
η\eta

"myu"

"eta"

\mu
μ\mu
\eta
η\eta

Fun[C,C]

Category of endofunctors for category C

  • objects are endofunctors
  • morphisms are natural transformations

It's a monoidal category!

  •    = functor composition (           )
  •    = identity functor (     )
\otimes
\otimes
I
II
F \circ G
FGF \circ G
1_C
1C1_C

Monoids in Fun[C,C]

What does a monoid look like in this category?

  • object 
  • morphism 
  • morphism
\mu : M \otimes M \rightarrow M
μ:MMM\mu : M \otimes M \rightarrow M
\eta : I \rightarrow M
η:IM\eta : I \rightarrow M
\mu : T \circ T \Rightarrow T
μ:TTT\mu : T \circ T \Rightarrow T
\eta : 1_C \Rightarrow T
η:1CT\eta : 1_C \Rightarrow T

Monoid in general

Monoid in Fun[C,C]

  • endofunctor 
  • nat trans 
  • nat trans
M
MM
T
TT

Hang on, that looks like...

\mu : T \circ T \Rightarrow T
μ:TTT\mu : T \circ T \Rightarrow T
\eta : 1_C \Rightarrow T
η:1CT\eta : 1_C \Rightarrow T

Monad

  • endofunctor 
  • nat trans 
  • nat trans
T
TT
\mu : T \circ T \Rightarrow T
μ:TTT\mu : T \circ T \Rightarrow T
\eta : 1_C \Rightarrow T
η:1CT\eta : 1_C \Rightarrow T

Monoid in Fun[C,C]

  • endofunctor 
  • nat trans 
  • nat trans
T
TT
\blacksquare
\blacksquare

why a monad is a monoid in the category of endofunctors

By Chris Birchall

why a monad is a monoid in the category of endofunctors

  • 3,063