<div class="gmail_quote">Your code examples are:</div><div class="gmail_quote"><br></div><div class="gmail_quote">On Sat, Jun 27, 2009 at 6:07 PM, Edward Ing <span dir="ltr">&lt;<a href="mailto:edward.ing@gmail.com">edward.ing@gmail.com</a>&gt;</span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">saveFile n =<br>
   do          cont &lt;- (liftM fromJust) $ getInputFPS &quot;file&quot;<br>
        let f = uploadDir ++ &quot;/&quot; ++ basename n<br>
        liftIO $ BS.writeFile f cont<br>
        return $ paragraph &lt;&lt; (&quot;Saved as &quot; +++ anchor ! [href f] &lt;&lt; f +++ &quot;.&quot;)</blockquote><div><br></div><div>Vs.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">

saveFile n =<br>
do   cont &lt;- getInputFPS &quot;file&quot;<br>
       let f = uploadDir ++ &quot;/&quot; ++ basename n<br>
      liftIO $ BS.writeFile f (fromJust cont)<br>
      return $ paragraph &lt;&lt; (&quot;Saved as &quot; +++ anchor ! [href f] &lt;&lt; f +++ &quot;.&quot;)<br></blockquote></div><br><div>Consider the line x &lt;- y in a do expression.  If y has type M a for some monad M, then x has type a.</div>
<div><br></div><div>So, let&#39;s say you have a value f :: Maybe Int, and you want to return the Int&#39;s stringification if it exists.  We can write this in these two ways:</div><div><br></div><div>do x &lt;- f</div><div>
   return (show x)</div><div><br></div><div>do x &lt;- liftM show f</div><div>   return x</div><div><br></div><div>liftM :: (a -&gt; b) -&gt; (M a -&gt; M b)   for any monad M.  That means if you want to apply a function to a value which is currently wrapped in a monad constructor, you need to &quot;lift&quot; it in.  liftM takes a function on ordinary values to a function on wrapped values.  But <i>after</i> you bind, you don&#39;t need to lift anymore.</div>
<div><br></div><div>Which of the two above styles to choose is a matter of style, and, in my code at least, varies from situation to situation.</div><div><br></div><div>That said, you can write both of these snippets as &quot;fmap show f&quot; or &quot;show &lt;$&gt; f&quot;  (where (&lt;$&gt;) is from Control.Applicative), which is how it would be done in practice.</div>
<div><br></div><div>Does that make sense?</div><div>Luke</div>