Let's ask GHC what the types are for some of the subexpressions.
> :t putStrLn . show
putStrLn . show :: (Show a) => a -> IO ()
That's certainly as expected.
> :t return 5 >>= f >>= f
return 5 >>= f >>= f :: [Int]
I suppose we expected that, but it doesn't answer your question. Next, a quick reminder on how that expression parses:
> :i (>>=)
class Monad m where
(>>=) :: m a -> (a -> m b) -> m b
...
infixl 1 >>=
Okay, it's left associative, so the expression is (return 5 >>= f) >>= f
.
> :t return 5 >>= f
return 5 >>= f :: [Int]
Comparing this to the above type signature for (>>=)
, we can observe two things:
- The second argument of
(>>=)
must return some sort of monad
- The first argument of
(>>=)
must be a value in the same monad
So we know that f
has to have a type shaped like (a -> m b)
here, and the actual type signature for f
is Int -> [Int]
. So we can manually combine the types:
Note that ([] a)
means the same thing as [a]
.
So the monad is indeed the list monad. So what's going on?
> return 5 :: ([] Int)
[5]
> [5] >>= f
[6, 10]
> ([5] >>= f) >>= f
[7, 12, 11, 20]