[Haskell-beginners] Re: Pointfree expeiments
Daniel Schoepe
daniel.schoepe at googlemail.com
Thu Nov 25 07:40:52 EST 2010
Paul Sargent <psarge at gmail.com> writes:
> Digging a little deeper, I decided to look at the definition of ap:
>
> ap = liftM2 id
>
> liftM2 :: (Monad m) => (a1 -> a2 -> r) -> m a1 -> m a2 -> m r
> liftM2 f m1 m2 = do { x1 <- m1; x2 <- m2; return (f x1 x2) }
>
> liftM2 makes sense to me, but again we seem to have a mismatch of types. liftM2 wants a two argument function for it's first argument, but ap provides id. I'm finding myself tumbling further and further down the rabbit hole.
>
id has type a -> a, so if you "instantiate" a to `a2 -> r', you get:
id :: (a2 -> r) -> (a2 -> r)
Since -> is right-associative this is the same as:
id :: (a2 -> r) -> a2 -> r
So that's how id can be seen as a two-argument function in this
case. That results in liftM2 id having the type:
liftM2 id :: (Monad m) => m (a2 -> r) -> m a2 -> m r
If you now insert the Reader monad for m, you get:
liftM2 id :: (s -> a2 -> r) -> (s -> a2) -> (s -> r)
So appying (liftM2 id), which is ap, to (+), causes s, a2 and r to be
the same type, since (+) has type (Num a) => a -> a -> a.
liftM2 id (+) :: Num a => (a -> a) -> a -> a
If you then apply that to id, as in ap (+) id, you get:
ap (+) id = liftM2 id (+) id :: Num a => a -> a
So this explains the type, and if you then expand the definitions of
liftM2 and >>= and return for the Reader monad, you will see that this
corresponds to \x -> x + x.
Regards,
Daniel
More information about the Beginners
mailing list