A monoid has two components:
"make an instance from nothing"
0(Unit => Int)""(Unit => String)Nil(Unit => List[_])
- "combine two instances"
(T,T) => T(summation, reduction)
A monad has two components:
T => F[T]:
- "make an F from thin air"
(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 elemsFuture: keep kicking the "deferred" can down the roadOption: each level of nesting can always short-circuit the whole thing toNone- 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:
id→bindcombine→flatMap
Monad.bind actually goes from Id[T] => F[T]
- it's a "natural transformation":
Id ~> F - it creates an
Ffrom "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
👋👋👋👋👋
