There is a good known function - bracket:
bracket
:: IO a -- ^ computation to run first (\"acquire resource\")
-> (a -> IO b) -- ^ computation to run last (\"release resource\")
-> (a -> IO c) -- ^ computation to run in-between
-> IO c -- returns the value from the in-between computation
bracket before after thing =
mask $ \restore -> do
a <- before
r <- restore (thing a) `onException` after a
_ <- after a
return r
I see two calls of after: once on an exception, the second time - _ <- after a - in all cases (with exception/without exception). I call this:
bracket (pure 1) (\a -> print a >> pure a) (\a -> head [])
And print happens only once. Then why, with 2 afters? How does it work at all?
Could somebody explain in details how this snippet:
r <- restore (thing a) `onException` after a
_ <- after a
work exactly?
ps. I tried bang (!..) patterns, and nothing changed, it seems it is not about lazy evaluation...
EDIT: experiment with own (more specific logic) implementation:
mybracket
:: IO a -- ^computation to run first (\"acquire resource\")
-> (Maybe c -> a -> IO c) -- ^computation to run last (\"release resource\")
-> (a -> IO c) -- ^computation to run in-between
-> IO c -- returns the value from the in-between computation
mybracket before after thing =
mask $ \restore -> do
a <- before
r <- restore (thing a) `onException` after Nothing a
r1 <- after (Just r) a
return r1
Can I be sure that mybracket will call after just once - for exception in thing and when no any exceptions, in both cases?