Monads
To start off, we have to understand that a Monad is not state
, impure
, imperative sequencing
and so on. It can be used to model these, but it isn’t defined as those things.
We can think of it as a pattern we observe.
In the context of Haskell, when a certain type we use obeys monadic laws, we can call it a monad.
There are 3 laws a monad has to obey:
Law | definition (>>=) | definition (>=>) | definition join / j |
---|---|---|---|
left identity | return a >>= f = f a | return >=> g == g | join . return == id |
right identity | m >>= return = m | f >=> return == f | join . fmap pure == id |
associativity | (m >>= f) >>= g = m >>= (\x -> fx >>= g) | f >=> (g >=> h) | j . fmap j = j . j |
A way to gain intuition if something is a monad is to gain intuition for these laws.
Recognize if a type follows these laws.
Let’s see some of the things that Monads
allow us to do:
It allows us to wrap some value, a
within a monadic context:
return :: a -> m a
It allows us to compose functions which return values wrapped in monadic contexts:
(>=>) :: (a -> m b) -> (b -> m c) -> (a -> m c)
It allows us to collapse contexts.
join :: m (m a) -> m a
It allows us to apply a function a -> m b
to a value, a
within a context m
and combine the contexts (one from m a
one from m b
).
(>>=) :: m a -> (a -> m b) -> m b
So where is this pattern useful?
Some examples:
- Writer Monad (To write values)
- Reader Monad (To read values)
- State Monad (I can do both!)
References: Bartosz milewski - Monads Haskell wiki - Monad laws Stephen Diehl - Eightfold path to monad satori