Copyright | (c) 2021 Xy Ren |
---|---|
License | BSD3 |
Maintainer | xy.r@outlook.com |
Stability | unstable |
Portability | non-portable (GHC only) |
Safe Haskell | None |
Language | Haskell2010 |
This module contains functions for interpreting effects. Most of the times you won't need to import this directly; the module Cleff reexports most of the functionalities.
This is an internal module and its API may change even between minor versions. Therefore you should be extra careful if you're to depend on this module.
Synopsis
- adjust :: forall es es'. (forall f. Rec f es' -> Rec f es) -> Eff es ~> Eff es'
- raise :: forall e es. Eff es ~> Eff (e ': es)
- raiseN :: forall es' es. KnownList es' => Eff es ~> Eff (es' ++ es)
- inject :: forall es' es. Subset es' es => Eff es' ~> Eff es
- subsume :: forall e es. e :> es => Eff (e ': es) ~> Eff es
- subsumeN :: forall es' es. Subset es' es => Eff (es' ++ es) ~> Eff es
- raiseUnder :: forall e' e es. Eff (e ': es) ~> Eff (e ': (e' ': es))
- raiseNUnder :: forall es' e es. KnownList es' => Eff (e ': es) ~> Eff (e ': (es' ++ es))
- raiseUnderN :: forall e es' es. KnownList es' => Eff (es' ++ es) ~> Eff (es' ++ (e ': es))
- raiseNUnderN :: forall es'' es' es. (KnownList es', KnownList es'') => Eff (es' ++ es) ~> Eff (es' ++ (es'' ++ es))
- class Handling esSend e es | esSend -> e es
- esSend :: Handling esSend e es => Env esSend
- type Handler e es = forall esSend. Handling esSend e es => e (Eff esSend) ~> Eff es
- type Translator e e' = forall esSend. e (Eff esSend) ~> e' (Eff esSend)
- interpret :: forall e es. Handler e es -> Eff (e ': es) ~> Eff es
- reinterpret :: forall e' e es. Handler e (e' ': es) -> Eff (e ': es) ~> Eff (e' ': es)
- reinterpret2 :: forall e' e'' e es. Handler e (e' ': (e'' ': es)) -> Eff (e ': es) ~> Eff (e' ': (e'' ': es))
- reinterpret3 :: forall e' e'' e''' e es. Handler e (e' ': (e'' ': (e''' ': es))) -> Eff (e ': es) ~> Eff (e' ': (e'' ': (e''' ': es)))
- reinterpretN :: forall es' e es. KnownList es' => Handler e (es' ++ es) -> Eff (e ': es) ~> Eff (es' ++ es)
- interpose :: forall e es. e :> es => Handler e es -> Eff es ~> Eff es
- impose :: forall e' e es. e :> es => Handler e (e' ': es) -> Eff es ~> Eff (e' ': es)
- imposeN :: forall es' e es. (KnownList es', e :> es) => Handler e (es' ++ es) -> Eff es ~> Eff (es' ++ es)
- transform :: forall e e' es. e' :> es => Translator e e' -> Eff (e ': es) ~> Eff es
- translate :: forall e e' es. Translator e e' -> Eff (e ': es) ~> Eff (e' ': es)
- toEff :: Handling esSend e es => Eff esSend ~> Eff es
- toEffWith :: forall esSend e es. Handling esSend e es => Handler e es -> Eff esSend ~> Eff es
- withFromEff :: Handling esSend e es => ((Eff es ~> Eff esSend) -> Eff esSend a) -> Eff es a
Trivial handling
raise :: forall e es. Eff es ~> Eff (e ': es) Source #
Lift a computation into a bigger effect stack with one more effect. For a more general version see raiseN
.
raiseN :: forall es' es. KnownList es' => Eff es ~> Eff (es' ++ es) Source #
Lift a computation into a bigger effect stack with arbitrarily more effects. This function requires
TypeApplications
.
inject :: forall es' es. Subset es' es => Eff es' ~> Eff es Source #
Lift a computation with a fixed, known effect stack into some superset of the stack.
subsume :: forall e es. e :> es => Eff (e ': es) ~> Eff es Source #
Eliminate a duplicate effect from the top of the effect stack. For a more general version see subsumeN
.
subsumeN :: forall es' es. Subset es' es => Eff (es' ++ es) ~> Eff es Source #
Eliminate several duplicate effects from the top of the effect stack. This function requires TypeApplications
.
raiseUnder :: forall e' e es. Eff (e ': es) ~> Eff (e ': (e' ': es)) Source #
Like raise
, but adds the new effect under the top effect. This is useful for transforming an interpreter
e'
into a reinterpreter :>
es => Eff
(e ': es) ~>
Eff
es
:Eff
(e ': es) ~>
Eff
(e' ': es)
myInterpreter :: Bar:>
es =>Eff
(Foo ': es)~>
Eff
es myInterpreter = ... myReinterpreter ::Eff
(Foo ': es)~>
Eff
(Bar ': es) myReinterpreter = myInterpreter.
raiseUnder
In other words,
reinterpret
h ==interpret
h .raiseUnder
However, note that this function is suited for transforming an existing interpreter into a reinterpreter; if you
want to define a reinterpreter from scratch, you should still prefer reinterpret
, which is both easier to use and
more efficient.
raiseNUnder :: forall es' e es. KnownList es' => Eff (e ': es) ~> Eff (e ': (es' ++ es)) Source #
Like raiseUnder
, but allows introducing multiple effects. This function requires TypeApplications
.
raiseUnderN :: forall e es' es. KnownList es' => Eff (es' ++ es) ~> Eff (es' ++ (e ': es)) Source #
Like raiseUnder
, but allows introducing the effect under multiple effects. This function requires
TypeApplications
.
raiseNUnderN :: forall es'' es' es. (KnownList es', KnownList es'') => Eff (es' ++ es) ~> Eff (es' ++ (es'' ++ es)) Source #
A generalization of both raiseUnderN
and raiseNUnder
, allowing introducing multiple effects under multiple
effects. This function requires TypeApplications
and is subject to serious type ambiguity; you most likely will
need to supply all three type variables explicitly.
Handler types
class Handling esSend e es | esSend -> e es Source #
The typeclass that denotes a handler scope, handling effect e
sent from the effect stack esSend
in the
effect stack es
.
You should not define instances for this typeclass whatsoever.
type Handler e es = forall esSend. Handling esSend e es => e (Eff esSend) ~> Eff es Source #
The type of an effect handler, which is a function that transforms an effect e
from an arbitrary effect stack
into computations in the effect stack es
.
type Translator e e' = forall esSend. e (Eff esSend) ~> e' (Eff esSend) Source #
The type of a simple transformation function from effect e
to e'
.
Interpreting effects
interpret :: forall e es. Handler e es -> Eff (e ': es) ~> Eff es Source #
Interpret an effect e
in terms of effects in the effect stack es
with an effect handler.
reinterpret :: forall e' e es. Handler e (e' ': es) -> Eff (e ': es) ~> Eff (e' ': es) Source #
Like interpret
, but adds a new effect e'
that can be used in the handler.
reinterpret2 :: forall e' e'' e es. Handler e (e' ': (e'' ': es)) -> Eff (e ': es) ~> Eff (e' ': (e'' ': es)) Source #
Like reinterpret
, but adds two new effects.
reinterpret3 :: forall e' e'' e''' e es. Handler e (e' ': (e'' ': (e''' ': es))) -> Eff (e ': es) ~> Eff (e' ': (e'' ': (e''' ': es))) Source #
Like reinterpret
, but adds three new effects.
reinterpretN :: forall es' e es. KnownList es' => Handler e (es' ++ es) -> Eff (e ': es) ~> Eff (es' ++ es) Source #
Like reinterpret
, but adds arbitrarily many new effects. This function requires TypeApplications
.
interpose :: forall e es. e :> es => Handler e es -> Eff es ~> Eff es Source #
Respond to an effect while being able to leave it unhandled (i.e. you can resend the effects in the handler).
impose :: forall e' e es. e :> es => Handler e (e' ': es) -> Eff es ~> Eff (e' ': es) Source #
Like interpose
, but allows to introduce one new effect to use in the handler.
imposeN :: forall es' e es. (KnownList es', e :> es) => Handler e (es' ++ es) -> Eff es ~> Eff (es' ++ es) Source #
Like impose
, but allows introducing arbitrarily many effects. This requires TypeApplications
.
Translating effects
Combinators for interpreting higher effects
toEffWith :: forall esSend e es. Handling esSend e es => Handler e es -> Eff esSend ~> Eff es Source #
Run a computation in the current effect stack, but handles the current effect inside the computation differently
by providing a new Handler
. This is useful for interpreting effects with local contexts, like Local
:
runReader :: r ->Eff
(Reader
r ': es)~>
Eff
es runReader x =interpret
(handle x) where handle :: r ->Handler
(Reader
r) es handle r = \caseAsk
->pure
rLocal
f m ->toEffWith
(handle $ f r) m