|
|
|
|
|
by _jackdk_
443 days ago
|
|
I agree. The "container" intuition for Monads leaves you stuck when you try to contemplate IO (or even Promises, these days), because the "bind" operator looks like it does something impossible: extract "the" `a` from the `IO a`, when you have no idea what it is. (Trust me, I spent a long time stuck at this point.) Better to think of Monad as "Applicative + join" (you need Applicative to get `pure`). If you think of Monads in terms of `fmap` + `join :: Monad m => m (m a) -> m a`, then you don't need to imagine an "extraction" step and your intuition is correct across more instances. Understanding `join` gives you an intuition that works for all the monads I can think of, whereas the container intuition only works for `Maybe` or `Either e` (not even `[]`, even though it _is_ a container). You can define each of `>>=`/`join`/`>=>` in terms of `pure` + any of the other two, and it is an illuminating exercise to do so. (That `class Monad` defines `>>=` as its method is mostly due to technical GHC reasons rather than anything mechanical.) |
|
One does wonder about the alternate world where that was the primary way people interacted with it.