<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">
    <channel>
        <title>Roman Cheplyaka: articles</title>
        <link>http://ro-che.info/articles/</link>
        <description />
        
        <lastBuildDate>Mon, 02 Jan 2012 00:00:00 UT</lastBuildDate>
        <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/RomanCheplyaka" /><feedburner:info uri="romancheplyaka" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
    <title>Composing monadic effects</title>
    <link>http://feedproxy.google.com/~r/RomanCheplyaka/~3/1r24GsS15Nw/2012-01-02-composing-monads.html</link>
    <description>&lt;p&gt;In Haskell, monad transformers are used to combine effects provided by multiple monads.&lt;/p&gt;
&lt;h2 id="boring-example-writer-reader-state"&gt;Boring example: Writer, Reader, State&lt;/h2&gt;
&lt;p&gt;For instance, if we want to have a read-only environment plus a write-only logging facility, we can start with the Reader monad and add a logging facility to it with the WriterT monad transformer:&lt;/p&gt;
&lt;pre class="sourceCode"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span class="kw"&gt;type&lt;/span&gt; &lt;span class="dt"&gt;MyMonad&lt;/span&gt; w r a &lt;span class="fu"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;WriterT&lt;/span&gt; w (&lt;span class="dt"&gt;Reader&lt;/span&gt; r) a&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Or, we could start with the Writer monad and put the ReaderT transformer on top of it:&lt;/p&gt;
&lt;pre class="sourceCode"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span class="kw"&gt;type&lt;/span&gt; &lt;span class="dt"&gt;MyMonad&lt;/span&gt; w r a &lt;span class="fu"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;ReaderT&lt;/span&gt; r (&lt;span class="dt"&gt;Writer&lt;/span&gt; w) a&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In the end, it doesn’t matter which way we choose, as both are isomorphic to&lt;/p&gt;
&lt;pre class="sourceCode"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span class="kw"&gt;type&lt;/span&gt; &lt;span class="dt"&gt;MyMonad&lt;/span&gt; w r a &lt;span class="fu"&gt;=&lt;/span&gt; r &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; (a, w)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If we want to have a state as well, we can plug in the StateT transformer anywhere in the stack, and again the order doesn’t matter. The resulting monad is now isomorphic to the standard &lt;a href="http://hackage.haskell.org/packages/archive/transformers/latest/doc/html/Control-Monad-Trans-RWS-Lazy.html"&gt;RWS&lt;/a&gt; (Reader-Writer-State) monad.&lt;/p&gt;
&lt;p&gt;So, we say about those transformers that they &lt;em&gt;commute&lt;/em&gt; (recall that Reader is just the ReaderT transformer applied to the Identity monad).&lt;/p&gt;
&lt;h2 id="more-interesting-example-either-writer"&gt;More interesting example: Either + Writer&lt;/h2&gt;
&lt;p&gt;Not every two transformers commute, though.&lt;/p&gt;
&lt;p&gt;Suppose we want to write log messages, plus to be able to abort the computation.&lt;/p&gt;
&lt;p&gt;There are two quite different ways to compose these effects.&lt;/p&gt;
&lt;p&gt;There’s&lt;/p&gt;
&lt;pre class="sourceCode"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span class="kw"&gt;type&lt;/span&gt; &lt;span class="dt"&gt;MyMonad&lt;/span&gt; e w a &lt;span class="fu"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;ErrorT&lt;/span&gt; e (&lt;span class="dt"&gt;Writer&lt;/span&gt; w) a&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;isomorphic to &lt;code class="sourceCode haskell"&gt;(&lt;span class="dt"&gt;Either&lt;/span&gt; e a, w)&lt;/code&gt;, and then there’s&lt;/p&gt;
&lt;pre class="sourceCode"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span class="kw"&gt;type&lt;/span&gt; &lt;span class="dt"&gt;MyMonad&lt;/span&gt; e w a &lt;span class="fu"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;WriterT&lt;/span&gt; w (&lt;span class="dt"&gt;Either&lt;/span&gt; e) a&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;isomorphic to &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;Either&lt;/span&gt; r (a, w)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;We can already see the difference from the types. In the first case, the &lt;code&gt;w&lt;/code&gt; is there independently of the value of &lt;code&gt;Either&lt;/code&gt;. In the second case, if the computation failed, the whole thing is &lt;code class="sourceCode haskell"&gt;&lt;span class="kw"&gt;Left&lt;/span&gt; msg&lt;/code&gt;, and we don’t get our log &lt;code&gt;w&lt;/code&gt; back.&lt;/p&gt;
&lt;p&gt;Let’s try the following to confirm our expectations:&lt;/p&gt;
&lt;pre class="sourceCode"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span class="fu"&gt;&amp;gt;&lt;/span&gt; runWriter &lt;span class="fu"&gt;$&lt;/span&gt; runErrorT &lt;span class="fu"&gt;$&lt;/span&gt; tell &lt;span class="st"&gt;&amp;quot;foo&amp;quot;&lt;/span&gt; &lt;span class="fu"&gt;&amp;gt;&amp;gt;&lt;/span&gt; throwError &lt;span class="st"&gt;&amp;quot;err&amp;quot;&lt;/span&gt; &lt;span class="fu"&gt;&amp;gt;&amp;gt;&lt;/span&gt; tell &lt;span class="st"&gt;&amp;quot;bar&amp;quot;&lt;/span&gt;&lt;br /&gt;(&lt;span class="kw"&gt;Left&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;err&amp;quot;&lt;/span&gt;,&lt;span class="st"&gt;&amp;quot;foo&amp;quot;&lt;/span&gt;)&lt;br /&gt;&lt;span class="fu"&gt;&amp;gt;&lt;/span&gt; runErrorT &lt;span class="fu"&gt;$&lt;/span&gt; runWriterT &lt;span class="fu"&gt;$&lt;/span&gt; tell &lt;span class="st"&gt;&amp;quot;foo&amp;quot;&lt;/span&gt; &lt;span class="fu"&gt;&amp;gt;&amp;gt;&lt;/span&gt; throwError &lt;span class="st"&gt;&amp;quot;err&amp;quot;&lt;/span&gt; &lt;span class="fu"&gt;&amp;gt;&amp;gt;&lt;/span&gt; tell &lt;span class="st"&gt;&amp;quot;bar&amp;quot;&lt;/span&gt;&lt;br /&gt;&lt;span class="kw"&gt;Left&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;err&amp;quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="developing-intuition"&gt;Developing intuition&lt;/h2&gt;
&lt;p&gt;When reasoning about a stack of monad transformers, it’s useful to keep in mind that a transformer knows nothing about its inner monad. It has to work “inside” that monad. It has no ability to alter or cancel the effects that happened before in that monad. (It can prevent those effects from happening, though — see &lt;code class="sourceCode haskell"&gt;tell &lt;span class="st"&gt;&amp;quot;bar&amp;quot;&lt;/span&gt;&lt;/code&gt; above.)&lt;/p&gt;
&lt;p&gt;In the first example above, which corresponds to &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;ErrorT&lt;/span&gt; e (&lt;span class="dt"&gt;Writer&lt;/span&gt; w)&lt;/code&gt;, the Error monad had to work inside the Writer monad. It simply had no way to tell the writer monad to “forget” what had been told to it before.&lt;/p&gt;
&lt;p&gt;In the second example, corresponding to &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;WriterT&lt;/span&gt; w (&lt;span class="dt"&gt;Either&lt;/span&gt; e) a&lt;/code&gt;, the main monad is now &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;Either&lt;/span&gt; e&lt;/code&gt;. If it decides to fail, it will return just the error, and nothing else.&lt;/p&gt;
&lt;p&gt;The same logic answers the question why there’s no &lt;code&gt;IOT&lt;/code&gt;, an IO monad transformer. Imagine this:&lt;/p&gt;
&lt;pre class="sourceCode"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span class="kw"&gt;do&lt;/span&gt;&lt;br /&gt;    targetHit &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; launchMissiles&lt;br /&gt;    when targetHit &lt;span class="fu"&gt;$&lt;/span&gt;&lt;br /&gt;        throwError &lt;span class="st"&gt;&amp;quot;oops I did it again&amp;quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Since &lt;code&gt;throwError&lt;/code&gt; happens in the base monad, the whole thing is just &lt;code class="sourceCode haskell"&gt;&lt;span class="kw"&gt;Left&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;oops I did it again&amp;quot;&lt;/span&gt;&lt;/code&gt; — nothing mentions any IO. But what about the missiles?&lt;/p&gt;
&lt;p&gt;If this shallow explanation is not enough to make you comfortable with transformers, I’d advise to read (or even to write) the implementation of some standard transformers.&lt;/p&gt;
&lt;h2 id="even-more-interesting-example-parsec-state"&gt;Even more interesting example: Parsec + State&lt;/h2&gt;
&lt;p&gt;The Parsec monad already allows us to have &lt;a href="http://hackage.haskell.org/packages/archive/parsec/latest/doc/html/Text-Parsec-Prim.html#v:getState"&gt;our own state&lt;/a&gt;, but let’s see how we can add one independently.&lt;/p&gt;
&lt;p&gt;Again, we have two ways to layer ParsecT and StateT transformers on top of Identity: &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;ParsecT&lt;/span&gt; s () (&lt;span class="dt"&gt;State&lt;/span&gt; u) a&lt;/code&gt; and &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;StateT&lt;/span&gt; u (&lt;span class="dt"&gt;Parsec&lt;/span&gt; s ()) a&lt;/code&gt;. Is there a difference?&lt;/p&gt;
&lt;p&gt;Recall that Parsec is a backtracking monad. It can execute one branch, fail, and then execute another branch. Do we observe the state changes that happened in the aborted branch?&lt;/p&gt;
&lt;p&gt;This will be our test code:&lt;/p&gt;
&lt;pre class="sourceCode"&gt;&lt;code class="sourceCode haskell"&gt;((put &lt;span class="dv"&gt;1&lt;/span&gt; &lt;span class="fu"&gt;&amp;gt;&amp;gt;&lt;/span&gt; char &lt;span class="ch"&gt;'b'&lt;/span&gt;) &lt;span class="fu"&gt;&amp;lt;|&amp;gt;&lt;/span&gt; char &lt;span class="ch"&gt;'a'&lt;/span&gt;) &lt;span class="fu"&gt;&amp;gt;&amp;gt;&lt;/span&gt; get&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We’ll try to run it with the input &lt;code class="sourceCode haskell"&gt;&lt;span class="st"&gt;&amp;quot;a&amp;quot;&lt;/span&gt;&lt;/code&gt; and initial state &lt;code class="sourceCode haskell"&gt;&lt;span class="dv"&gt;0&lt;/span&gt;&lt;/code&gt;. First, Parsec executes the left branch of &lt;code class="sourceCode haskell"&gt;&lt;span class="fu"&gt;&amp;lt;|&amp;gt;&lt;/span&gt;&lt;/code&gt;, fails, and proceeds with the right branch. If the state is “global”, then the final result will be &lt;code class="sourceCode haskell"&gt;&lt;span class="dv"&gt;1&lt;/span&gt;&lt;/code&gt;. If the state is subject to backtracking, then we’ll see &lt;code class="sourceCode haskell"&gt;&lt;span class="dv"&gt;0&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In the &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;ParsecT&lt;/span&gt; s () (&lt;span class="dt"&gt;State&lt;/span&gt; u) a&lt;/code&gt; case, the base monad is State. ParsecT works inside that monad and cannot revert the effects that happened there. (It may seem that it could remember the state of a branch using &lt;code&gt;get&lt;/code&gt; and then restore it using &lt;code&gt;put&lt;/code&gt;; but a monad transformer has to be polymorphic in the underlying monad and thus cannot rely on existence of &lt;code&gt;get&lt;/code&gt; and &lt;code&gt;put&lt;/code&gt;.)&lt;/p&gt;
&lt;p&gt;And indeed, the code&lt;/p&gt;
&lt;pre class="sourceCode"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span class="kw"&gt;import&lt;/span&gt; &lt;span class="dt"&gt;Text.Parsec&lt;/span&gt;&lt;br /&gt;&lt;span class="kw"&gt;import&lt;/span&gt; &lt;span class="dt"&gt;Control.Monad.State&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;main &lt;span class="fu"&gt;=&lt;/span&gt; &lt;span class="fu"&gt;print&lt;/span&gt; &lt;span class="fu"&gt;$&lt;/span&gt; &lt;span class="fu"&gt;flip&lt;/span&gt; evalState &lt;span class="dv"&gt;0&lt;/span&gt; &lt;span class="fu"&gt;$&lt;/span&gt; runParserT p () &lt;span class="st"&gt;&amp;quot;-&amp;quot;&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;a&amp;quot;&lt;/span&gt;&lt;br /&gt;    &lt;span class="kw"&gt;where&lt;/span&gt; p &lt;span class="fu"&gt;=&lt;/span&gt; ((put &lt;span class="dv"&gt;1&lt;/span&gt; &lt;span class="fu"&gt;&amp;gt;&amp;gt;&lt;/span&gt; char &lt;span class="ch"&gt;'b'&lt;/span&gt;) &lt;span class="fu"&gt;&amp;lt;|&amp;gt;&lt;/span&gt; char &lt;span class="ch"&gt;'a'&lt;/span&gt;) &lt;span class="fu"&gt;&amp;gt;&amp;gt;&lt;/span&gt; get&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;prints &lt;code class="sourceCode haskell"&gt;&lt;span class="kw"&gt;Right&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Let’s now try the second option: layering StateT on top of Parsec. We cannot use the code above as is, because types do not match: e.g. &lt;code class="sourceCode haskell"&gt;char &lt;span class="ch"&gt;'b'&lt;/span&gt;&lt;/code&gt; has type &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;Parsec&lt;/span&gt; s () &lt;span class="dt"&gt;Char&lt;/span&gt;&lt;/code&gt;, but we need &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;StateT&lt;/span&gt; u (&lt;span class="dt"&gt;Parsec&lt;/span&gt; s ()) &lt;span class="dt"&gt;Char&lt;/span&gt;&lt;/code&gt;. Such an upgrade is done by the &lt;code&gt;lift&lt;/code&gt; function.&lt;/p&gt;
&lt;p&gt;Sometimes, however, we need to “downgrade” computations from &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;StateT&lt;/span&gt; u (&lt;span class="dt"&gt;Parsec&lt;/span&gt; s ()) a&lt;/code&gt; to &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;Parsec&lt;/span&gt; s () a&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;For example, to implement a &lt;code class="sourceCode haskell"&gt;&lt;span class="fu"&gt;&amp;lt;|&amp;gt;&lt;/span&gt;&lt;/code&gt; operator of type&lt;/p&gt;
&lt;pre class="sourceCode"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span class="ot"&gt;(&amp;lt;|&amp;gt;) &lt;/span&gt;&lt;span class="ot"&gt;::&lt;/span&gt; &lt;span class="dt"&gt;StateT&lt;/span&gt; u (&lt;span class="dt"&gt;Parsec&lt;/span&gt; s ()) a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;StateT&lt;/span&gt; u (&lt;span class="dt"&gt;Parsec&lt;/span&gt; s ()) a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;StateT&lt;/span&gt; u (&lt;span class="dt"&gt;Parsec&lt;/span&gt; s ()) a&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;we need first to downgrade the arguments to plain Parsec computation, invoke Parsec’s own &lt;code class="sourceCode haskell"&gt;&lt;span class="fu"&gt;&amp;lt;|&amp;gt;&lt;/span&gt;&lt;/code&gt; and then upgrade the result back to StateT.&lt;/p&gt;
&lt;pre class="sourceCode"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span class="kw"&gt;import&lt;/span&gt; &lt;span class="dt"&gt;Text.Parsec&lt;/span&gt; &lt;span class="kw"&gt;as&lt;/span&gt; &lt;span class="dt"&gt;P&lt;/span&gt;&lt;br /&gt;&lt;span class="kw"&gt;import&lt;/span&gt; &lt;span class="dt"&gt;Control.Monad.State&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;main &lt;span class="fu"&gt;=&lt;/span&gt; &lt;span class="fu"&gt;print&lt;/span&gt; &lt;span class="fu"&gt;$&lt;/span&gt; runParser (evalStateT p &lt;span class="dv"&gt;0&lt;/span&gt;) () &lt;span class="st"&gt;&amp;quot;-&amp;quot;&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;a&amp;quot;&lt;/span&gt;&lt;br /&gt;  &lt;span class="kw"&gt;where&lt;/span&gt;&lt;br /&gt;    p &lt;span class="fu"&gt;=&lt;/span&gt; ((put &lt;span class="dv"&gt;1&lt;/span&gt; &lt;span class="fu"&gt;&amp;gt;&amp;gt;&lt;/span&gt; char &lt;span class="ch"&gt;'b'&lt;/span&gt;) &lt;span class="fu"&gt;&amp;lt;|&amp;gt;&lt;/span&gt; char &lt;span class="ch"&gt;'a'&lt;/span&gt;) &lt;span class="fu"&gt;&amp;gt;&amp;gt;&lt;/span&gt; get&lt;br /&gt;&lt;br /&gt;    char &lt;span class="fu"&gt;=&lt;/span&gt; lift &lt;span class="fu"&gt;.&lt;/span&gt; P.char&lt;br /&gt;&lt;br /&gt;    a &lt;span class="fu"&gt;&amp;lt;|&amp;gt;&lt;/span&gt; b &lt;span class="fu"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;StateT&lt;/span&gt; &lt;span class="fu"&gt;$&lt;/span&gt; \s &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt;&lt;br /&gt;        runStateT a s &lt;span class="fu"&gt;P.&amp;lt;|&amp;gt;&lt;/span&gt; runStateT b s&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Notice how we explicitly run both branches of &lt;code class="sourceCode haskell"&gt;&lt;span class="fu"&gt;&amp;lt;|&amp;gt;&lt;/span&gt;&lt;/code&gt; with the same state. It’s no surprise now that the state will be “backtracked” and the result will be &lt;code class="sourceCode haskell"&gt;&lt;span class="kw"&gt;Right&lt;/span&gt; &lt;span class="dv"&gt;0&lt;/span&gt;&lt;/code&gt;. By the way, this is the same result as would be achieved using Parsec’s internal state.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/RomanCheplyaka/~4/1r24GsS15Nw" height="1" width="1"/&gt;</description>
    <pubDate>Mon, 02 Jan 2012 00:00:00 UT</pubDate>
    <guid isPermaLink="false">http://ro-che.info/articles//2012-01-02-composing-monads.html</guid>
<feedburner:origLink>http://ro-che.info/articles//2012-01-02-composing-monads.html</feedburner:origLink></item>

    </channel> 
</rss>

