<div dir="ltr"><br><br><div class="gmail_quote">On Mon, Jun 28, 2010 at 10:02 PM, Carl Howells <span dir="ltr">&lt;<a href="mailto:chowells79@gmail.com">chowells79@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;">
While working this weekend on the Snap web framework, I ran into a<br>
problem.  Snap implements MonadCatchIO, so I thought I could just use<br>
bracket to handle resource acquisition/release in a safe manner.<br>
Imagine my surprise when bracket simply failed to run the release<br>
action sometimes.<br>
<br>
I quickly determined the times when it doesn&#39;t run are when Snap&#39;s<br>
monadic short-circuiting is used.  I dug into the source of bracket<br>
(in the transformers branch, though the mtl branch has the same<br>
behavior in these cases, with slightly different code), and the reason<br>
why quickly became obvious:<br>
<br>
-- | Generalized version of &#39;E.bracket&#39;<br>
bracket :: MonadCatchIO m =&gt; m a -&gt; (a -&gt; m b) -&gt; (a -&gt; m c) -&gt; m c<br>
bracket before after thing = block $ do<br>
  a &lt;- before<br>
  r &lt;- unblock (thing a) `onException` after a<br>
  _ &lt;- after a<br>
  return r<br>
<br>
When monadic short-circuiting applies, the &quot;_ &lt;- after a&quot; line gets<br>
completely ignored.  In discussions with #haskell on this topic, it<br>
quickly became clear that for any monad transformer that can affect<br>
control flow, the definition of bracket in MonadCatchIO doesn&#39;t keep<br>
the guarantee provided by bracket in Control.Exception, which is that<br>
the &quot;after&quot; action will be run exactly once.<br>
<br>
Because of that, I think bracket needs to be a class function.<br>
Furthermore, I think it needs to be a new class, ie<br>
<br>
class MonadCatchIO m =&gt; MonadBracketIO m where<br>
   bracket :: m a -&gt; (a -&gt; m b) -&gt; (a -&gt; m c) -&gt; m c<br>
<br>
This would allow its definition in cases where it makes sense (Snap or<br>
MaybeT IO), but it could be left out in cases where it doesn&#39;t make<br>
sense, like ListT IO, even though MonadCatchIO makes sense there.<br>
<font color="#888888"><font class="Apple-style-span" color="#000000"><font class="Apple-style-span" color="#888888"><br></font></font></font></blockquote><div>I&#39;m not sure if it&#39;s related to this, but I had a problem[1] using the ContT instance of MonadCatchIO, but there the result was the opposite: I would have resources released twice. I would really like to have that one solved as well.</div>
<div><br></div><div>Michael</div><div><br></div><div>[1] <a href="http://permalink.gmane.org/gmane.comp.lang.haskell.cafe/76262">http://permalink.gmane.org/gmane.comp.lang.haskell.cafe/76262</a></div></div></div>