🎓 A1Learner
🔍
0 of 50 lessons completed

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 v

Bracket 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 txt

Release 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 v

Key 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?