# [Haskell-beginners] How does the type of "ap = liftM2 id" work?

Tillmann Rendel rendel at daimi.au.dk
Fri Aug 22 15:02:12 EDT 2008

```Quergle Quergle wrote:
> I'm a bit perplexed by what it means to do something like "ap = liftM2 id"
>
>   liftM2 :: (Monad m) => (a1 -> a2 -> r) -> m a1 -> m a2 -> m r
>   id :: a -> a
>   liftM2 id :: (Monad m) => m (a2 -> r) -> m a2 -> m r
>
> My intuitive understanding is that liftM2 is expecting a two-argument
> function as its first argument, so it seems a little unexpected to
> pass it "id", a one-argument function. And I can't really see how the
> type signature of "liftM2 id" is derived from "liftM2" and "id". Any
> help much appreciated!

Polymorphic values in Haskell have more then one type. Lets try to
figure out a type of the id in liftM2 id. From the type signature of id,
we know that it has to be a -> a for some a. From the type signature of
liftM2, we know that is has to be a1 -> a2 -> r for some a1, a2 and r.
Since a1 -> a2 -> r is a1 -> (a2 -> r), we have

(a -> a) == a1 -> (a2 -> r)

and therefore

a == a1 == a2 -> r.

If we substitute a2 -> r for both a and a1 in the types of id and
liftM2, we see why liftM2 id is well-typed and one of its types:

id :: (a2 -> r) -> (a2 -> r)
liftM2 :: ((a2 -> r) -> (a2 -> r)) -> m (a2 -> r) -> m a2 -> m r
liftM2 id :: m (a2 -> r) -> m a2 -> mr

If you have problems with understand ap = liftM2 id, you may want to
look into (\$) = id first.

Tillmann
```