The bracket
functions are useful for making sure that resources are
released properly by code that may raise exceptions:
bracket :: IO a -> (a -> IO b) -> (a -> IO c) -> IO c
bracket_ :: IO a -> IO b -> IO c -> IO c
finally :: IO a -> IO b -> IO b
For example, to open a file, do some work on it and then close it again, we might use something like:
process_file = bracket (openFile "filename") closeFile
(do
...
)
bracket
works as follows: it executes its first argument
("open"), then its third argument, followed finally by its second
argument ("close"). If the third argument happened to raise an
exception, then the close operation will still be performed, and the
exception will be re-raised.
This means that in the example above the file will always be closed, even if an error occurs during processing.
The arguments to bracket
are in this order so that we can
partially apply it, like:
withFile name = bracket (openFile name) closeFile
The bracket_
function is a variant of bracket
that throws
away the result of the open, and finally
is an even simpler
version where we just want some closing code.