Sophie

Sophie

distrib > Fedora > 18 > i386 > by-pkgid > 6db87534498865af2fd704ce2007759d > files > 10

ghc-mmorph-devel-1.0.0-1.fc18.i686.rpm

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>Control.Monad.Morph</title><link href="ocean.css" rel="stylesheet" type="text/css" title="Ocean" /><script src="haddock-util.js" type="text/javascript"></script><script type="text/javascript">//<![CDATA[
window.onload = function () {pageLoad();setSynopsis("mini_Control-Monad-Morph.html");};
//]]>
</script></head><body><div id="package-header"><ul class="links" id="page-menu"><li><a href="src/Control-Monad-Morph.html">Source</a></li><li><a href="index.html">Contents</a></li><li><a href="doc-index.html">Index</a></li></ul><p class="caption">mmorph-1.0.0: Monad morphisms</p></div><div id="content"><div id="module-header"><table class="info"><tr><th>Safe Haskell</th><td>Safe-Infered</td></tr></table><p class="caption">Control.Monad.Morph</p></div><div id="table-of-contents"><p class="caption">Contents</p><ul><li><a href="#g:1">Functors over Monads
</a></li><li><a href="#g:2">Monads over Monads
</a></li><li><a href="#g:3">Tutorial
</a><ul><li><a href="#g:4">Generalizing base monads
</a></li><li><a href="#g:5">Monad morphisms
</a></li><li><a href="#g:6">Mixing diverse transformers
</a></li><li><a href="#g:7">Embedding transformers
</a></li></ul></li></ul></div><div id="description"><p class="caption">Description</p><div class="doc"><p>A monad morphism is a natural transformation:
</p><pre> morph :: forall a . m a -&gt; n a
</pre><p>... that obeys the following two laws:
</p><pre> morph $ do x &lt;- m  =  do x &lt;- morph m
            f x           morph (f x)
 
 morph (return x) = return x
</pre><p>... which are equivalent to the following two functor laws:
</p><pre> morph . (f &gt;=&gt; g) = morph . f &gt;=&gt; morph . g
 
 morph . return = return
</pre><p>Examples of monad morphisms include:
</p><ul><li> <code><a href="Control-Monad-Morph.html#v:lift">lift</a></code> (from <code><a href="Control-Monad-Morph.html#t:MonadTrans">MonadTrans</a></code>)
</li><li> <code><a href="Control-Monad-Morph.html#v:squash">squash</a></code> (See below)
</li><li> <code><code><a href="Control-Monad-Morph.html#v:hoist">hoist</a></code> f</code> (See below), if <code>f</code> is a monad morphism
</li><li> <code>(f . g)</code>, if <code>f</code> and <code>g</code> are both monad morphisms
</li><li> <code><a href="/usr/share/doc/ghc/html/libraries/base-4.5.0.0/Prelude.html#v:id">id</a></code>
</li></ul><p>Monad morphisms commonly arise when manipulating existing monad transformer
    code for compatibility purposes.  The <code><a href="Control-Monad-Morph.html#t:MFunctor">MFunctor</a></code>, <code><a href="Control-Monad-Morph.html#t:MonadTrans">MonadTrans</a></code>, and
    <code><a href="Control-Monad-Morph.html#t:MMonad">MMonad</a></code> classes define standard ways to change monad transformer stacks:
</p><ul><li> <code><a href="Control-Monad-Morph.html#v:lift">lift</a></code> introduces a new monad transformer layer of any type.
</li><li> <code><a href="Control-Monad-Morph.html#v:squash">squash</a></code> flattens two identical monad transformer layers into a single
      layer of the same type.
</li><li> <code><a href="Control-Monad-Morph.html#v:hoist">hoist</a></code> maps monad morphisms to modify deeper layers of the monad
       transformer stack.
</li></ul></div></div><div id="synopsis"><p id="control.syn" class="caption expander" onclick="toggleSection('syn')">Synopsis</p><ul id="section.syn" class="hide" onclick="toggleSection('syn')"><li class="src short"><span class="keyword">class</span>  <a href="#t:MFunctor">MFunctor</a> t  <span class="keyword">where</span><ul class="subs"><li><a href="#v:hoist">hoist</a> :: <a href="/usr/share/doc/ghc/html/libraries/base-4.5.0.0/Control-Monad.html#t:Monad">Monad</a> m =&gt; (<span class="keyword">forall</span> a.  m a -&gt; n a) -&gt; t m b -&gt; t n b</li></ul></li><li class="src short"><span class="keyword">class</span> (<a href="Control-Monad-Morph.html#t:MFunctor">MFunctor</a> t, <a href="Control-Monad-Morph.html#t:MonadTrans">MonadTrans</a> t) =&gt; <a href="#t:MMonad">MMonad</a> t  <span class="keyword">where</span><ul class="subs"><li><a href="#v:embed">embed</a> :: <a href="/usr/share/doc/ghc/html/libraries/base-4.5.0.0/Control-Monad.html#t:Monad">Monad</a> n =&gt; (<span class="keyword">forall</span> a.  m a -&gt; t n a) -&gt; t m b -&gt; t n b</li></ul></li><li class="src short"><span class="keyword">class</span>  <a href="#t:MonadTrans">MonadTrans</a> t  <span class="keyword">where</span><ul class="subs"><li><a href="#v:lift">lift</a> :: <a href="/usr/share/doc/ghc/html/libraries/base-4.5.0.0/Control-Monad.html#t:Monad">Monad</a> m =&gt; m a -&gt; t m a</li></ul></li><li class="src short"><a href="#v:squash">squash</a> :: (<a href="/usr/share/doc/ghc/html/libraries/base-4.5.0.0/Control-Monad.html#t:Monad">Monad</a> m, <a href="Control-Monad-Morph.html#t:MMonad">MMonad</a> t) =&gt; t (t m) a -&gt; t m a</li><li class="src short"><a href="#v:-62--124--62-">(&gt;|&gt;)</a> :: (<a href="/usr/share/doc/ghc/html/libraries/base-4.5.0.0/Control-Monad.html#t:Monad">Monad</a> m3, <a href="Control-Monad-Morph.html#t:MMonad">MMonad</a> t) =&gt; (<span class="keyword">forall</span> a.  m1 a -&gt; t m2 a) -&gt; (<span class="keyword">forall</span> b.  m2 b -&gt; t m3 b) -&gt; m1 c -&gt; t m3 c</li><li class="src short"><a href="#v:-60--124--60-">(&lt;|&lt;)</a> :: (<a href="/usr/share/doc/ghc/html/libraries/base-4.5.0.0/Control-Monad.html#t:Monad">Monad</a> m3, <a href="Control-Monad-Morph.html#t:MMonad">MMonad</a> t) =&gt; (<span class="keyword">forall</span> b.  m2 b -&gt; t m3 b) -&gt; (<span class="keyword">forall</span> a.  m1 a -&gt; t m2 a) -&gt; m1 c -&gt; t m3 c</li><li class="src short"><a href="#v:-61--60--124-">(=&lt;|)</a> :: (<a href="/usr/share/doc/ghc/html/libraries/base-4.5.0.0/Control-Monad.html#t:Monad">Monad</a> n, <a href="Control-Monad-Morph.html#t:MMonad">MMonad</a> t) =&gt; (<span class="keyword">forall</span> a.  m a -&gt; t n a) -&gt; t m b -&gt; t n b</li><li class="src short"><a href="#v:-124--62--61-">(|&gt;=)</a> :: (<a href="/usr/share/doc/ghc/html/libraries/base-4.5.0.0/Control-Monad.html#t:Monad">Monad</a> n, <a href="Control-Monad-Morph.html#t:MMonad">MMonad</a> t) =&gt; t m b -&gt; (<span class="keyword">forall</span> a.  m a -&gt; t n a) -&gt; t n b</li></ul></div><div id="interface"><h1 id="g:1">Functors over Monads
</h1><div class="top"><p class="src"><span class="keyword">class</span>  <a name="t:MFunctor" class="def">MFunctor</a> t  <span class="keyword">where</span><a href="src/Control-Monad-Morph.html#MFunctor" class="link">Source</a></p><div class="doc"><p>A functor in the category of monads, using <code><a href="Control-Monad-Morph.html#v:hoist">hoist</a></code> as the analog of <code><a href="/usr/share/doc/ghc/html/libraries/base-4.5.0.0/Control-Monad.html#v:fmap">fmap</a></code>:
</p><pre> hoist (f . g) = hoist f . hoist g
 
 hoist id = id
</pre></div><div class="subs methods"><p class="caption">Methods</p><p class="src"><a name="v:hoist" class="def">hoist</a> :: <a href="/usr/share/doc/ghc/html/libraries/base-4.5.0.0/Control-Monad.html#t:Monad">Monad</a> m =&gt; (<span class="keyword">forall</span> a.  m a -&gt; n a) -&gt; t m b -&gt; t n b<a href="src/Control-Monad-Morph.html#hoist" class="link">Source</a></p><div class="doc"><p>Lift a monad morphism from <code>m</code> to <code>n</code> into a monad morphism from
        <code>(t m)</code> to <code>(t n)</code>
</p></div></div><div class="subs instances"><p id="control.i:MFunctor" class="caption collapser" onclick="toggleSection('i:MFunctor')">Instances</p><div id="section.i:MFunctor" class="show"><table><tr><td class="src"><a href="Control-Monad-Morph.html#t:MFunctor">MFunctor</a> <a href="/usr/share/doc/ghc/html/libraries/transformers-0.3.0.0/Control-Monad-Trans-Maybe.html#t:MaybeT">MaybeT</a></td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="Control-Monad-Morph.html#t:MFunctor">MFunctor</a> <a href="/usr/share/doc/ghc/html/libraries/transformers-0.3.0.0/Control-Monad-Trans-Identity.html#t:IdentityT">IdentityT</a></td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="Control-Monad-Morph.html#t:MFunctor">MFunctor</a> (<a href="/usr/share/doc/ghc/html/libraries/transformers-0.3.0.0/Control-Monad-Trans-Writer-Strict.html#t:WriterT">WriterT</a> w)</td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="Control-Monad-Morph.html#t:MFunctor">MFunctor</a> (<a href="/usr/share/doc/ghc/html/libraries/transformers-0.3.0.0/Control-Monad-Trans-Writer-Lazy.html#t:WriterT">WriterT</a> w)</td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="Control-Monad-Morph.html#t:MFunctor">MFunctor</a> (<a href="/usr/share/doc/ghc/html/libraries/transformers-0.3.0.0/Control-Monad-Trans-State-Strict.html#t:StateT">StateT</a> s)</td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="Control-Monad-Morph.html#t:MFunctor">MFunctor</a> (<a href="/usr/share/doc/ghc/html/libraries/transformers-0.3.0.0/Control-Monad-Trans-State-Lazy.html#t:StateT">StateT</a> s)</td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="Control-Monad-Morph.html#t:MFunctor">MFunctor</a> (<a href="/usr/share/doc/ghc/html/libraries/transformers-0.3.0.0/Control-Monad-Trans-Reader.html#t:ReaderT">ReaderT</a> r)</td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="Control-Monad-Morph.html#t:MFunctor">MFunctor</a> (<a href="/usr/share/doc/ghc/html/libraries/transformers-0.3.0.0/Control-Monad-Trans-Error.html#t:ErrorT">ErrorT</a> e)</td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="Control-Monad-Morph.html#t:MFunctor">MFunctor</a> (<a href="/usr/share/doc/ghc/html/libraries/transformers-0.3.0.0/Control-Monad-Trans-RWS-Strict.html#t:RWST">RWST</a> r w s)</td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="Control-Monad-Morph.html#t:MFunctor">MFunctor</a> (<a href="/usr/share/doc/ghc/html/libraries/transformers-0.3.0.0/Control-Monad-Trans-RWS-Lazy.html#t:RWST">RWST</a> r w s)</td><td class="doc empty">&nbsp;</td></tr></table></div></div></div><h1 id="g:2">Monads over Monads
</h1><div class="top"><p class="src"><span class="keyword">class</span> (<a href="Control-Monad-Morph.html#t:MFunctor">MFunctor</a> t, <a href="Control-Monad-Morph.html#t:MonadTrans">MonadTrans</a> t) =&gt; <a name="t:MMonad" class="def">MMonad</a> t  <span class="keyword">where</span><a href="src/Control-Monad-Morph.html#MMonad" class="link">Source</a></p><div class="doc"><p>A monad in the category of monads, using <code><a href="Control-Monad-Morph.html#v:lift">lift</a></code> from <code><a href="Control-Monad-Morph.html#t:MonadTrans">MonadTrans</a></code> as the
    analog of <code><a href="/usr/share/doc/ghc/html/libraries/base-4.5.0.0/Control-Monad.html#v:return">return</a></code> and <code><a href="Control-Monad-Morph.html#v:embed">embed</a></code> as the analog of (<code><a href="/usr/share/doc/ghc/html/libraries/base-4.5.0.0/Control-Monad.html#v:-61--60--60-">=&lt;&lt;</a></code>):
</p><pre> embed lift = id
 
 embed f (lift m) = f m
 
 embed g (embed f t) = embed (\m -&gt; embed g (f m)) t
</pre></div><div class="subs methods"><p class="caption">Methods</p><p class="src"><a name="v:embed" class="def">embed</a> :: <a href="/usr/share/doc/ghc/html/libraries/base-4.5.0.0/Control-Monad.html#t:Monad">Monad</a> n =&gt; (<span class="keyword">forall</span> a.  m a -&gt; t n a) -&gt; t m b -&gt; t n b<a href="src/Control-Monad-Morph.html#embed" class="link">Source</a></p><div class="doc"><p>Embed a newly created <code><a href="Control-Monad-Morph.html#t:MMonad">MMonad</a></code> layer within an existing layer
</p><p><code><a href="Control-Monad-Morph.html#v:embed">embed</a></code> is analogous to (<code><a href="/usr/share/doc/ghc/html/libraries/base-4.5.0.0/Control-Monad.html#v:-61--60--60-">=&lt;&lt;</a></code>)
</p></div></div><div class="subs instances"><p id="control.i:MMonad" class="caption collapser" onclick="toggleSection('i:MMonad')">Instances</p><div id="section.i:MMonad" class="show"><table><tr><td class="src"><a href="Control-Monad-Morph.html#t:MMonad">MMonad</a> <a href="/usr/share/doc/ghc/html/libraries/transformers-0.3.0.0/Control-Monad-Trans-Maybe.html#t:MaybeT">MaybeT</a></td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="Control-Monad-Morph.html#t:MMonad">MMonad</a> <a href="/usr/share/doc/ghc/html/libraries/transformers-0.3.0.0/Control-Monad-Trans-Identity.html#t:IdentityT">IdentityT</a></td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="/usr/share/doc/ghc/html/libraries/base-4.5.0.0/Data-Monoid.html#t:Monoid">Monoid</a> w =&gt; <a href="Control-Monad-Morph.html#t:MMonad">MMonad</a> (<a href="/usr/share/doc/ghc/html/libraries/transformers-0.3.0.0/Control-Monad-Trans-Writer-Strict.html#t:WriterT">WriterT</a> w)</td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="/usr/share/doc/ghc/html/libraries/base-4.5.0.0/Data-Monoid.html#t:Monoid">Monoid</a> w =&gt; <a href="Control-Monad-Morph.html#t:MMonad">MMonad</a> (<a href="/usr/share/doc/ghc/html/libraries/transformers-0.3.0.0/Control-Monad-Trans-Writer-Lazy.html#t:WriterT">WriterT</a> w)</td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="Control-Monad-Morph.html#t:MMonad">MMonad</a> (<a href="/usr/share/doc/ghc/html/libraries/transformers-0.3.0.0/Control-Monad-Trans-Reader.html#t:ReaderT">ReaderT</a> r)</td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="/usr/share/doc/ghc/html/libraries/transformers-0.3.0.0/Control-Monad-Trans-Error.html#t:Error">Error</a> e =&gt; <a href="Control-Monad-Morph.html#t:MMonad">MMonad</a> (<a href="/usr/share/doc/ghc/html/libraries/transformers-0.3.0.0/Control-Monad-Trans-Error.html#t:ErrorT">ErrorT</a> e)</td><td class="doc empty">&nbsp;</td></tr></table></div></div></div><div class="top"><p class="src"><span class="keyword">class</span>  <a name="t:MonadTrans" class="def">MonadTrans</a> t  <span class="keyword">where</span></p><div class="doc"><p>The class of monad transformers.  Instances should satisfy the
 following laws, which state that <code><a href="Control-Monad-Morph.html#v:lift">lift</a></code> is a transformer of monads:
</p><ul><li><pre><code><a href="Control-Monad-Morph.html#v:lift">lift</a></code> . <code><a href="/usr/share/doc/ghc/html/libraries/base-4.5.0.0/Control-Monad.html#v:return">return</a></code> = <code><a href="/usr/share/doc/ghc/html/libraries/base-4.5.0.0/Control-Monad.html#v:return">return</a></code></pre></li><li><pre><code><a href="Control-Monad-Morph.html#v:lift">lift</a></code> (m &gt;&gt;= f) = <code><a href="Control-Monad-Morph.html#v:lift">lift</a></code> m &gt;&gt;= (<code><a href="Control-Monad-Morph.html#v:lift">lift</a></code> . f)</pre></li></ul></div><div class="subs methods"><p class="caption">Methods</p><p class="src"><a name="v:lift" class="def">lift</a> :: <a href="/usr/share/doc/ghc/html/libraries/base-4.5.0.0/Control-Monad.html#t:Monad">Monad</a> m =&gt; m a -&gt; t m a</p><div class="doc"><p>Lift a computation from the argument monad to the constructed monad.
</p></div></div><div class="subs instances"><p id="control.i:MonadTrans" class="caption collapser" onclick="toggleSection('i:MonadTrans')">Instances</p><div id="section.i:MonadTrans" class="show"><table><tr><td class="src"><a href="Control-Monad-Morph.html#t:MonadTrans">MonadTrans</a> <a href="/usr/share/doc/ghc/html/libraries/transformers-0.3.0.0/Control-Monad-Trans-Maybe.html#t:MaybeT">MaybeT</a></td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="Control-Monad-Morph.html#t:MonadTrans">MonadTrans</a> <a href="/usr/share/doc/ghc/html/libraries/transformers-0.3.0.0/Control-Monad-Trans-Identity.html#t:IdentityT">IdentityT</a></td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="/usr/share/doc/ghc/html/libraries/base-4.5.0.0/Data-Monoid.html#t:Monoid">Monoid</a> w =&gt; <a href="Control-Monad-Morph.html#t:MonadTrans">MonadTrans</a> (<a href="/usr/share/doc/ghc/html/libraries/transformers-0.3.0.0/Control-Monad-Trans-Writer-Strict.html#t:WriterT">WriterT</a> w)</td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="/usr/share/doc/ghc/html/libraries/base-4.5.0.0/Data-Monoid.html#t:Monoid">Monoid</a> w =&gt; <a href="Control-Monad-Morph.html#t:MonadTrans">MonadTrans</a> (<a href="/usr/share/doc/ghc/html/libraries/transformers-0.3.0.0/Control-Monad-Trans-Writer-Lazy.html#t:WriterT">WriterT</a> w)</td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="Control-Monad-Morph.html#t:MonadTrans">MonadTrans</a> (<a href="/usr/share/doc/ghc/html/libraries/transformers-0.3.0.0/Control-Monad-Trans-State-Strict.html#t:StateT">StateT</a> s)</td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="Control-Monad-Morph.html#t:MonadTrans">MonadTrans</a> (<a href="/usr/share/doc/ghc/html/libraries/transformers-0.3.0.0/Control-Monad-Trans-State-Lazy.html#t:StateT">StateT</a> s)</td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="Control-Monad-Morph.html#t:MonadTrans">MonadTrans</a> (<a href="/usr/share/doc/ghc/html/libraries/transformers-0.3.0.0/Control-Monad-Trans-Reader.html#t:ReaderT">ReaderT</a> r)</td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="/usr/share/doc/ghc/html/libraries/transformers-0.3.0.0/Control-Monad-Trans-Error.html#t:Error">Error</a> e =&gt; <a href="Control-Monad-Morph.html#t:MonadTrans">MonadTrans</a> (<a href="/usr/share/doc/ghc/html/libraries/transformers-0.3.0.0/Control-Monad-Trans-Error.html#t:ErrorT">ErrorT</a> e)</td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="/usr/share/doc/ghc/html/libraries/base-4.5.0.0/Data-Monoid.html#t:Monoid">Monoid</a> w =&gt; <a href="Control-Monad-Morph.html#t:MonadTrans">MonadTrans</a> (<a href="/usr/share/doc/ghc/html/libraries/transformers-0.3.0.0/Control-Monad-Trans-RWS-Strict.html#t:RWST">RWST</a> r w s)</td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="/usr/share/doc/ghc/html/libraries/base-4.5.0.0/Data-Monoid.html#t:Monoid">Monoid</a> w =&gt; <a href="Control-Monad-Morph.html#t:MonadTrans">MonadTrans</a> (<a href="/usr/share/doc/ghc/html/libraries/transformers-0.3.0.0/Control-Monad-Trans-RWS-Lazy.html#t:RWST">RWST</a> r w s)</td><td class="doc empty">&nbsp;</td></tr></table></div></div></div><div class="top"><p class="src"><a name="v:squash" class="def">squash</a> :: (<a href="/usr/share/doc/ghc/html/libraries/base-4.5.0.0/Control-Monad.html#t:Monad">Monad</a> m, <a href="Control-Monad-Morph.html#t:MMonad">MMonad</a> t) =&gt; t (t m) a -&gt; t m a<a href="src/Control-Monad-Morph.html#squash" class="link">Source</a></p><div class="doc"><p>Squash two <code><a href="Control-Monad-Morph.html#t:MMonad">MMonad</a></code> layers into a single layer
</p><p><code><a href="Control-Monad-Morph.html#v:squash">squash</a></code> is analogous to <code><a href="/usr/share/doc/ghc/html/libraries/base-4.5.0.0/Control-Monad.html#v:join">join</a></code>
</p></div></div><div class="top"><p class="src"><a name="v:-62--124--62-" class="def">(&gt;|&gt;)</a> :: (<a href="/usr/share/doc/ghc/html/libraries/base-4.5.0.0/Control-Monad.html#t:Monad">Monad</a> m3, <a href="Control-Monad-Morph.html#t:MMonad">MMonad</a> t) =&gt; (<span class="keyword">forall</span> a.  m1 a -&gt; t m2 a) -&gt; (<span class="keyword">forall</span> b.  m2 b -&gt; t m3 b) -&gt; m1 c -&gt; t m3 c<a href="src/Control-Monad-Morph.html#%3E%7C%3E" class="link">Source</a></p><div class="doc"><p>Compose two <code><a href="Control-Monad-Morph.html#t:MMonad">MMonad</a></code> layer-building functions
</p><p>(<code><a href="Control-Monad-Morph.html#v:-62--124--62-">&gt;|&gt;</a></code>) is analogous to (<code><a href="/usr/share/doc/ghc/html/libraries/base-4.5.0.0/Control-Monad.html#v:-62--61--62-">&gt;=&gt;</a></code>)
</p></div></div><div class="top"><p class="src"><a name="v:-60--124--60-" class="def">(&lt;|&lt;)</a> :: (<a href="/usr/share/doc/ghc/html/libraries/base-4.5.0.0/Control-Monad.html#t:Monad">Monad</a> m3, <a href="Control-Monad-Morph.html#t:MMonad">MMonad</a> t) =&gt; (<span class="keyword">forall</span> b.  m2 b -&gt; t m3 b) -&gt; (<span class="keyword">forall</span> a.  m1 a -&gt; t m2 a) -&gt; m1 c -&gt; t m3 c<a href="src/Control-Monad-Morph.html#%3C%7C%3C" class="link">Source</a></p><div class="doc"><p>Equivalent to (<code><a href="Control-Monad-Morph.html#v:-62--124--62-">&gt;|&gt;</a></code>) with the arguments flipped
</p><p>(<code><a href="Control-Monad-Morph.html#v:-60--124--60-">&lt;|&lt;</a></code>) is analogous to (<code><a href="/usr/share/doc/ghc/html/libraries/base-4.5.0.0/Control-Monad.html#v:-60--61--60-">&lt;=&lt;</a></code>)
</p></div></div><div class="top"><p class="src"><a name="v:-61--60--124-" class="def">(=&lt;|)</a> :: (<a href="/usr/share/doc/ghc/html/libraries/base-4.5.0.0/Control-Monad.html#t:Monad">Monad</a> n, <a href="Control-Monad-Morph.html#t:MMonad">MMonad</a> t) =&gt; (<span class="keyword">forall</span> a.  m a -&gt; t n a) -&gt; t m b -&gt; t n b<a href="src/Control-Monad-Morph.html#%3D%3C%7C" class="link">Source</a></p><div class="doc"><p>An infix operator equivalent to <code><a href="Control-Monad-Morph.html#v:embed">embed</a></code>
</p><p>(<code><a href="Control-Monad-Morph.html#v:-61--60--124-">=&lt;|</a></code>) is analogous to (<code><a href="/usr/share/doc/ghc/html/libraries/base-4.5.0.0/Control-Monad.html#v:-61--60--60-">=&lt;&lt;</a></code>)
</p></div></div><div class="top"><p class="src"><a name="v:-124--62--61-" class="def">(|&gt;=)</a> :: (<a href="/usr/share/doc/ghc/html/libraries/base-4.5.0.0/Control-Monad.html#t:Monad">Monad</a> n, <a href="Control-Monad-Morph.html#t:MMonad">MMonad</a> t) =&gt; t m b -&gt; (<span class="keyword">forall</span> a.  m a -&gt; t n a) -&gt; t n b<a href="src/Control-Monad-Morph.html#%7C%3E%3D" class="link">Source</a></p><div class="doc"><p>Equivalent to (<code><a href="Control-Monad-Morph.html#v:-61--60--124-">=&lt;|</a></code>) with the arguments flipped
</p><p>(<code><a href="Control-Monad-Morph.html#v:-124--62--61-">|&gt;=</a></code>) is analogous to (<code><a href="/usr/share/doc/ghc/html/libraries/base-4.5.0.0/Control-Monad.html#v:-62--62--61-">&gt;&gt;=</a></code>)
</p></div></div><h1 id="g:3">Tutorial
</h1><div class="doc"><p>Monad morphisms solve the common problem of fixing monadic code after the
    fact without modifying the original source code or type signatures.  The
    following sections illustrate various examples of transparently modifying
    existing functions.
</p></div><h2 id="g:4">Generalizing base monads
</h2><div class="doc"><p>Imagine that some library provided the following <code><a href="/usr/share/doc/ghc/html/libraries/transformers-0.3.0.0/Control-Monad-Trans-State-Lazy.html#t:State">State</a></code> code:
</p><pre> import Control.Monad.Trans.State
 
 tick :: State Int ()
 tick = modify (+1)
</pre><p>... but we would prefer to reuse <code>tick</code> within a larger
    <code>(<code><a href="/usr/share/doc/ghc/html/libraries/transformers-0.3.0.0/Control-Monad-Trans-State-Lazy.html#t:StateT">StateT</a></code> Int <code><a href="/usr/share/doc/ghc/html/libraries/base-4.5.0.0/System-IO.html#t:IO">IO</a></code>)</code> block in order to mix in <code><a href="/usr/share/doc/ghc/html/libraries/base-4.5.0.0/System-IO.html#t:IO">IO</a></code> actions.
</p><p>We could patch the original library to generalize <code>tick</code>'s type signature:
</p><pre> tick :: (Monad m) =&gt; StateT Int m ()
</pre><p>... but we would prefer not to fork upstream code if possible.  How could
    we generalize <code>tick</code>'s type without modifying the original code?
</p><p>We can solve this if we realize that <code><a href="/usr/share/doc/ghc/html/libraries/transformers-0.3.0.0/Control-Monad-Trans-State-Lazy.html#t:State">State</a></code> is a type synonym for
    <code><a href="/usr/share/doc/ghc/html/libraries/transformers-0.3.0.0/Control-Monad-Trans-State-Lazy.html#t:StateT">StateT</a></code> with an <code><a href="/usr/share/doc/ghc/html/libraries/transformers-0.3.0.0/Data-Functor-Identity.html#t:Identity">Identity</a></code> base monad:
</p><pre> type State s = StateT s Identity
</pre><p>... which means that <code>tick</code>'s true type is actually:
</p><pre> tick :: StateT Int Identity ()
</pre><p>Now all we need is a function that <code>generalize</code>s the <code><a href="/usr/share/doc/ghc/html/libraries/transformers-0.3.0.0/Data-Functor-Identity.html#t:Identity">Identity</a></code> base monad
    to be any monad:
</p><pre> import Data.Functor.Identity
 
 generalize :: (Monad m) =&gt; Identity a -&gt; m a
 generalize m = return (runIdentity m)
</pre><p>... which we can <code><a href="Control-Monad-Morph.html#v:hoist">hoist</a></code> to change <code>tick</code>'s base monad:
</p><pre> hoist :: (Monad m, MFunctor t) =&gt; (forall a . m a -&gt; n a) -&gt; t m b -&gt; t n b
 
 hoist generalize :: (Monad m, MFunctor t) =&gt; t Identity b -&gt; t m b
 
 hoist generalize tick :: (Monad m) =&gt; StateT Int m ()
</pre><p>This lets us mix <code>tick</code> alongside <code><a href="/usr/share/doc/ghc/html/libraries/base-4.5.0.0/System-IO.html#t:IO">IO</a></code> using <code><a href="Control-Monad-Morph.html#v:lift">lift</a></code>:
</p><pre> import Control.Monad.Morph
 import Control.Monad.Trans.Class
 
 tock                        ::                   StateT Int IO ()
 tock = do
     hoist generalize tick   :: (Monad      m) =&gt; StateT Int m  ()
     lift $ putStrLn &quot;Tock!&quot; :: (MonadTrans t) =&gt; t          IO ()
</pre><pre class="screen"><code class="prompt">&gt;&gt;&gt; </code><strong class="userinput"><code>runStateT tock 0
</code></strong>Tock!
((), 1)
</pre></div><h2 id="g:5">Monad morphisms
</h2><div class="doc"><p>Notice that <code>generalize</code> is a monad morphism, and the following two proofs
    show how <code>generalize</code> satisfies the monad morphism laws.  You can refer to
    these proofs as an example for how to prove a function obeys the monad
    morphism laws:
</p><pre> generalize (return x)
 
 -- Definition of 'return' for the Identity monad
 = generalize (Identity x)
 
 -- Definition of 'generalize'
 = return (runIdentity (Identity x))
 
 -- runIdentity (Identity x) = x
 = return x
</pre><pre> generalize $ do x &lt;- m
                 f x
 
 -- Definition of (&gt;&gt;=) for the Identity monad
 = generalize (f (runIdentity m))
 
 -- Definition of 'generalize'
 = return (runIdentity (f (runIdentity m)))
 
 -- Monad law: Left identity
 = do x &lt;- return (runIdentity m)
      return (runIdentity (f x))
 
 -- Definition of 'generalize' in reverse
 = do x &lt;- generalize m
      generalize (f x)
</pre></div><h2 id="g:6">Mixing diverse transformers
</h2><div class="doc"><p>You can combine <code><a href="Control-Monad-Morph.html#v:hoist">hoist</a></code> and <code><a href="Control-Monad-Morph.html#v:lift">lift</a></code> to insert arbitrary layers anywhere
    within a monad transformer stack.  This comes in handy when interleaving two
    diverse stacks.
</p><p>For example, we might want to combine the following <code>save</code> function:
</p><pre> import Control.Monad.Trans.Writer
 
 -- i.e. :: StateT Int (WriterT [Int] Identity) ()
 save    :: StateT Int (Writer  [Int]) ()
 save = do
     n &lt;- get
     lift $ tell [n]
</pre><p>... with our previous <code>tock</code> function:
</p><pre> tock :: StateT Int IO ()
</pre><p>However, <code>save</code> and <code>tock</code> differ in two ways:
</p><ul><li> <code>tock</code> lacks a <code><a href="/usr/share/doc/ghc/html/libraries/transformers-0.3.0.0/Control-Monad-Trans-Writer-Strict.html#t:WriterT">WriterT</a></code> layer
</li><li> <code>save</code> has an <code><a href="/usr/share/doc/ghc/html/libraries/transformers-0.3.0.0/Data-Functor-Identity.html#t:Identity">Identity</a></code> base monad
</li></ul><p>We can mix the two by inserting a <code><a href="/usr/share/doc/ghc/html/libraries/transformers-0.3.0.0/Control-Monad-Trans-Writer-Strict.html#t:WriterT">WriterT</a></code> layer for <code>tock</code> and
    generalizing <code>save</code>'s base monad:
</p><pre> import Control.Monad
 
 program ::                   StateT Int (WriterT [Int] IO) ()
 program = replicateM_ 4 $ do
     hoist lift tock
         :: (MonadTrans t) =&gt; StateT Int (t             IO) ()
     hoist (hoist generalize) save
         :: (Monad      m) =&gt; StateT Int (WriterT [Int] m ) ()
</pre><pre class="screen"><code class="prompt">&gt;&gt;&gt; </code><strong class="userinput"><code>execWriterT (runStateT program 0)
</code></strong>Tock!
Tock!
Tock!
Tock!
[1,2,3,4]
</pre></div><h2 id="g:7">Embedding transformers
</h2><div class="doc"><p>Suppose we decided to <code>check</code> all <code><a href="/usr/share/doc/ghc/html/libraries/base-4.5.0.0/Control-Exception-Base.html#t:IOException">IOException</a></code>s using a combination of
    <code><a href="/usr/share/doc/ghc/html/libraries/base-4.5.0.0/Control-Exception-Base.html#v:try">try</a></code> and <code>ErrorT</code>:
</p><pre> import Control.Exception
 import Control.Monad.Trans.Class
 import Control.Monad.Trans.Error
 
 check :: IO a -&gt; ErrorT IOException IO a
 check io = ErrorT (try io)
</pre><p>... but then we forget to use <code>check</code> in one spot, mistakenly using <code><a href="Control-Monad-Morph.html#v:lift">lift</a></code>
    instead:
</p><pre> program :: ErrorT IOException IO ()
 program = do
     str &lt;- lift $ readFile &quot;test.txt&quot;
     check $ putStr str
</pre><pre class="screen"><code class="prompt">&gt;&gt;&gt; </code><strong class="userinput"><code>runErrorT program
</code></strong>*** Exception: test.txt: openFile: does not exist (No such file or directory)
</pre><p>How could we go back and fix <code>program</code> without modifying its source code?
</p><p>Well, <code>check</code> is a monad morphism, but we can't <code><a href="Control-Monad-Morph.html#v:hoist">hoist</a></code> it to modify the
    base monad because then we get two <code><a href="/usr/share/doc/ghc/html/libraries/transformers-0.3.0.0/Control-Monad-Trans-Error.html#t:ErrorT">ErrorT</a></code> layers instead of one:
</p><pre> hoist check :: (MFunctor t) =&gt; t IO a -&gt; t (ErrorT IOException IO) a

 hoist check program :: ErrorT IOException (ErrorT IOException IO) ()
</pre><p>We'd prefer to <code><a href="Control-Monad-Morph.html#v:embed">embed</a></code> all newly generated exceptions in the existing
    <code><a href="/usr/share/doc/ghc/html/libraries/transformers-0.3.0.0/Control-Monad-Trans-Error.html#t:ErrorT">ErrorT</a></code> layer:
</p><pre> embed check :: ErrorT IOException IO a -&gt; ErrorT IOException IO a

 embed check program :: ErrorT IOException IO ()
</pre><p>This correctly checks the exceptions that slipped through the cracks:
</p><pre class="screen"><code class="prompt">&gt;&gt;&gt; </code><strong class="userinput"><code>import Control.Monad.Morph
</code></strong><code class="prompt">&gt;&gt;&gt; </code><strong class="userinput"><code>runErrorT (embed check program)
</code></strong>Left test.txt: openFile: does not exist (No such file or directory)
</pre></div></div></div><div id="footer"><p>Produced by <a href="http://www.haskell.org/haddock/">Haddock</a> version 2.10.0</p></div></body></html>