<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>&lt;jurgen.doser@gmail.com&gt;</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 &lt;jurgen.doser@gmail.com&gt;<br>Subject: Re: [Haskell-cafe] Heavy lift-ing<br>To: "michael rice" &lt;nowgate@yahoo.com&gt;<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>&gt; On 11:43 Fri 23 Jul&nbsp; &nbsp;&nbsp;&nbsp;, michael rice wrote:<br>&gt; [...]<br>&gt; &gt; But how does one add [0,1] and [0,2] to get [0,2,1,3]?<br>&gt; <br>&gt;
 liftM2 (+) [0,1] [0,2] gives the list<br>&gt; <br>&gt;&nbsp;&nbsp;&nbsp;[0+0, 0+2, 1+0, 1+2]<br><br>which one could have found out by asking ghci:<br><br>Prelude Control.Monad&gt; let f a b = show a ++ " + " ++ show b<br>Prelude Control.Monad&gt; liftM2 f [0,1] [0,2]<br>["0 + 0","0 + 2","1 + 0","1 + 2"]<br><br>or simpler:<br><br>Prelude Control.Monad&gt; 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>&gt; (recall that (&gt;&gt;=) in the list monad is concatMap).<br><br>(&gt;&gt;=) = flip concatMap, to be precise. Or, concatMap = (=&lt;&lt;)<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>&nbsp; &nbsp; = { definition of liftM2 }<br><br>do {x &lt;- a; y &lt;- b; return (f x y)}<br><br>&nbsp; &nbsp; = { simplified translation
 of do-notation }<br><br>a &gt;&gt;= \x -&gt; (b &gt;&gt;= \y -&gt; return (f x y))<br><br>&nbsp; &nbsp; = { change (&gt;&gt;=) to (=&lt;&lt;) and flip arguments }<br><br>(\x -&gt; ((\y -&gt; return (f x y)) =&lt;&lt; b)) =&lt;&lt; a <br><br>&nbsp; &nbsp; = { specialized to the list monad }<br><br>(\x -&gt; ((\y -&gt; [f x y])) `concatMap` b)) `concatMap` a <br><br>&nbsp; &nbsp; = { change concatMap to prefix application }<br><br>concatMap (\x -&gt; concatMap (\y -&gt; [x+y]) b) a<br><br>and indeed:<br><br>Prelude&gt; concatMap (\x -&gt; concatMap (\y -&gt; [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>&nbsp; &nbsp; = { definition }<br><br>do { x &lt;- a ; return f a }<br>&nbsp; <br>&nbsp; &nbsp; = { same changes as above
 }<br><br>concatMap (\x -&gt; [f x]) a<br><br>&nbsp; &nbsp; = { definition of concatMap }<br><br>concat (map (\x -&gt; [f x]) a<br><br>&nbsp; &nbsp; = { concating singletons can be simplified } <br><br>map (\x -&gt; f x) a<br><br>&nbsp; &nbsp; = { 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 -&gt; concatMap (\y -&gt; [x+y]) b) a<br><br>&nbsp; &nbsp; = { see above }<br><br>concatMap (\x -&gt; map (\y -&gt; x+y) b) a<br><br>&nbsp; &nbsp; = { use operator section }<br><br>concatMap (\x -&gt; map (x+) b) a<br><br>which is about as clear as possible a definition for liftM2 (+)<br><br><br>&nbsp;&nbsp;&nbsp; Jürgen<br><br><br><br></div></blockquote></td></tr></tbody></table></div></td></tr></table><br>