TL;DR: We use the ((->) r
monad instance inbetween.
We have to look at (.) (>>=)
. So let us first repeat the types:
(>>=) :: Monad m => m a -> ((a -> m b) -> m b)
(.) :: (y -> z ) -> (x -> y) -> (x -> z)
Therefore, we have
(.) (>>=) :: Monad m => (x -> m a) -> (x -> ((a -> m b) -> m b))
-- or, with less parentheses
(.) (>>=) :: Monad m => (x -> m a) -> x -> (a -> m b) -> m b
Now, we plug in another (>>=)
:
(.) (>>=) :: Monad m => (x -> m a ) -> x -> (a -> m b) -> m b
(>>=) :: Monad k => k i -> ((i -> k j) -> k j)
But now we have a problem. We have Monad m => m a
and ((i -> k j) -> k j)
at the same position. Is that even possible? Well, it's possible if there is a monad instance for
Monad k => (->) (i -> k j)
Turns out there is one, namely
instance Monad ((->) r)
for any r
.
Now our outer monad m
is ((->) (i -> k j)
, therefore we replace all occurences of m
by (i -> k j) ->
:
(.) (>>=) :: (x -> (i -> k j) -> a) -> x -> (a -> (i -> k j) -> b) -> (i -> k j) -> b
(>>=) :: Monad k => k i -> ((i -> k j) -> k j)
Now set x ~ k i
, a ~ k j
and we end up with
(.) (>>=) :: (x -> (i -> k j) -> a) -> x -> (a -> (i -> k j) -> b) -> (i -> k j) -> b
(>>=) :: Monad k => k i -> ((i -> k j) -> k j)
(>>=) . (>>=) :: Monad k => k i -> (k j -> (i -> k j) -> b) -> (i -> k j) -> b
Last, we rename k
to m
, i
to a
and j
to b2
, and we end up with
(>>=) . (>>=) :: Monad m => m a -> (m b2 -> (a -> m b2) -> b) -> (a -> m b2) -> b