<table cellspacing="0" cellpadding="0" border="0" ><tr><td valign="top" style="font: inherit;"><div id="yiv1785775733"><table id="yiv1785775733bodyDrftID" class="yiv1785775733" border="0" cellpadding="0" cellspacing="0"><tbody><tr><td id="yiv1785775733drftMsgContent" style="font: inherit;">Thanks all,<br><br>Wild, at least up to the "optional" part, which I haven't dug into yet.<br><br>So the (+) for the Maybe monad and the (+) for the List monad are one in the same, the magic springs from the monads.<br><br>Why is it called "lift"-ing?<br><br>Michael<br><br><br>--- On <b>Fri, 7/23/10, Jürgen Doser <i><jurgen.doser@gmail.com></i></b> wrote:<br><blockquote style="border-left: 2px solid rgb(16, 16, 255); margin-left: 5px; padding-left: 5px;"><br>From: Jürgen Doser <jurgen.doser@gmail.com><br>Subject: Re: [Haskell-cafe] Heavy lift-ing<br>To: "michael rice" <nowgate@yahoo.com><br>Cc: haskell-cafe@haskell.org<br>Date: Friday, July 23,
2010, 4:50 PM<br><br><div class="yiv1785775733plainMail">El vie, 23-07-2010 a las 15:05 -0400, Nick Bowler escribió:<br>> On 11:43 Fri 23 Jul , michael rice wrote:<br>> [...]<br>> > But how does one add [0,1] and [0,2] to get [0,2,1,3]?<br>> <br>>
liftM2 (+) [0,1] [0,2] gives the list<br>> <br>> [0+0, 0+2, 1+0, 1+2]<br><br>which one could have found out by asking ghci:<br><br>Prelude Control.Monad> let f a b = show a ++ " + " ++ show b<br>Prelude Control.Monad> liftM2 f [0,1] [0,2]<br>["0 + 0","0 + 2","1 + 0","1 + 2"]<br><br>or simpler:<br><br>Prelude Control.Monad> liftM2 (,) [0,1] [2,3]<br>[(0,2),(0,3),(1,2),(1,3)]<br><br>i.e., the in the list monad, you pair each element of one list with each<br>element of the other(s).<br><br>> (recall that (>>=) in the list monad is concatMap).<br><br>(>>=) = flip concatMap, to be precise. Or, concatMap = (=<<)<br><br>Now let's have some fun with equational reasoning to see what liftM2<br>does exactly: (Only read this if you really want to!)<br><br>liftM2 f a b <br><br> = { definition of liftM2 }<br><br>do {x <- a; y <- b; return (f x y)}<br><br> = { simplified translation
of do-notation }<br><br>a >>= \x -> (b >>= \y -> return (f x y))<br><br> = { change (>>=) to (=<<) and flip arguments }<br><br>(\x -> ((\y -> return (f x y)) =<< b)) =<< a <br><br> = { specialized to the list monad }<br><br>(\x -> ((\y -> [f x y])) `concatMap` b)) `concatMap` a <br><br> = { change concatMap to prefix application }<br><br>concatMap (\x -> concatMap (\y -> [x+y]) b) a<br><br>and indeed:<br><br>Prelude> concatMap (\x -> concatMap (\y -> [x+y]) [0,2]) [0,1]<br>[0,2,1,3]<br><br>with some effort, I think one can understand what happens here. It<br>should also be clear how this is generalized to liftM3, liftM4, etc. <br><br>Oh, btw, what about liftM1? Obviously, this should be the following:<br><br>liftM1 f a<br><br> = { definition }<br><br>do { x <- a ; return f a }<br> <br> = { same changes as above
}<br><br>concatMap (\x -> [f x]) a<br><br> = { definition of concatMap }<br><br>concat (map (\x -> [f x]) a<br><br> = { concating singletons can be simplified } <br><br>map (\x -> f x) a<br><br> = { eta-reduction }<br><br>map f a<br><br>i.e., liftM1 = map, which is indeed just fmap for lists, as already<br>pointed out.<br><br>You can use this to simplify the last line of the concatMap derivation<br>above:<br><br>concatMap (\x -> concatMap (\y -> [x+y]) b) a<br><br> = { see above }<br><br>concatMap (\x -> map (\y -> x+y) b) a<br><br> = { use operator section }<br><br>concatMap (\x -> map (x+) b) a<br><br>which is about as clear as possible a definition for liftM2 (+)<br><br><br> Jürgen<br><br><br><br></div></blockquote></td></tr></tbody></table></div></td></tr></table><br>