liveBook · Manning

Bracket function

As explained in Functional Design and Architecture: Examples in Haskell

The bracket pattern is a resource-management pattern that acquires a resource, runs an action with it, and ensures disposal after the action finishes.

Resource management becomes unsafe when acquisition, use, and disposal are scattered across application code. The bracket pattern centralizes that lifetime: acquire one resource, run an action, and dispose of the resource afterward. section 10.0 section 10.3.2

The bracket function accepts initialization, release, and utilization functions. Keep one resource per bracket. For several resources, nest brackets so each acquired resource has an individual disposal scope; if an action fails, cleanup runs before the exception is rethrown. section 10.3.2 section 10.4

Sentry logging service

A main function can bracket Sentry initialization with its disposal and application action: initialize the service, run doSomething with it, then deinitialize it. Applying one bracket per resource avoids partially initialized bundles and long-lived resources left behind after failures. section 10.3.2

bracket

 :: IO resource                -- acquire the resource
 -> (resource -> IO ())        -- release the resource
 -> (resource -> IO result)    -- utilize the resource
 -> IO result                  -- return the result

Use the type signature to see the bracket contract: acquire a resource, release it, use it, and return the action result. section 10.3.2

main = 
 bracket initResourceA deinitResourceA (\resourceA ->
 bracket initResourceB deinitResourceB (\resourceB ->
 bracket initResourceC deinitResourceC (\resourceC ->
   utilizeMyResources (resourceA, resourceB, resourceC)
 )))

Nested brackets make resource lifetimes explicit and ensure outer resources remain available for cleanup when inner actions fail. section 10.3.2

How Functional Design and Architecture: Examples in Haskell covers it

How deep it goes
Defines three callbacks, demonstrates nested cleanup, and notes exception behavior while deferring tricky exception mechanisms.
Examples
Uses Sentry logging and nested acquisition of ResourceA, ResourceB, and ResourceC.
What you can do after
Apply resource lifetimes through Haskell’s bracket function and compose cleanup for multiple resources.
How it connects
Connects resource management with exceptions, concurrency, RAII, and functional programming.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Functional Design and Architecture: Examples in Haskell. The section links point to the parts of the book it draws on.