I have recently started learning Haskell, and I was trying to do the following function composition (join . mapM
) but got some weird types out of this function that I don't understand. I thought that either GHC would assume that t == m
in the mapM
type and the output of mapM
would become m (m b)
which would be join-able or it would not and this would error out because of type mismatch. Instead the following happened:
mapM :: (Traversable t, Monad m) => (a -> m b) -> t a -> m (t b)
join :: Monad m => m (m a) -> m a
join . mapM :: Traversable t => (a -> t a -> b) -> t a -> t b
I don't understand how this is possible. The way I understand it, function composition should use the inputs of the first (or the second depending how you look at it) function and the outputs of the second function. But here the expected input function for mapM
changes from a unary function to a binary function and I have no clue why. Even if GHC can't just make the assumption that t == m
like I did, which I half expected, it should error out because of type mismatch, not change the input function type, right? What is happening here?
liftM
, akafmap
, seems unrelated to this composition). But in short, the output ofmapM
is a functiont a -> m (t b)
, andjoin
needs a monadic value of the formm ( m c)
as input. The only way for these types to unify is for the Monadm
to be the function typet a -> b
, wheret
anda
are fixed. (It's actually rather surprising to me that this works at all, but the types all match up.) – Robin Zigmond(->) t a
, whose values are functions with inputt a
. (Sometime I wonder why Haskell has both a direct Monad instance for "functions with a fixed input", and one called the "reader monad" which is exactly the same but in anewtype
wrapper. I think it would work better without the "unwrapped" version having a monad/applicative instance - but I'm getting off topic...) – Robin ZigmondmapM
ist a -> m (t b)
. Ifm
is the monad(->) (t a)
then that's the same ast a - > t a -> t b
- orm (m (t b))
for the same monad.join
turns that intom (t b)
, ort a -> t b
. – Robin Zigmond