While (>>=)
can sometimes be useful when used directly, its main purpose is to implement the <-
bind syntax in do notation. It has the type m a -> (a -> m b) -> m b
mainly because, when used in a do notation block, the right hand side of the <-
is of type m a
, the left hand side "binds" an a
to the given identifier and, when combined with remainder of the do block, is of type a -> m b
, the resulting monadic action is of type m b
, and this is the only type it possibly could have to make this work.
For example:
echo = do
input <- getLine
putStrLn input
The right hand side of the <-
is of type IO String
The left hands side of the <-
with the remainder of the do block are of type String -> IO ()
. Compare with the desugared version using >>=
:
echo = getLine >>= (\input -> putStrLn input)
The left hand side of the >>=
is of type IO String
. The right hand side is of type String -> IO ()
. Now, by applying an eta reduction to the lambda we can instead get:
echo = getLine >>= putStrLn
which shows why >>=
is sometimes used directly rather than as the "engine" that powers do notation along with >>
.
I'd also like to provide what I think is an important correction to the concept of "unwrapping" a monadic value, which is that it doesn't happen. The Monad class does not provide a generic function of type Monad m => m a -> a
. Some particular instances do but this is not a feature of monads in general. Monads, generally speaking, cannot be "unwrapped".
Remember that m >>= k = join (fmap k m)
is a law that must be true for any monad. Any particular implementation of >>=
must satisfy this law and so must be equivalent to this general implementation.
What this means is that what really happens is that the monadic "computation" a -> m b
is "lifted" to become an m a -> m (m b)
using fmap and then applied the m a
, giving an m (m b)
; and then join :: m (m a) -> m a
is used to squish the two m
s together to yield a m b
. So the a
never gets "out" of the monad. The monad is never "unwrapped". This is an incorrect way to think about monads and I would strongly recommend that you not get in the habit.