Haskell Bracket Cleanup
Haskell bracket cleanup is a pattern that always runs a release step after a use step. It keeps a resource closed or reset even when the use step stops early.
Release runs after use
The use step sets the box to 7. The release step then sets it to 99.
import Control.Exception (bracket)
import Data.IORef
main :: IO ()
main = do
ref <- newIORef 0
bracket (return ref) (\_ -> writeIORef ref 99) (\r -> writeIORef r 7)
v <- readIORef ref
print vBracket closes a file handle
The use step writes one line through the handle. The release step closes the handle before the file is read back.
import Control.Exception (bracket)
import System.IO
main :: IO ()
main = do
bracket (openFile "clean-b.txt" WriteMode) hClose (\h -> hPutStrLn h "done")
txt <- readFile "clean-b.txt"
putStr txtRelease runs even when use fails
The use step sets the box and then fails. The outer try catches the failure and the box still shows the release value.
import Control.Exception (bracket, try, SomeException, throwIO)
import Data.IORef
useStep :: IORef Int -> IO ()
useStep r = do
writeIORef r 7
throwIO (userError "boom")
main :: IO ()
main = do
ref <- newIORef 0
r <- try (bracket (return ref) (\_ -> writeIORef ref 99) useStep) :: IO (Either SomeException ())
v <- readIORef ref
print v
putStrLn (case r of Left _ -> "caught"; Right _ -> "ok")Example
import Control.Exception (bracket)
import Data.IORef
import System.IO
main :: IO ()
main = do
ref <- newIORef 0
bracket (openFile "clean-final.txt" WriteMode) (\h -> hClose h >> writeIORef ref 99) (\h -> hPutStrLn h "hello" >> writeIORef ref 7)
txt <- readFile "clean-final.txt"
putStr txt
v <- readIORef ref
print vKey points
- Bracket: bracket takes an acquire step, a release step, and a use step.
- Acquire: the acquire step gets the resource and hands it to the other steps.
- Release: the release step runs after the use step finishes.
- Failure: the release step also runs when the use step fails.
- Order: the use step runs first and the release step runs last.
In this example, the program opens a file inside bracket and tracks a box beside it. The use step writes a line and sets the box to 7. The release step closes the handle and sets the box to 99, and the program prints the file text and the final box value.
Note
bracket is the safe shape for handles and other resources that must be released.
Try it Yourself
Edit the code, then press Run.
Running is simulated · Haskell Playground
Exercise
What does bracket guarantee about its release step?