Reputation: 41919
Looking at the bracket
function from Parallel and Concurrent Programming in Haskell:
bracket :: IO a -> (a -> IO b) -> (a -> IO c) -> IO c
bracket before after during = do
a <- before
c <- during a `onException` after a
after a
return c
In the event of an exception, why does the after
function only get called once? In other words, I'm confused at the apparent execution of after a
twice in the event of an exception.
But, the code shows that after a
only gets called, as I understand, once:
λ: >data MyException = MyException deriving Show
λ: >instance Exception MyException
λ: >let e = return MyException :: IO MyException
λ: >bracket e (const $ putStrLn "clean up!") return
clean up!
MyException
Upvotes: 4
Views: 430
Reputation: 55049
From the docs for bracket
:
When you want to acquire a resource, do some work with it, and then release the resource, it is a good idea to use
bracket
, becausebracket
will install the necessary exception handler to release the resource in the event that an exception is raised during the computation. If an exception is raised, thenbracket
will re-raise the exception (after performing the release).
And onException
:
Like
finally
, but only performs the final action if there was an exception raised by the computation.
So if there is an exception thrown from during a
, the first call to after a
is executed, then the exception is rethrown, skipping the second after a
; if there is no exception, only the second is executed.
Note that in your sample code, you’re returning an exception, not throwing it—to throw, you need to use throw
or preferably throwIO :: Exception e => e -> IO a
.
Upvotes: 6