fractal-layer: Composable resource management and dependency injection

[ bsd3, control, library ] [ Propose Tags ] [ Report a vulnerability ]

Composable, type-safe resource management and dependency injection for Haskell, inspired by ZIO's ZLayer. . Break your application's god record into independent layers, each declaring exactly what it needs and what it produces. Layers compose via Arrow, Category, and Alternative, with automatic resource cleanup, concurrent initialisation, and singleton service caching.


[Skip to Readme]

Downloads

Maintainer's Corner

Package maintainers

For package maintainers and hackage trustees

Candidates

  • No Candidates
Versions [RSS] 0.1.0.0
Change log CHANGELOG.md
Dependencies aeson (>=2.0 && <3), base (>=4.17.0.0 && <5), containers (>=0.6 && <1), hashable (>=1.4 && <2), mtl (>=2.2 && <3), profunctors (>=5.6 && <6), resourcet (>=1.2 && <2), selective (>=0.5 && <1), text (>=2.0 && <3), time (>=1.12 && <2), transformers (>=0.5 && <0.7), unliftio (>=0.2 && <1), unordered-containers (>=0.2 && <1) [details]
Tested with ghc ==9.10.3
License BSD-3-Clause
Author Ian Duncan
Maintainer ian@mercury.com
Uploaded by IanDuncan at 2026-03-18T18:24:35Z
Category Control
Source repo head: git clone https://github.com/iand675/fractal(fractal-layer)
Distributions
Downloads 0 total (0 in the last 30 days)
Rating (no votes yet) [estimated by Bayesian average]
Your Rating
  • λ
  • λ
  • λ
Status Docs available [build log]
Last success reported on 2026-03-18 [all 1 reports]

Readme for fractal-layer-0.1.0.0

[back to package description]

fractal-layer

Composable, type-safe resource management and dependency injection for Haskell, inspired by ZIO's ZLayer.

The idea

A Layer m deps env is a recipe for building a value of type env from dependencies deps, with automatic resource cleanup. Think of it as deps -> m env plus a finaliser that runs when the scope ends.

configLayer :: Layer IO () Config
dbLayer     :: Layer IO Config Database
cacheLayer  :: Layer IO Config Cache

Each layer declares exactly what it needs and what it produces. The compiler enforces correct wiring at every composition site.

Composition

Layers compose via standard Haskell typeclasses:

-- sequential: config feeds into db and web
appLayer :: Layer IO () (Config, (Database, WebServer))
appLayer = configLayer >>> (dbLayer &&& webLayer)

-- fallback: try remote, fall back to local
dbLayer :: Layer IO Config Database
dbLayer = remotePostgres <|> localSQLite

(&&&) runs both sides concurrently. (<|>) cleans up the failed branch before trying the fallback.

Services (shared singletons)

When two layers need the same expensive resource, Service gives you at-most-once initialisation with automatic sharing:

poolService :: Service IO Config ConnectionPool
poolService = mkService $ do
  cfg <- ask
  resource (createPool cfg) drainPool

webLayer :: Layer IO Config WebServer
webLayer = do
  pool <- service poolService   -- creates the pool
  resource (startWeb pool) stopWeb

apiLayer :: Layer IO Config ApiServer
apiLayer = do
  pool <- service poolService   -- reuses the same pool
  resource (startApi pool) stopApi

Running

main :: IO ()
main = withLayer () appLayer $ \(cfg, (db, ws)) ->
  serveRequests ws
  -- all resources released here, in reverse acquisition order

Documentation

See the Haddock docs on Fractal.Layer for a full walkthrough with examples.

License

BSD-3-Clause