Safe Haskell | None |
---|---|
Language | Haskell2010 |
Synopsis
- data Bracket :: Effect where
- GeneralBracket :: m a -> (a -> ExitCase b -> m c) -> (a -> m b) -> Bracket m (b, c)
- data ExitCase a
- generalBracket :: Eff Bracket m => m a -> (a -> ExitCase b -> m c) -> (a -> m b) -> m (b, c)
- bracket :: Eff Bracket m => m a -> (a -> m c) -> (a -> m b) -> m b
- bracket_ :: Eff Bracket m => m a -> m c -> m b -> m b
- bracketOnError :: Eff Bracket m => m a -> (a -> m c) -> (a -> m b) -> m b
- onError :: Eff Bracket m => m a -> m b -> m a
- finally :: Eff Bracket m => m a -> m b -> m a
- bracketToIO :: (Carrier m, MonadMask m) => BracketToIOC m a -> m a
- runBracketLocally :: Carrier m => BracketLocallyC m a -> m a
- ignoreBracket :: Carrier m => IgnoreBracketC m a -> m a
- threadBracketViaClass :: forall t m a. Monad m => (RepresentationalT t, forall b. MonadMask b => MonadMask (t b)) => (forall x. Bracket m x -> m x) -> Bracket (t m) a -> t m a
- class MonadCatch m => MonadMask (m :: Type -> Type)
- type BracketToIOC = InterpretPrimC BracketToIOH Bracket
- type BracketLocallyC = InterpretPrimC BracketLocallyH Bracket
- type IgnoreBracketC = InterpretC IgnoreBracketH Bracket
Effects
data Bracket :: Effect where Source #
An effect for exception-safe acquisition and release of resources.
Bracket
is typically used as a primitive effect.
If you define a Carrier
that relies on a novel
non-trivial monad transformer t
, then you need to make
a
instance (if possible).
ThreadsEff
t Bracket
threadBracketViaClass
can help you with that.
The following threading constraints accept Bracket
:
GeneralBracket :: m a -> (a -> ExitCase b -> m c) -> (a -> m b) -> Bracket m (b, c) |
Instances
ThreadsEff (ExceptT e) Bracket Source # | |
Monoid s => ThreadsEff (WriterT s) Bracket Source # | |
ThreadsEff (StateT s) Bracket Source # | |
ThreadsEff (ReaderT i) Bracket Source # | |
ThreadsEff (StateT s) Bracket Source # | |
Monoid s => ThreadsEff (WriterT s) Bracket Source # | |
Monoid s => ThreadsEff (WriterT s) Bracket Source # | |
Monad m => MonadThrow (ViaAlg s Bracket m) Source # | |
Monad m => MonadCatch (ViaAlg s Bracket m) Source # | |
(Reifies s (ReifiedEffAlgebra Bracket m), Monad m) => MonadMask (ViaAlg s Bracket m) Source # | |
Defined in Control.Effect.Type.Bracket mask :: ((forall a. ViaAlg s Bracket m a -> ViaAlg s Bracket m a) -> ViaAlg s Bracket m b) -> ViaAlg s Bracket m b # uninterruptibleMask :: ((forall a. ViaAlg s Bracket m a -> ViaAlg s Bracket m a) -> ViaAlg s Bracket m b) -> ViaAlg s Bracket m b # generalBracket :: ViaAlg s Bracket m a -> (a -> ExitCase b -> ViaAlg s Bracket m c) -> (a -> ViaAlg s Bracket m b) -> ViaAlg s Bracket m (b, c) # |
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
).
Actions
generalBracket :: Eff Bracket m => m a -> (a -> ExitCase b -> m c) -> (a -> m b) -> m (b, c) Source #
bracketOnError :: Eff Bracket m => m a -> (a -> m c) -> (a -> m b) -> m b Source #
Interpretations
bracketToIO :: (Carrier m, MonadMask m) => BracketToIOC m a -> m a Source #
Run a Bracket
by effect that protects against
any abortive computation of any effect, as well
as any IO exceptions and asynchronous exceptions.
Derivs
(BracketToIOC
m) =Bracket
':Derivs
m
Prims
(BracketToIOC
m) =Bracket
':Prims
m
runBracketLocally :: Carrier m => BracketLocallyC m a -> m a Source #
Run a Bracket
effect that protects against
any abortive computations of purely local effects
-- i.e. effects interpreted before runBracketLocally
that are not interpreted in terms of the final monad
nor other effects interpreted after runBracketLocally
.
This does not protect against IO exceptions of any kind, including asynchronous exceptions.
This is more situational compared to bracketToIO
,
but can be useful. For an example, see the wiki.
Derivs
(BracketLocallyC
m) =Bracket
':Derivs
m
Prims
(BracketLocallyC
m) =Bracket
':Prims
m
ignoreBracket :: Carrier m => IgnoreBracketC m a -> m a Source #
Run a Bracket
effect by ignoring it, providing no protection at all.
Derivs
(IgnoreBracketC
m) =Bracket
':Derivs
m
Prims
(IgnoreBracketC
m) =Prims
m
Threading utilities
threadBracketViaClass :: forall t m a. Monad m => (RepresentationalT t, forall b. MonadMask b => MonadMask (t b)) => (forall x. Bracket m x -> m x) -> Bracket (t m) a -> t m a Source #
A valid definition of threadEff
for a
instance,
given that ThreadsEff
t Bracket
t
lifts
.MonadMask
BEWARE: threadBracketViaClass
is only safe if the implementation of
generalBracket
for t m
only makes use of generalBracket
for m
,
and no other methods of MonadThrow
, MonadCatch
, or MonadMask
.
MonadMask
class MonadCatch m => MonadMask (m :: Type -> Type) #
A class for monads which provide for the ability to account for all possible exit points from a computation, and to mask asynchronous exceptions. Continuation-based monads are invalid instances of this class.
Instances should ensure that, in the following code:
fg = f `finally` g
The action g
is called regardless of what occurs within f
, including
async exceptions. Some monads allow f
to abort the computation via other
effects than throwing an exception. For simplicity, we will consider aborting
and throwing an exception to be two forms of "throwing an error".
If f
and g
both throw an error, the error thrown by fg
depends on which
errors we're talking about. In a monad transformer stack, the deeper layers
override the effects of the inner layers; for example, ExceptT e1 (Except
e2) a
represents a value of type Either e2 (Either e1 a)
, so throwing both
an e1
and an e2
will result in Left e2
. If f
and g
both throw an
error from the same layer, instances should ensure that the error from g
wins.
Effects other than throwing an error are also overriden by the deeper layers.
For example, StateT s Maybe a
represents a value of type s -> Maybe (a,
s)
, so if an error thrown from f
causes this function to return Nothing
,
any changes to the state which f
also performed will be erased. As a
result, g
will see the state as it was before f
. Once g
completes,
f
's error will be rethrown, so g
' state changes will be erased as well.
This is the normal interaction between effects in a monad transformer stack.
By contrast, lifted-base's
version of finally
always discards all of g
's non-IO effects, and g
never sees any of f
's non-IO effects, regardless of the layer ordering and
regardless of whether f
throws an error. This is not the result of
interacting effects, but a consequence of MonadBaseControl
's approach.
Instances
Carriers
type BracketToIOC = InterpretPrimC BracketToIOH Bracket Source #
type BracketLocallyC = InterpretPrimC BracketLocallyH Bracket Source #
type IgnoreBracketC = InterpretC IgnoreBracketH Bracket Source #