<div dir="ltr"><br><br><div class="gmail_quote">On Mon, Jun 28, 2010 at 10:02 PM, Carl Howells <span dir="ltr"><<a href="mailto:chowells79@gmail.com">chowells79@gmail.com</a>></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't run are when Snap'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 'E.bracket'<br>
bracket :: MonadCatchIO m => m a -> (a -> m b) -> (a -> m c) -> m c<br>
bracket before after thing = block $ do<br>
a <- before<br>
r <- unblock (thing a) `onException` after a<br>
_ <- after a<br>
return r<br>
<br>
When monadic short-circuiting applies, the "_ <- after a" 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't keep<br>
the guarantee provided by bracket in Control.Exception, which is that<br>
the "after" 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 => MonadBracketIO m where<br>
bracket :: m a -> (a -> m b) -> (a -> m c) -> 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'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'm not sure if it'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>