cleff-0.3.2.0: Fast and concise extensible effects
Copyright(c) 2021 Xy Ren
LicenseBSD3
Maintainerxy.r@outlook.com
Stabilityexperimental
Portabilitynon-portable (GHC only)
Safe HaskellTrustworthy
LanguageHaskell2010

Cleff.Mask

Description

 
Synopsis

Effect

data Mask :: Effect where Source #

An effect capable of masking and performing cleanup operations when an computation is interrupted. In particular, this effects allows the use of bracket.

Technical details

Regarding the nuances of bracket semantics, this effect uses the semantics of UnliftIO.Exception rather than Control.Exception. They are more sensible defaults and users can implement other semantics out of the primitive operations if they want to.

Constructors

Mask :: ((m ~> m) -> m a) -> Mask m a 
UninterruptibleMask :: ((m ~> m) -> m a) -> Mask m a 
OnException :: m a -> m b -> Mask m a 

High-level operations

bracket Source #

Arguments

:: Mask :> es 
=> Eff es a

The computation to run first, usually acquires a resource

-> (a -> Eff es c)

The computation to run after the main computation, usually cleans up

-> (a -> Eff es b)

The main computation that uses the resource

-> Eff es b 

Run a computation that acquires a resource (alloc), then a main computation using that resource, then a cleanup computation (dealloc). bracket guarantees that alloc and dealloc will always run, regardless of whether an exception is thrown in the main computation. Note that if an exception is thrown in the main computation, it will be rethrown after bracket finishes.

Technical details

Note that this function uses unliftio semantics: resource acquiring action is interruptibly masked while resource cleanup is uninterruptibleMasked. Most of the times, this will be what you want. Other functions in this module use unliftio semantics too.

bracketOnError Source #

Arguments

:: Mask :> es 
=> Eff es a

The computation to run first, usually acquires a resource

-> (a -> Eff es c)

The computation to run when the main computation throws an exception, usually cleans up

-> (a -> Eff es b)

The main computation that uses the resource

-> Eff es b 

Like bracket, but only runs cleanup if an exception is thrown in the main computation.

bracket_ :: Mask :> es => Eff es a -> Eff es c -> (a -> Eff es b) -> Eff es b Source #

Variant of bracket that does not pass the allocated resource to the cleanup action.

bracketOnError_ :: Mask :> es => Eff es a -> Eff es c -> (a -> Eff es b) -> Eff es b Source #

Variant of bracketOnError that does not pass the allocated resource to the cleanup action.

onError Source #

Arguments

:: Mask :> es 
=> Eff es a

The main computation that may throw an exception

-> Eff es b

The computation that runs when an exception is thrown

-> Eff es a 

Attach an action that runs if the main computation throws an exception. Note that this will rethrow the exception instead of returning to normal control flow.

The cleanup action is guaranteed not to be interrupted halfways.

finally Source #

Arguments

:: Mask :> es 
=> Eff es a

The main computation that may throw an exception

-> Eff es b

The computation that runs after the main computation, regardless of whether an exception is thrown

-> Eff es a 

Attach a cleanup action that will always run after a potentially throwing computation.

Primitive operations

mask :: Mask :> es => ((Eff es ~> Eff es) -> Eff es a) -> Eff es a Source #

Prevents a computation from receiving asynchronous exceptions, i.e. being interrupted by another thread. Also provides a function to restore receiving async exceptions for a computation.

However, some potentially blocking actions like takeMVar can still be interrupted, and for them also not to be interrupted in any case you'll need uninterruptibleMask. See mask for details.

uninterruptibleMask :: Mask :> es => ((Eff es ~> Eff es) -> Eff es a) -> Eff es a Source #

Prevents a computation from receiving asynchronous exceptions, even if there is an interruptible operation (operations that potentially deadlocks or otherwise blocks indefinitely). Therefore this function is potentially dangerous in the sense that it can make a thread both unresponsive and unkillable. See uninterruptibleMask for details.

onException Source #

Arguments

:: Mask :> es 
=> Eff es a

The main computation that may throw an exception

-> Eff es b

The computation that runs when an exception is thrown

-> Eff es a 

Like onError, but without uninterruptibleMasking the cleanup action, making it possible that a cleanup action is interrupted. Use onError is usually the safer option.

mask_ :: Mask :> es => Eff es a -> Eff es a Source #

Variant of mask that does not provide a restoring function.

uninterruptibleMask_ :: Mask :> es => Eff es a -> Eff es a Source #

Variant of uninterruptibleMask that does not provide a restoring function.

Interpretations

runMask :: Eff (Mask ': es) ~> Eff es Source #

Interpret the Mask effect in terms of primitive IO actions.