Safe Haskell | Safe-Inferred |
---|---|
Language | Haskell2010 |
LazyBracket
Description
This module provides variants of the bracket
function that delay the
acquisition of the resource until it's used for the first time. If
the resource is never used, it will never be acquired.
A trivial example. This bracket code with a faulty acquisition doesn't throw an exception because the resource is never accessed:
>>>
:{
lazyBracket (throwIO (userError "oops")) (\_ -> pure ()) \Resource {} -> do pure () :}
But this code does:
>>>
:{
lazyBracket (throwIO (userError "oops")) (\_ -> pure ()) \Resource {accessResource} -> do _ <- accessResource pure () :} *** Exception: user error (oops)
To be even more lazy, certain kinds of operations on the resource do not trigger acquisition: instead, they are stashed and applied once the resource has been acquired for other reasons.
Look at the sequence of ouput messages here:
>>>
:{
lazyBracket (putStrLn "acquired!") (\() -> putStrLn "released!") \Resource {accessResource, controlResource} -> do controlResource \() -> putStrLn "control op 1 - delayed" putStrLn "before acquiring" _ <- accessResource putStrLn "after acquiring" controlResource \() -> putStrLn "control op 2 - immediately executed" pure () :} before acquiring acquired! control op 1 - delayed after acquiring control op 2 - immediately executed released!
If we never access the resource, the release function and the stashed operations are not executed:
>>>
:{
lazyBracket (putStrLn "acquired!") (\() -> putStrLn "released!") \Resource {accessResource, controlResource} -> do controlResource \() -> putStrLn "control op 1 - never happens" pure () :}
Synopsis
- lazyBracket :: (MonadIO m, MonadMask m) => IO a -> (a -> m c) -> (Resource a -> m b) -> m b
- lazyGeneralBracket :: forall m a b c. (MonadIO m, MonadMask m) => IO a -> (a -> ExitCase b -> m c) -> (Resource a -> m b) -> m (b, Maybe c)
- lazyGeneralBracket_ :: forall m a b c. (MonadIO m, MonadMask m) => IO a -> (a -> ExitCase b -> m c) -> (Resource a -> m b) -> m b
- data Resource a = Resource {
- accessResource :: IO a
- controlResource :: (a -> IO ()) -> IO ()
- data ExitCase a
Lazy brackets that delay resource acquisition.
Arguments
:: (MonadIO m, MonadMask m) | |
=> IO a | Computation to run to acquire the resource. |
-> (a -> m c) | Computation to run to release the resource, in case it was acquired. |
-> (Resource a -> m b) | Computation to run in-between (might trigger resource acquisition). |
-> m b | Returns the value from the in-between computation |
A version of bracket
for which the resource is not
acquired at the beginning, but the first time it's used in the main callback.
If the resource is never used, it won't be acquired.
Arguments
:: forall m a b c. (MonadIO m, MonadMask m) | |
=> IO a | Computation to run to acquire the resource |
-> (a -> ExitCase b -> m c) | Computation to run to release the resource, in case it was acquired The release function has knowledge of how the main callback was exited: by normal completion, by a runtime exception, or otherwise aborted. This can be useful when acquiring resources from resource pools, to decide whether to return the resource to the pool or to destroy it. |
-> (Resource a -> m b) | Computation to run in-between (might trigger resource acquisition) |
-> m (b, Maybe c) | Returns the value from the in-between computation, and also of the release computation, if it took place. |
A version of generalBracket
for which the resource is not
acquired at the beginning, but the first time it's used in the main callback.
If the resource is never used, it won't be acquired.
Arguments
:: forall m a b c. (MonadIO m, MonadMask m) | |
=> IO a | computation to run to acquire the resource |
-> (a -> ExitCase b -> m c) | computation to run to release the resource, in case it was acquired |
-> (Resource a -> m b) | computation to run in-between (might trigger resource acquisition) |
-> m b | returns the value from the in-between computation. |
Slightly simpler version of lazyGeneralBracket
that doesn't return the result of the
release computation.
Resource wrapper.
A wrapper type over resources that delays resource acquisition.
Because one must be careful with the kinds of functions that are passed to controlResource
,
it might be a good idea to define convenience wrappers over Resource
with
more restricted interfaces.
Constructors
Resource | |
Fields
|
Re-exports.
A MonadMask
computation may either succeed with a value, abort with an
exception, or abort for some other reason. For example, in ExceptT e IO
you can use throwM
to abort with an exception (ExitCaseException
) or
throwE
to abort with a value of type e
(ExitCaseAbort
).
Constructors
ExitCaseSuccess a | |
ExitCaseException SomeException | |
ExitCaseAbort |