Nick Bowler nbowler at elliptictech.com
Fri Jul 23 15:05:41 EDT 2010

```On 11:43 Fri 23 Jul     , michael rice wrote:
> Hi,
>
> I don't understand what's taking place here.
>
> >From Hoogle:
>
> =================
>
> liftM2 :: Monad  m => (a1 -> a2 -> r) -> m a1 -> m a2 -> m r
>
> Promote a function to a monad, scanning the monadic arguments from left to right. For example,
>
>     liftM2 (+) [0,1] [0,2] = [0,2,1,3]
>     liftM2 (+) (Just 1) Nothing = Nothing
>
> =================
>
> What does it mean to "promote a function to a monad?"

Consider fmap, which 'promotes a function to a functor':

fmap :: Functor f => (a -> b) -> f a -> f b

This might be easier to understand if you fully parenthesise this:

fmap :: Functor f => (a -> b) -> (f a -> f b)

In other words, fmap takes a function on ordinary values as input, and
outputs a function on a particular Functor.

Now consider liftM, which 'promotes a function to a monad':

liftM :: Monad m => (a -> b) -> m a -> m b

Hey, this looks almost the same as fmap (it is)!  Now, monads have
additional structure which allows us to promote more complicated
functions, for example:

liftM2 :: Monad m => (a -> b -> c) -> m a -> m b -> m c

which, when fully parenthesised, looks like

liftM2 :: Monad m => (a -> b -> c) -> (m a -> m b -> m c)

What we have now is that we can promote a 'two argument' function to
Monads (this is not possible on mere Functors, hence there's no fmap2).

> It would seem that the monad values must understand the function
> that's being promoted, like Ints understand (+).

Yes, liftM2 (+) gives you a new function with type

(Num a, Monad m) => m a -> m a -> m a

> But how does one add [0,1] and [0,2] to get [0,2,1,3]?

liftM2 (+) [0,1] [0,2] gives the list

[0+0, 0+2, 1+0, 1+2]

(recall that (>>=) in the list monad is concatMap).

--
Nick Bowler, Elliptic Technologies (http://www.elliptictech.com/)
```