HORIZON HASKELLDocslts/ghc-10.0.xfc4e5982026-10-11Search names, modules, packages, or :: a typeCtrl K

GHC 10.0.0.20260917 · lts/ghc-10.0.x · fc4e598 · 2026-10-11

Moduleextensible-effects-5.0.0.1Haskell2010

Control.Eff

A monadic library for implementing effectful computation in a modular way.

This module provides the Eff monad - the base type for all effectful computation. The Member typeclass is the main interface for describing which effects are necessary for a given function.

Consult the Control.Eff.QuickStart module and the readme for gentle introductions.

To use extensible effects effectively some language extensions are necessary/recommended.

{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE MonoLocalBinds #-}
  • 5 types
  • 2 classes
  • 5 values

Effect type

2 declarations
valuerun :: Eff '[] w -> w
#

Get the result from a pure computation

A pure computation has type Eff '[] a. The empty effect-list indicates that no further effects need to be handled.

datadata Eff (r :: [Type -> Type]) a
#

The monad that all effects in this library are based on.

An effectful computation is a value of type `Eff r a`. In this signature, r is a type-level list of effects that are being requested and need to be handled inside an effectful computation. a is the computation's result similar to other monads.

A computation's result can be retrieved via the run function. However, all effects used in the computation need to be handled by the use of the effects' run* functions before unwrapping the final result. For additional details, see the documentation of the effects you are using.

Instances35MonadBase, MonadBaseControl, Monad, Functor, Applicative, Alternative, …
  • Alternative f => Handle NDet r a (Eff r' (f w))Defined in extensible-effects-5.0.0.1 · Control.Eff.Logic.NDet

    Given a callback and NDet requests respond to them. Note that this makes explicit that we rely on f to have enough room to store all possibilities.

  • Alternative f => Handle NDet r a ([Eff r a] -> Eff r' (f w))Defined in extensible-effects-5.0.0.1 · Control.Eff.Logic.NDet

    More performant handler; uses reified job queue

  • (Monad b, MonadBase b m, Lifted m r) => MonadBase b (Eff r)Defined in extensible-effects-5.0.0.1 · Control.Eff.Internal
  • MonadBase m m => MonadBaseControl m (Eff '[Lift m])Defined in extensible-effects-5.0.0.1 · Control.Eff.Internal
  • (MonadBase m m, LiftedBase m r) => MonadBaseControl m (Eff (Exc e ': r))Defined in extensible-effects-5.0.0.1 · Control.Eff.Exception
  • (MonadBase m m, LiftedBase m r) => MonadBaseControl m (Eff (Fresh ': r))Defined in extensible-effects-5.0.0.1 · Control.Eff.Fresh
  • (MonadBase m m, LiftedBase m r) => MonadBaseControl m (Eff (NDet ': r))Defined in extensible-effects-5.0.0.1 · Control.Eff.Logic.NDet
  • (MonadBase m m, LiftedBase m r) => MonadBaseControl m (Eff (State s ': r))Defined in extensible-effects-5.0.0.1 · Control.Eff.State.Lazy
  • (MonadBase m m, LiftedBase m r) => MonadBaseControl m (Eff (OnDemandState s ': r))Defined in extensible-effects-5.0.0.1 · Control.Eff.State.OnDemand
  • (MonadBase m m, LiftedBase m r) => MonadBaseControl m (Eff (State s ': r))Defined in extensible-effects-5.0.0.1 · Control.Eff.State.Strict
  • (MonadBase m m, LiftedBase m r) => MonadBaseControl m (Eff (Writer w ': r))Defined in extensible-effects-5.0.0.1 · Control.Eff.Writer.Lazy
  • (MonadBase m m, LiftedBase m r) => MonadBaseControl m (Eff (Writer w ': r))Defined in extensible-effects-5.0.0.1 · Control.Eff.Writer.Strict
  • (MonadBase m m, LiftedBase m s) => MonadBaseControl m (Eff (Reader e ': s))Defined in extensible-effects-5.0.0.1 · Control.Eff.Reader.Lazy
  • (MonadBase m m, LiftedBase m s) => MonadBaseControl m (Eff (Reader e ': s))Defined in extensible-effects-5.0.0.1 · Control.Eff.Reader.Strict
  • Monad (Eff r)Defined in extensible-effects-5.0.0.1 · Control.Eff.Internal
  • Functor (Eff r)Defined in extensible-effects-5.0.0.1 · Control.Eff.Internal
  • Applicative (Eff r)Defined in extensible-effects-5.0.0.1 · Control.Eff.Internal
  • Member NDet r => Alternative (Eff r)Defined in extensible-effects-5.0.0.1 · Control.Eff.Logic.NDet · orphan
  • Member NDet r => MonadPlus (Eff r)Defined in extensible-effects-5.0.0.1 · Control.Eff.Logic.NDet · orphan

    Mapping of NDet requests to MonadPlus. We obey the following laws (taken from the Backtr and @LogicT papers):

    mzero >>= f = mzero                               -- (L1)
    mzero `mplus` m = m                               -- (L2)
    m `mplus` mzero = m                               -- (L3)
    m `mplus` (n `mplus` o) = (m `mplus` n) `mplus` o -- (L4)
    (m `mplus` n) >>= k = (m >>= k) `mplus` (n >>= k) -- (L5)
    • L1 is the left-zero law for mzero

    • L2, L3, L4 are the Monoid laws

    NOTE that we do not obey the right-zero law for mzero. Specifically, we do not obey:

    m >> mzero  = mzero
  • (MonadIO m, Lifted m r) => MonadIO (Eff r)Defined in extensible-effects-5.0.0.1 · Control.Eff.Internal
  • Member NDet r => MSplit (Eff r)Defined in extensible-effects-5.0.0.1 · Control.Eff.Logic.NDet · orphan

    We implement LogicT, the non-determinism reflection, of which soft-cut is one instance. See the LogicT paper for an explanation.

  • Relay (Eff r w) rDefined in extensible-effects-5.0.0.1 · Control.Eff.Internal
  • Handle (Program f) r a (Intrprtr f r' -> Eff r' a)Defined in extensible-effects-5.0.0.1 · Control.Eff.Operational

    Given a continuation and a program, interpret it Usually, we have r ~ [Program f : r']

  • Handle (Yield a b) (Yield a b ': r) w (Eff r (Y r b a))Defined in extensible-effects-5.0.0.1 · Control.Eff.Coroutine

    Given a continuation and a request, respond to it

  • type StM (Eff '[Lift m]) a = aDefined in extensible-effects-5.0.0.1 · Control.Eff.Internal
  • type StM (Eff (Exc e ': r)) a = StM (Eff r) (Either e a)Defined in extensible-effects-5.0.0.1 · Control.Eff.Exception
  • type StM (Eff (Fresh ': r)) a = StM (Eff r) (a, Int)Defined in extensible-effects-5.0.0.1 · Control.Eff.Fresh
  • type StM (Eff (NDet ': r)) a = StM (Eff r) [a]Defined in extensible-effects-5.0.0.1 · Control.Eff.Logic.NDet
  • type StM (Eff (Reader e ': s)) a = StM (Eff s) aDefined in extensible-effects-5.0.0.1 · Control.Eff.Reader.Lazy
  • type StM (Eff (Reader e ': s)) a = StM (Eff s) aDefined in extensible-effects-5.0.0.1 · Control.Eff.Reader.Strict
  • type StM (Eff (State s ': r)) a = StM (Eff r) (a, s)Defined in extensible-effects-5.0.0.1 · Control.Eff.State.Lazy
  • type StM (Eff (OnDemandState s ': r)) a = StM (Eff r) (a, s)Defined in extensible-effects-5.0.0.1 · Control.Eff.State.OnDemand
  • type StM (Eff (State s ': r)) a = StM (Eff r) (a, s)Defined in extensible-effects-5.0.0.1 · Control.Eff.State.Strict
  • type StM (Eff (Writer w ': r)) a = StM (Eff r) (a, [w])Defined in extensible-effects-5.0.0.1 · Control.Eff.Writer.Lazy
  • type StM (Eff (Writer w ': r)) a = StM (Eff r) (a, [w])Defined in extensible-effects-5.0.0.1 · Control.Eff.Writer.Strict

Lift IO computations

8 declarations
valuelift :: Lifted m r => m a -> Eff r a
#

embed an operation of type `m a` into the Eff monad when Lift m is in a part of the effect-list.

valuerunLift :: Monad m => Eff '[Lift m] w -> m w
#

The handler of Lift requests. It is meant to be terminal: we only allow a single Lifted Monad. Note, too, how this is different from other handlers.

valuecatchesDynE :: Lifted IO r => Eff r a -> [HandlerDynE r a] -> Eff r a
#

Catch multiple dynamic exceptions. The implementation follows that in Control.Exception almost exactly. Not yet tested. Could this be useful for control with cut?

newtypenewtype Lift (m :: k -> Type) (a :: k)
#

Lifting: emulating monad transformers

Constructors

Instances3MonadBaseControl, Handle, StM
  • MonadBase m m => MonadBaseControl m (Eff '[Lift m])Defined in extensible-effects-5.0.0.1 · Control.Eff.Internal
  • Monad m => Handle (Lift m) r a (m k)Defined in extensible-effects-5.0.0.1 · Control.Eff.Internal

    Handle lifted requests by running them sequentially

  • type StM (Eff '[Lift m]) a = aDefined in extensible-effects-5.0.0.1 · Control.Eff.Internal
typetype Lifted (m :: Type -> Type) (r :: [Type -> Type]) = SetMember Lift (Lift m) r
#

A convenient alias to SetMember Lift (Lift m) r, which allows us to assert that the lifted type occurs ony once in the effect list.

Effect list

3 declarations
classclass FindElem t r => Member (t :: Type -> Type) (r :: [Type -> Type]) where
#

Typeclass that asserts that effect t is contained inside the effect-list r.

The FindElem typeclass is an implementation detail and not required for using the effect list or implementing custom effects.

Instances2Member
  • FindElem t r => Member t rDefined in extensible-effects-5.0.0.1 · Data.OpenUnion
  • t ~ s => Member t '[s]Defined in extensible-effects-5.0.0.1 · Data.OpenUnion

    Explicit type-level equality condition is a dirty hack to eliminate the type annotation in the trivial case, such as run (runReader () get).

    There is no ambiguity when finding instances for Member t (a ': b ': r), which the second instance is selected.

    The only case we have to concerned about is Member t '[s]. But, in this case, values of definition is the same (if present), and the first one is chosen according to GHC User Manual, since the latter one is incoherent. This is the optimal choice.

classclass Member t r => SetMember (tag :: k -> Type -> Type) (t :: Type -> Type) (r :: [Type -> Type]) | tag r -> t
#

This class is used for emulating monad transformers

Instances1SetMember
  • (EQU t1 t2 p, MemberU' p tag t1 (t2 ': r)) => SetMember tag t1 (t2 ': r)Defined in extensible-effects-5.0.0.1 · Data.OpenUnion
familytype family (<::) (ms :: [Type -> Type]) (r :: [Type -> Type]) :: Constraint where
#

A useful operator for reducing boilerplate in signatures.

The following lines are equivalent.

(Member (Exc e) r, Member (State s) r) => ...
[ Exc e, State s ] r = ...

Equations