How does gpostpro "escape from the monad"?
<p>I am trying to understand how this very abstract recursive function from the Haskell <code>recursion-schemes</code> package works (or, indeed, what it does!) - from <a href="https://github.com/ekmett/recursion-schemes/blob/74ccfaea0e336e84978e47fca35b94e0c5f476f2/Data/Functor/Foldable.hs" rel="nofollow">this file</a>:</p>

<pre><code>class Functor (Base t) =&gt; Corecursive t where

  [...]

  -- | A generalized postpromorphism
  gpostpro
    :: (Recursive t, Monad m)
    =&gt; (forall b. m (Base t b) -&gt; Base t (m b)) -- distributive law
    -&gt; (forall c. Base t c -&gt; Base t c)         -- natural transformation
    -&gt; (a -&gt; Base t (m a))                      -- a (Base t)-m-coalgebra
    -&gt; a                                        -- seed
    -&gt; t
  gpostpro k e g = a . return where a = embed . fmap (ana (e . project) . a . join) . k . liftM g
</code></pre>

<p>In particular, what I want to understand is: how does it apply the <code>g</code> function which mentions the monad type constructor <code>m</code>, but then return a value of the <code>t</code> type, which doesn't mention or depend on <code>m</code>? I thought escaping from arbitrary monads was impossible in Haskell!</p>

<p>I first loaded the source file into Intero to try to use its type-at-point feature, but that attempt <a href="https://github.com/commercialhaskell/intero/issues/264" rel="nofollow">failed</a>.</p>

<p>I then loaded it into GHCi using <code>cabal repl</code>, and tried to follow the types through the composed functions one at a time, using GHCi to help with type inference, by commenting out various bits of the definition. However, when I got to the <code>fmap</code>, I couldn't work out what to comment out, because if I uncommented the recursive <code>a</code> invocation but commented out other stuff, I thought it probably wouldn't even compile because the partially-commented-out <em>definition</em> of <code>a</code> wouldn't have the right type.</p>