× {{alert.msg}} Never ask again
Get notified about new tutorials RECEIVE NEW TUTORIALS

Refactoring to an applicative style in Haskell

Mouna Cheikhna
Nov 20, 2016
<p>with this parser code with do-notation:</p> <p> </p> <pre><code class="language-python">p_hex :: CharParser () Char p_hex = do char '%' a &lt;- hexDigit b &lt;- hexDigit let ((d, _):_) = readHex [a,b] return . toEnum $ d </code></pre> <p><br> we can refactor with applicative to make it much shorter and more clear:</p> <pre><code class="language-javascript">a_hex = hexify &lt;$&gt; (char '%' *&gt; hexDigit) &lt;*&gt; hexDigit where hexify a b = toEnum . fst . head . readHex $ [a,b]</code></pre> <p>onother example : </p> <pre><code class="language-python">do a &lt;- e1 b &lt;- e2 c &lt;- e3 return (f a b c)</code></pre> <p><br> can be refactored to: </p> <pre><code class="language-python">f &lt;$&gt; e1 &lt;*&gt; e2 &lt;*&gt; e3</code></pre> <p>or <br>  </p> <pre><code class="language-python">liftA3 e1 e2 e3 </code></pre> <p>generaly here's a method to switch from Monads to applicative style:<br> Start using liftM, liftM2, etc or ap where you can, in place of do/(&gt;&gt;=). </p> <pre><code class="language-python">do x &lt;- fx y &lt;- fy return (g x y)</code></pre> <p><br> It can be rewritten to liftM2 g fx fy. In general, whenever the choice or construction of monadic <br> actions does not depend on the outcomes of previous monadic actions, then it should be possible to rewrite everything with liftM.<br> When you notice you're only using those monad methods, then import Control.Applicative and replace return with pure, liftM with (&lt;$&gt;)<br> (or fmap or liftA), liftM2 with liftA2, etc, and ap with (&lt;*&gt;). <br> If your function signature was Monad m =&gt; ..., change to Applicative m =&gt; ... (and maybe rename m to f or whatever).</p>
comments powered by Disqus