Skip to content

Instantly share code, notes, and snippets.

@ryan-williams
Last active March 14, 2020 19:51
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ryan-williams/7aa726291301633fa795a9712ed514d5 to your computer and use it in GitHub Desktop.
Save ryan-williams/7aa726291301633fa795a9712ed514d5 to your computer and use it in GitHub Desktop.
Attempt to articulate an intuitive understanding about why "a monad is a monoid in the category of endofunctors"™️

a monad is just a monoid in the category of endofunctors

Monoid

A monoid has two components:

id (or empty)

"make an instance from nothing"

  • 0 (Unit => Int)
  • "" (Unit => String)
  • Nil (Unit => List[_])

combine (|+|)

  • "combine two instances"
  • (T,T) => T (summation, reduction)

Monad

A monad has two components:

bind (similar to monoid's id/empty)

T => F[T]:

  • "make an F from thin air"

flatMap

(F[A], A => F[B]) => F[B]

At first, that type signature makes people think of:

(F[A], A => F[B]) => F[F[B]]

Note the doubly nested F in the result; this is what you'd naively get from a Functor map.

Each Monad's special essence is: how does it flatten (i.e. F[F[B]] => F[B])?

  • List: make one list by concatenating all elems
  • Future: keep kicking the "deferred" can down the road
  • Option: each level of nesting can always short-circuit the whole thing to None
  • etc.

Turning F[F[B]] into F[B] is like combining two [nested levels of F[_]] into one, which sounds a lot like monoidal combine above.

So a monad is like a higher-level monoid in some way:

  • idbind
  • combineflatMap

Monad.bind actually goes from Id[T] => F[T]

  • it's a "natural transformation": Id ~> F
  • it creates an F from "nothing" (Id)

Monad.bind actually goes from F⊙F [T] => F[T]

  • it's a "natural transformation (F,F) -> F
  • it combines two Fs into one

👋👋👋👋👋

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment