in-other-words-0.1.0.0: A higher-order effect system where the sky's the limit

Control.Effect.Exceptional

Synopsis

# Effects

data Exceptional eff exc m a Source #

An effect that allows for the safe use of an effect eff that may throw exceptions of the type exc by forcing the user to eventually catch those exceptions at some point of the program.

The main combinator of Exceptional is catching.

This could be unsafe in the presence of Conc. If you use catching on a computation that:

• Spawns an asynchronous computation
• Throws an exception inside the asynchronous computation from a use of eff
• Returns the Async of that asynchronous computation

Then waiting on that Async outside of the catching will throw that exception without it being caught.

type SafeError exc = Exceptional (Throw exc) exc Source #

A particularly useful specialization of Exceptional, for gaining restricted access to an Error exc effect. Main combinators are catchSafe and trySafe.

# Actions

catching :: forall eff exc m a. Eff (Exceptional eff exc) m => ExceptionallyC eff exc m a -> (exc -> m a) -> m a Source #

Gain access to eff and Catch exc within a region, but only if you're ready to handle any unhandled exception e :: exc that may arise from the use of eff within that region.

For example:

-- A part of the program unknowing and uncaring that the use of SomeEffect
-- may throw exceptions.
uncaringProgram :: Eff SomeEffect m => m String
uncaringProgram = do
doSomeThing
doSomeOtherThing

caringProgram :: Eff (Exceptional SomeEffect SomeEffectExc) m => m String
caringProgram =
catching @eff uncaringProgram (\(exc :: SomeEffectExc) -> handlerForSomeEffectExc exc)


trying :: forall eff exc m a. Eff (Exceptional eff exc) m => ExceptionallyC eff exc m a -> m (Either exc a) Source #

Gain access to eff within a region. If any use of eff within that region throws an unhandled exception e :: exc, then this returns Left e.

throwing :: forall eff exc m a. Effs [Exceptional eff exc, Throw exc] m => ExceptionallyC eff exc m a -> m a Source #

Gain access to eff within a region, rethrowing any exception e :: exc that may occur from the use of eff within that region.

catchSafe :: forall exc m a. Eff (SafeError exc) m => ExceptionallyC (Throw exc) exc m a -> (exc -> m a) -> m a Source #

Gain access to Error exc within a region, but only if you're ready to handle any unhandled exception e :: exc that may arise from within that region.

trySafe :: forall exc m a. Eff (SafeError exc) m => ExceptionallyC (Throw exc) exc m a -> m (Either exc a) Source #

Gain access to Error exc within a region. If any unhandled exception e :: exc is thrown within that region, then this returns Left e.

# Interpretations

runExceptional :: forall eff exc m a. (Member eff (Derivs m), Eff (Catch exc) m) => ExceptionalC eff exc m a -> m a Source #

Run an Exceptional eff exc effect if both eff and Catch exc are part of the effect stack.

In order for this to be safe, you must ensure that the Catch exc catches all exceptions that arise from the use of eff and that only uses of eff throws those exceptions. Otherwise, the use of catching is liable to catch exceptions not arising from uses of eff, or fail to catch exceptions that do arise from uses of eff.

runExceptionalJust :: forall eff smallExc bigExc m a. (Member eff (Derivs m), Eff (Error bigExc) m) => (bigExc -> Maybe smallExc) -> InterpretReifiedC (Exceptional eff smallExc) m a -> m a Source #

Run an Exceptional eff exc effect if eff is part of the effect stack, provided a function that identifies the kind of exceptions that may arise from the use of eff.

In order for this to be safe, you must ensure that the function identifies all exceptions that arise from the use of eff and that only uses of eff throws those exceptions. Otherwise, the use of catching is liable to catch other exceptions not arising from uses of eff, or fail to catch exceptions that do arise from uses of eff.

The type of this interpreter is higher-rank, as it makes use of InterpretReifiedC. This makes runExceptionalJust difficult to use partially applied; for example, you can't compose it using .. You may prefer the simpler, but less performant, runExceptionalJustSimple.

safeErrorToError :: forall exc m a. Eff (Error exc) m => SafeErrorToErrorC exc m a -> m a Source #

Run a SafeError exc effect by transforming it into an Error exc effect.

runSafeError :: forall e m a p. (Carrier m, Threaders '[ErrorThreads] m p) => SafeErrorC e m a -> m a Source #

Run a SafeError e effect purely.

Derivs (SafeErrorC e m) = SafeError e ': Prims m
Prims (SafeErrorC e m) = Optional ((->) e) ': Prims m

safeErrorToIO :: forall e m a. (Eff (Embed IO) m, MonadCatch m) => SafeErrorToIOC e m a -> m a Source #

Runs a SafeError e effect by making use of IO exceptions.

Derivs (SafeErrorToIOC e m) = SafeError e ': Derivs m
Prims (SafeErrorToIOC e m) = Optional ((->) SomeException) ': Prims m

This has a higher-rank type, as it makes use of SafeErrorToIOC. This makes safeErrorToIO very difficult to use partially applied. In particular, it can't be composed using ..

If performance is secondary, consider using the slower safeErrorToIOSimple, which doesn't have a higher-rank type.

safeErrorToErrorIO :: forall e m a. Effs '[Embed IO, ErrorIO] m => SafeErrorToErrorIOC e m a -> m a Source #

Runs a SafeError e effect by transforming it into ErrorIO and Embed IO.

This has a higher-rank type, as it makes use of SafeErrorToErrorIOC. This makes safeErrorToErrorIO very difficult to use partially applied. In particular, it can't be composed using ..

If performance is secondary, consider using the slower safeErrorToErrorIOSimple, which doesn't have a higher-rank type.

# Simple variants of interpretations

runExceptionalJustSimple :: forall eff smallExc bigExc m a p. (Member eff (Derivs m), Eff (Error bigExc) m, Threaders '[ReaderThreads] m p) => (bigExc -> Maybe smallExc) -> InterpretSimpleC (Exceptional eff smallExc) m a -> m a Source #

Run an Exceptional eff exc effect if eff is part of the effect stack, provided a function that identifies the kind of exceptions that may arise from the use of eff.

In order for this to be safe, you must ensure that the function identifies all exceptions that arise from the use of eff and that only uses of eff throws those exceptions. Otherwise, the use of catching is liable to catch exceptions not arising from uses of eff, or fail to catch exceptions that do arise from uses of eff.

This is a less performant version of runExceptionalJust, but doesn't have a higher-rank type. This makes runExceptionalJustSimple much easier to use partially applied.

safeErrorToIOSimple :: forall e m a p. (Eff (Embed IO) m, MonadCatch m, Threaders '[ReaderThreads] m p) => SafeErrorToIOSimpleC e m a -> m a Source #

Runs a SafeError e effect by making use of IO exceptions.

Derivs (SafeErrorToIOSimpleC e m) = SafeError e ': Derivs m
Prims (SafeErrorToIOSimpleC e m) = Optional ((->) SomeException) ': Prims m

This is a less performant version of safeErrorToIO that doesn't have a higher-rank type, making it much easier to use partially applied.

safeErrorToErrorIOSimple :: forall e m a p. (Effs '[ErrorIO, Embed IO] m, Threaders '[ReaderThreads] m p) => SafeErrorToErrorIOSimpleC e m a -> m a Source #

Runs a SafeError e effect by transforming it into ErrorIO and Embed IO.

This is a less performant version of safeErrorToErrorIO that doesn't have a higher-rank type, making it much easier to use partially applied.

class (forall e. Threads (ExceptT e) p) => ErrorThreads p Source #

ErrorThreads accepts the following primitive effects:

• Regional s
• Optional s (when s is a functor)
• BaseControl b
• Unravel p
• ListenPrim s (when s is a Monoid)
• WriterPrim s (when s is a Monoid)
• ReaderPrim i
• Mask
• Bracket
• Fix

#### Instances

Instances details
 (forall e. Threads (ExceptT e) p) => ErrorThreads p Source # Instance detailsDefined in Control.Effect.Internal.Error

A class for monads which allow exceptions to be caught, in particular exceptions which were thrown by throwM.

Instances should obey the following law:

catch (throwM e) f = f e

Note that the ability to catch an exception does not guarantee that we can deal with all possible exit points from a computation. Some monads, such as continuation-based stacks, allow for more than just a success/failure strategy, and therefore catch cannot be used by those monads to properly implement a function such as finally. For more information, see MonadMask.

Minimal complete definition

catch

#### Instances

Instances details

# Carriers

data ExceptionallyC (eff :: Effect) (exc :: *) m a Source #

#### Instances

Instances details