Copyright | (c) 2024 Sayo Koyoneda |
---|---|
License | MPL-2.0 (see the LICENSE file) |
Maintainer | ymdfield@outlook.jp |
Safe Haskell | None |
Language | GHC2021 |
Heftia is an extensible effects library that generalizes "Algebraic Effects and Handlers" to higher-order effects, providing users with maximum flexibility and delivering standard and reasonable speed. In its generalization, the focus is on ensuring predictable results based on simple, consistent semantics, while preserving soundness.
Basic Usage
The following is an example of defining, using, and interpreting the first-order
effect Log
for logging and the higher-order effect Span
for representing
named spans in a program.
import Control.Monad.Hefty import Prelude hiding (log, span) data Log a where Log :: String -> Log ()makeEffectF
[''Log] data Span m (a :: Type) where Span :: String -> m a -> Span m amakeEffectH
[''Span] runLog :: (IO
<|
ef) =>Eff
eh (Log ': ef)~>
Eff
eh ef runLog =interpret
\(Log msg) -> liftIO $ putStrLn $ "[LOG] " <> msg runSpan :: (IO
<|
ef) =>Eff
(Span ': eh) ef~>
Eff
eh ef runSpan =interpretH
\(Span name m) -> doliftIO
$putStrLn
$ "[Start span '" <> name <> "']" r <- mliftIO
$putStrLn
$ "[End span '" <> name <> "']"pure
r prog ::IO
() prog =runEff
. runLog . runSpan $ do span "example program" do log "foo" span "greeting" do log "hello" log "world" log "bar" >>> prog [Start span 'example program'] [LOG] foo [Start span 'greeting'] [LOG] hello [LOG] world [End span 'greeting'] [LOG] bar [End span 'example program']
- When defining effects, you use the Template Haskell functions
makeEffectF
andmakeEffectH
. - The first
Eff
type parameter is a type-level list of higher-order effects, the second is for first-order effects.
Glossary
- Handler
- Interpreter for first-order effects.
- Elaborator
- Interpreter for higher-order effects.
Elaboration is generally performed by editing first-order (or higher-order) effectful operations within the computation held by the higher-order effect being elaborated.
runCatch :: (
eThrow
<|
ef) =>Eff
'[
e] efCatch
~>
Eff
'[] ef runCatch =interpretH
elabCatch elabCatch :: (
eThrow
<|
ef) =>Catch
e~~>
Eff
'[] ef elabCatch (
action hdl) = action &Catch
interposeWith
\(
e) _ -> hdl eThrow
Here,
elabCatch
is the elaborator for theCatch
effect.
- Interpretation / Handling / Elaboration
- The act of performing interpretation, or the process thereof.
Also, an interpreter function refers to a function represented by a natural transformation
~>
or of typeInterpreter
, that is, one that takes an effectful operation as an argument. On the other hand, when we say interpretation function, we mean a function of the form
, that is, one that takes theEff
eh ef ~>Eff
eh' ef'Eff
monad as an argument. In the previous example,elabCatch
is the interpreter function for theCatch
effect, andrunCatch
is the interpretation function for theCatch
effect.The interpretation function may also be called an interpreter.
- Continuational stateful interpreter
- An interpreter function that realizes features related to the continuation in algebraic effects.
It is a function that takes two arguments: an effectful operation and a continuation, which is the continuation of the computation from that operation, and returns the computation up to the end of the computation being interpreted.
By ignoring the continuation argument, it allows for global escapes like the
Throw
effect.runThrow ::
Eff
'[] (
e ': r) a ->Throw
Eff
'[] r (Either
e a) runThrow =interpretBy
(pure
.
Right
) handleThrow handleThrow ::Interpreter
(
e) (Throw
Eff
'[] r) (Either
e a) handleThrow (
e) _ =Throw
pure
$Left
eHere,
handleThrow
is the continuational stateful handler for theThrow
effect.By calling the continuation argument multiple times, it allows for non-deterministic computations like the Data.Effect.NonDet effect.
runNonDet :: forall f ef a . (
Alternative
f) =>Eff
'[] (
':Choose
Empty
': ef) a ->Eff
'[] ef (f a) runNonDet =bundleN
@2>>>
interpretBy
(pure
.pure
) ( (\
k ->Choose
liftA2
(<|>
) (kFalse
) (kTrue
))!+
(\
_ ->Empty
pure
empty
)!+
nil
)The function passed as the second argument to
interpretBy
is the continuational stateful handler.Additionally, what is passed as the first argument to
interpretBy
is called a value handler. This extends the continuation in the computation being interpreted. - Continuational state
- The state of the computation that appears through interpretation, behaving based on continuation-based semantics.
Naming Rules for Interpretation Functions
Functions with an
H
, such asinterpretH
, are for higher-order effects, while those without are for first-order effects.interpret
:: e~>
Eff
eh ef ->Eff
(e ': eh) ef ~>Eff
eh efinterpretH
:: e (Eff
eh ef)~>
Eff
eh ef ->Eff
(e ': eh) ef~>
Eff
eh efNote:
~>
binds more tightly than->
.
Functions may additionally have
With
orBy
at the end of their names.- These provide functionality equivalent to "Algebraic Effects and Handlers," meaning they offer access to delimited continuations during interpretation.
- Functions in the
By
family take two arguments: a value handler and a continuational stateful effect interpreter. They are the most generalized form. - Functions in the
With
family omit the value handler and take only the effect interpreter as an argument. - The difference between
interpretBy ret f m
andinterpretWith f m >>= ret
is that, during interpretation, the delimited continuation passed as the second argumentk
tof
in the former extends up to whenret
finishes, whereas in the latter, it only goes untilm
finishes (just beforeret
), soret
is not included ink
. - Functions without
With
orBy
cannot manipulate continuations; therefore, you cannot maintain internal state or perform behaviors like global escapes or non-deterministic computations during interpretation.
Functions that perform recursive continuational stateful interpretation have
Rec
additionally added.Non-recursive continuational stateful interpretation functions like
interpretWith
cannot be used unless the higher-order effects are empty:interpretWith
:: e ~> Eff '[] ef =>Eff
'[] (e ': ef) ~>Eff
'[] efThe
Rec
versions can be used even wheneh
is not empty.interpretRecWith
:: e ~>Eff
eh (e ': ef) ~>Eff
eh ef- When using this type of function, pay attention to their reset semantics. This is discussed later.
- In principle, they cannot take value handlers, so there is no combination with
By
.
Function names combine the above three attributes.
Examples of complex combinations include interpretHBy
and interpretRecHWith
.
Semantics of effects
Consider the following example.
data SomeEff a where SomeAction :: SomeEff StringmakeEffectF
[''SomeEff] -- | Throws an exception when 'SomeAction' is encountered runSomeEff :: (String
Throw
<|
ef) =>Eff
eh (SomeEff ': ef)~>
Eff
eh ef runSomeEff =interpret
\SomeAction ->throw
"not caught" -- | Catches the exception if 'someAction' results in one action :: (SomeEff<|
ef,Catch
String<<|
eh,Throw
String<|
ef) => Eff eh ef action = someAction `` \(_ :: String) ->
catch
pure
"caught" prog1 :: IO () prog1 =runPure
. runThrow @String . runCatch @String . runSomeEff $ action >>> prog1 Right "caught" prog2 :: IO () prog2 =runPure
. runThrow @String . runSomeEff . runCatch @String $ action >>> prog2 Left "not caught"
When applying runCatch
after runSomeEff
in prog1
, the exception is caught, but in the reverse order, it is not caught.
We will now explain this behavior to understand it.
In Heftia, the behavior of higher-order effects is based on reduction semantics—that is, term rewriting semantics similar to those in "Algebraic Effects and Handlers." By properly understanding and becoming familiar with this semantics, users can quickly and easily predict execution results.
Let's revisit the definition of runCatch
:
runCatch :: (e
Throw
<|
ef) =>Eff
'[e] ef
Catch
~>
Eff
'[] ef runCatch =interpretH
elabCatch elabCatch :: (e
Throw
<|
ef) =>Catch
e~~>
Eff
'[] ef elabCatch (action hdl) = action &
Catch
interposeWith
\(e) _ -> hdl e
Throw
When runCatch
encounters code like ... (action `catch` hdl) ...
in the program, it rewrites that part to ... (
interposeWith
(\(Throw
e) _ -> hdl e) action) ...
.
In general, functions like interpretH
and interposeH
behave this way—they recursively rewrite the target higher-order effects according to the given elaborator.
Rewriting proceeds from the deepest scope toward the outer scopes.
The same applies to first-order effects. Handling an effect means rewriting the effects that appear in the program.
With this in mind, let's follow the rewriting step by step.
Looking at prog1
.
First, when runSomeEff
is applied to action
:
runSomeEff action =interpret
(\SomeAction ->throw
"not caught") $ someAction `` \(_ :: String) ->
catch
pure
"caught" ==>throw
"not caught" `` \(_ :: String) ->
catch
pure
"caught"
The program is rewritten into a program like the above.
Next, when runCatch
is applied to this, it evaluates to:
runCatch @String $throw
"not caught" `` \(_ :: String) ->
catch
pure
"caught" ==>interposeWith
(\(e) _ ->
Throw
pure
"caught") $throw
"not caught" ==>pure
"caught"
In this way, the exception is caught.
On the other hand, in prog2
, when runCatch
is applied to action
:
runCatch @String action = runCatch @String $ someAction `` \(_ :: String) ->
catch
pure
"caught" ==>interposeWith
(\(@Throw
e) _ ->pure
"caught") $ someAction
At this point, since there is no throw
in the computation
that is the target of interposeWith
(only someAction
appears, which is not
throw
!), interposeWith
does nothing because there is no
throw
to rewrite:
==> someAction
Therefore, when runSomeEff
is applied:
runSomeEff someAction
==> throw
"not caught"
Thus, the exception remains as is.
In other words, in prog2
, at the point of runCatch
, it is impossible for runCatch
to know that someAction
will later be rewritten into throw
.
Interpreters decide what to do based only on the current state of the program's rewriting. They do not change the result based on any other information.
This is all there is to the reduction semantics of algebraic effects.
Independence from IO Semantics
As seen in the initial example with logs and spans, IO
operations are embedded as effects.
Not limited to IO
, any monad can be embedded as an effect.
Embedded IO
can be viewed as instruction scripts, and to avoid confusion when using Heftia, it should be regarded as such.
Rather than thinking "Haskell represents side effects via a type-level tag called IO
", it's better to think:
- Haskell is a purely functional language where you cannot write anything other than pure functions.
IO
is just an opaque algebraic data type whose definition you cannot see, no different from others.- The runtime system treats the value
main
as a sequence of instructions to be executed on the CPU. - Programming with side effects in Haskell is meta-programming where you write a pure function program that outputs
IO
type instruction scripts.
In fact, the semantics of effects in Heftia are completely isolated from the level of IO
.
Considerations at the IO
level, such as "asynchronous exceptions might be thrown",
"what is the current state of exception masking", or
"this state/environment value is local and not shared between threads", have no influence on effect interpretation and need not be considered.
IO
is just a data type representing programs with side effects, and we are merely meta-programming it.
The consistent semantics of algebraic effects prevent leaks of abstraction from the IO
level.
This is a significant difference from IO
-fused effect system libraries like effectful and cleff.
Reset Semantics in Recursive Continuational Stateful Interpretation
When performing recursive continuational stateful interpretation, that is, when using functions with Rec
, it's necessary to understand their semantics.
If you are not using Rec
functions, you don't need to pay particular attention to this section.
runStateRec
is a variant of
runState
,
a handler for the State
effect that can be used even when higher-order effects are unelaborated:
runStateRec
::Eff
eh (s ': ef)
State
~>
Eff
eh efrunState
::Eff
'[] (s ': ef)
State
~>
Eff
'[] ef
runStateRec
uses Rec
functions internally. When a function uses Rec
functions internally, it's best to reflect that in its naming.
Now, if you perform runStateRec
before elaborating higher-order effects, the following occurs.
Note that we are using the Log
and Span
effects introduced in the first example.
import Prelude hiding (log, span) prog :: IO () prog =runEff
do runLog . runSpan . runStateRec @[Int] [] $ domodify
@[Int] (++ [1]) log . show =<<get
@[Int] span "A" domodify
@[Int] (++ [2]) log . show =<<get
@[Int]modify
@[Int] (++ [3]) log . show =<<get
@[Int]pure
() >>> prog [LOG] [1] [Start spanA
] [LOG] [1,2] [End spanA
] [LOG] [1,3]
After exiting span A
, the added 2
has disappeared. As shown, state changes within the scope may not be preserved after exiting the scope.
This is a fundamental limitation of state preservation. When attempting to perform continuational stateful interpretation of an effect, if there are unelaborated higher-order effects remaining, resets of this continuational state occur for each scope of those higher-order effects. For higher-order effects that have already been elaborated and removed from the list at that point, there is naturally no impact.
This is simply because runStateRec
(generally all Rec
functions) recursively applies runState
to the scopes of unelaborated higher-order effects.
Interpretation occurs independently for each scope, and the state is not carried over.
From the perspective of shift/reset
delimited continuations, this phenomenon can be seen as reset
s being inserted at the scopes of unelaborated higher-order effects.
Whether this behavior occurs can be determined in advance.
This reset behavior occurs only when using Rec
functions and when the program passed to that function performs unelaborated higher-order effects internally.
The reset behavior occurs locally only at the points where those effects are performed.
Whether an unelaborated higher-order effect e
is performed internally can generally be determined by looking at the type signature of the effectful program.
Given an effectful program p
, if its type signature includes e
in the list of higher-order effects,
or if the constraint part includes e
or <<|
ehe
, then you know that higher-order effect is being used.
If not, <<:
me
cannot be performed internally in the function p
.
If you do not desire this reset behavior, you can avoid it by elaborating all higher-order effects first and emptying them when performing continuational stateful interpretation without using Rec
functions:
import Prelude hiding (log, span) prog :: IO () prog =runEff
do runLog . runState @[Int] [] . runSpan $ domodify
@[Int] (++ [1]) log . show =<<get
@[Int] span "A" domodify
@[Int] (++ [2]) log . show =<<get
@[Int]modify
@[Int] (++ [3]) log . show =<<get
@[Int]pure
() >>> prog [LOG] [1] [Start spanA
] [LOG] [1,2] [Ene spanA
] [LOG] [1,2,3]
Interpreting Multiple Effects Simultaneously
For example, consider a situation where you want to use multiple Catch
effects simultaneously.
The following is a case where both String
and Int
appear as exception types:
prog ::Eff
'[String,
Catch
Int] '[
Catch
String,
Throw
Int] ()
Throw
In this case, you may get stuck trying to use runCatch
.
This is because runCatch
has the following type signature:
runCatch :: (e
Throw
<|
ef) =>Eff
'[e] ef
Catch
~>
Eff
'[] ef
You cannot write runCatch @Int . runCatch @String
. It requires the higher-order effects to be empty after interpretation:
runCatch @String . runCatch @Int $ prog ^^^^^^^^^^^^^ • Couldn't match type: '[] with: '[Catch String] Expected: Eff '[Catch Int] ef x -> Eff '[Catch String] ef x Actual: Eff '[Catch Int] ef x -> Eff '[] ef x • In the second argument of ‘(.)’, namely ‘runCatch @Int’ In the first argument of ‘($)’, namely ‘runCatch @String . runCatch @Int’ In the expression: runCatch @String . runCatch @Int $ prog
In situations like this, where you want to perform continuational stateful elaboration on multiple higher-order effects simultaneously, you generally cannot reduce the higher-order effect list step by step or via multi-staging. Instead, you need to elaborate all of them at once simultaneously.
This is possible by pattern matching on the open union of higher-order effects using the !!+
operator.
prog' ::Eff
'[] '[String,
Throw
Int] () prog' =
Throw
interpretH
(elabCatch @String!!+
elabCatch @Int!!+
nilH
) .bundleAllH
$ prog
bundleAllH
collects the entire list of higher-order effects into a single higher-order effect using an open union.
Similarly, this can be done for first-order effects using !+
, nil
, and bundleAll
.
Synopsis
- data Eff (eh :: [EffectH]) (ef :: [EffectF]) a
- type (:!!) = Eff
- type (!!) (eh :: EffectH) (ef :: EffectF) = SumToRecUnionList UnionH eh :!! SumToRecUnionList Union ef
- type (+) = (:+:) :: (Type -> Type) -> (Type -> Type) -> Type -> Type
- type (:+:) = (:+:) :: ((Type -> Type) -> Type -> Type) -> ((Type -> Type) -> Type -> Type) -> (Type -> Type) -> Type -> Type
- type ($) (f :: Type -> Type) a = f a
- type ($$) (h :: (Type -> Type) -> Type -> Type) (f :: Type -> Type) = h f
- type Interpreter (e :: Type -> Type) (m :: Type -> Type) ans = forall x. e x -> (x -> m ans) -> m ans
- type Elaborator (e :: (Type -> Type) -> Type -> Type) (m :: Type -> Type) ans = Interpreter (e m) m ans
- type (~~>) (e :: (Type -> Type) -> Type -> Type) (f :: Type -> Type) = e f ~> f
- send :: forall (e :: EffectF) (ef :: [EffectF]) (eh :: [EffectH]). e <| ef => e ~> Eff eh ef
- sendH :: forall (e :: EffectH) (eh :: [EffectH]) (ef :: [EffectF]). e <<| eh => e (Eff eh ef) ~> Eff eh ef
- send0 :: forall e (eh :: [EffectH]) (ef :: [Type -> Type]) x. e x -> Eff eh (e ': ef) x
- send0H :: forall e (eh :: [(Type -> Type) -> Type -> Type]) (ef :: [EffectF]) x. e (Eff (e ': eh) ef) x -> Eff (e ': eh) ef x
- sendN :: forall (i :: Nat) (ef :: [Type -> Type]) (eh :: [EffectH]). KnownNat i => ElemAt i ef ~> Eff eh ef
- sendNH :: forall (i :: Nat) (eh :: [(Type -> Type) -> Type -> Type]) (ef :: [EffectF]). KnownNat i => ElemAt i eh (Eff eh ef) ~> Eff eh ef
- sendUnion :: forall (ef :: [EffectF]) a (eh :: [EffectH]). Union ef a -> Eff eh ef a
- sendUnionBy :: forall a (eh :: [EffectH]) (ef :: [EffectF]) ans. (a -> Eff eh ef ans) -> Union ef a -> Eff eh ef ans
- sendUnionH :: forall (eh :: [EffectH]) (ef :: [EffectF]) a. UnionH eh (Eff eh ef) a -> Eff eh ef a
- sendUnionHBy :: forall a (eh :: [EffectH]) (ef :: [EffectF]) ans. (a -> Eff eh ef ans) -> UnionH eh (Eff eh ef) a -> Eff eh ef ans
- runEff :: forall (m :: Type -> Type). Monad m => Eff ('[] :: [EffectH]) '[m] ~> m
- runPure :: Eff ('[] :: [EffectH]) ('[] :: [EffectF]) a -> a
- interpret :: forall (e :: Type -> Type) (ef :: [EffectF]) (eh :: [EffectH]). (e ~> Eff eh ef) -> Eff eh (e ': ef) ~> Eff eh ef
- interpretWith :: forall (e :: Type -> Type) (ef :: [EffectF]) a. Interpreter e (Eff ('[] :: [EffectH]) ef) a -> Eff ('[] :: [EffectH]) (e ': ef) a -> Eff ('[] :: [EffectH]) ef a
- interpretBy :: forall (e :: Type -> Type) (ef :: [EffectF]) ans a. (a -> Eff ('[] :: [EffectH]) ef ans) -> Interpreter e (Eff ('[] :: [EffectH]) ef) ans -> Eff ('[] :: [EffectH]) (e ': ef) a -> Eff ('[] :: [EffectH]) ef ans
- interpretRecWith :: forall e (ef :: [EffectF]) (eh :: [EffectH]) a. (forall ans x. e x -> (x -> Eff eh ef ans) -> Eff eh ef ans) -> Eff eh (e ': ef) a -> Eff eh ef a
- interpretH :: forall (e :: (Type -> Type) -> Type -> Type) (eh :: [EffectH]) (ef :: [EffectF]). HFunctor e => (e ~~> Eff eh ef) -> Eff (e ': eh) ef ~> Eff eh ef
- interpretHWith :: forall (e :: (Type -> Type) -> Type -> Type) (eh :: [EffectH]) (ef :: [EffectF]) a. HFunctor e => Interpreter (e (Eff '[e] ef)) (Eff eh ef) a -> Eff '[e] ef a -> Eff eh ef a
- interpretHBy :: forall (e :: (Type -> Type) -> Type -> Type) (eh :: [EffectH]) (ef :: [EffectF]) ans a. HFunctor e => (a -> Eff eh ef ans) -> Interpreter (e (Eff '[e] ef)) (Eff eh ef) ans -> Eff '[e] ef a -> Eff eh ef ans
- interpretRecHWith :: forall e (eh :: [(Type -> Type) -> Type -> Type]) (ef :: [EffectF]) a. HFunctor e => (forall ans x. e (Eff eh ef) x -> (x -> Eff eh ef ans) -> Eff eh ef ans) -> Eff (e ': eh) ef a -> Eff eh ef a
- reinterpret :: forall (e :: Type -> Type) (ef' :: [EffectF]) (ef :: [Type -> Type]) (eh :: [EffectH]). IsSuffixOf ef ef' => (e ~> Eff eh ef') -> Eff eh (e ': ef) ~> Eff eh ef'
- reinterpretN :: forall (n :: Natural) (e :: Type -> Type) (ef' :: [EffectF]) (ef :: [EffectF]) (eh :: [EffectH]). WeakenN n ef ef' => (e ~> Eff eh ef') -> Eff eh (e ': ef) ~> Eff eh ef'
- reinterpretNWith :: forall (n :: Natural) (e :: Type -> Type) (ef' :: [EffectF]) (ef :: [EffectF]) a. WeakenN n ef ef' => Interpreter e (Eff ('[] :: [EffectH]) ef') a -> Eff ('[] :: [EffectH]) (e ': ef) a -> Eff ('[] :: [EffectH]) ef' a
- reinterpretBy :: forall (e :: Type -> Type) (ef' :: [EffectF]) (ef :: [Type -> Type]) ans a. IsSuffixOf ef ef' => (a -> Eff ('[] :: [EffectH]) ef' ans) -> Interpreter e (Eff ('[] :: [EffectH]) ef') ans -> Eff ('[] :: [EffectH]) (e ': ef) a -> Eff ('[] :: [EffectH]) ef' ans
- reinterpretNBy :: forall (n :: Natural) (e :: Type -> Type) (ef' :: [EffectF]) (ef :: [EffectF]) ans a. WeakenN n ef ef' => (a -> Eff ('[] :: [EffectH]) ef' ans) -> Interpreter e (Eff ('[] :: [EffectH]) ef') ans -> Eff ('[] :: [EffectH]) (e ': ef) a -> Eff ('[] :: [EffectH]) ef' ans
- reinterpretRecWith :: forall e (ef' :: [EffectF]) (ef :: [EffectF]) (eh :: [EffectH]) a. IsSuffixOf ef ef' => (forall ans x. e x -> (x -> Eff eh ef' ans) -> Eff eh ef' ans) -> Eff eh (e ': ef) a -> Eff eh ef' a
- reinterpretRecNWith :: forall (n :: Natural) e (ef' :: [EffectF]) (ef :: [EffectF]) (eh :: [EffectH]) a. WeakenN n ef ef' => (forall ans x. e x -> (x -> Eff eh ef' ans) -> Eff eh ef' ans) -> Eff eh (e ': ef) a -> Eff eh ef' a
- reinterpretH :: forall (e :: (Type -> Type) -> Type -> Type) (eh :: [(Type -> Type) -> Type -> Type]) (eh' :: [EffectH]) (ef :: [EffectF]). (HFunctor e, IsSuffixOf eh eh') => (e ~~> Eff eh' ef) -> Eff (e ': eh) ef ~> Eff eh' ef
- reinterpretNH :: forall (n :: Natural) (e :: (Type -> Type) -> Type -> Type) (eh :: [EffectH]) (eh' :: [EffectH]) (ef :: [EffectF]). (HFunctor e, WeakenN n eh eh') => (e ~~> Eff eh' ef) -> Eff (e ': eh) ef ~> Eff eh' ef
- reinterpretHWith :: forall (e :: (Type -> Type) -> Type -> Type) (eh :: [EffectH]) (ef :: [EffectF]) a. HFunctor e => Interpreter (e (Eff '[e] ef)) (Eff eh ef) a -> Eff '[e] ef a -> Eff eh ef a
- reinterpretNHWith :: forall (n :: Natural) (e :: (Type -> Type) -> Type -> Type) (eh :: [EffectH]) (ef :: [EffectF]) a. (HFunctor e, WeakenN n ('[] :: [EffectH]) eh) => Interpreter (e (Eff '[e] ef)) (Eff eh ef) a -> Eff '[e] ef a -> Eff eh ef a
- reinterpretHBy :: forall (e :: (Type -> Type) -> Type -> Type) (eh :: [EffectH]) (ef :: [EffectF]) ans a. HFunctor e => (a -> Eff eh ef ans) -> Interpreter (e (Eff '[e] ef)) (Eff eh ef) ans -> Eff '[e] ef a -> Eff eh ef ans
- reinterpretNHBy :: forall (n :: Natural) (e :: (Type -> Type) -> Type -> Type) (eh :: [EffectH]) (ef :: [EffectF]) ans a. (HFunctor e, WeakenN n ('[] :: [EffectH]) eh) => (a -> Eff eh ef ans) -> Interpreter (e (Eff '[e] ef)) (Eff eh ef) ans -> Eff '[e] ef a -> Eff eh ef ans
- reinterpretRecHWith :: forall e (eh :: [(Type -> Type) -> Type -> Type]) (eh' :: [EffectH]) (ef :: [EffectF]) a. (HFunctor e, IsSuffixOf eh eh') => (forall ans x. e (Eff eh' ef) x -> (x -> Eff eh' ef ans) -> Eff eh' ef ans) -> Eff (e ': eh) ef a -> Eff eh' ef a
- reinterpretRecNHWith :: forall (n :: Natural) e (eh :: [(Type -> Type) -> Type -> Type]) (eh' :: [(Type -> Type) -> Type -> Type]) (ef :: [EffectF]) a. (HFunctor e, WeakenN n eh eh') => (forall ans x. e (Eff eh' ef) x -> (x -> Eff eh' ef ans) -> Eff eh' ef ans) -> Eff (e ': eh) ef a -> Eff eh' ef a
- interpose :: forall (e :: EffectF) (ef :: [EffectF]) (eh :: [EffectH]). e <| ef => (e ~> Eff eh ef) -> Eff eh ef ~> Eff eh ef
- interposeWith :: forall (e :: EffectF) (ef :: [EffectF]) a. e <| ef => Interpreter e (Eff ('[] :: [EffectH]) ef) a -> Eff ('[] :: [EffectH]) ef a -> Eff ('[] :: [EffectH]) ef a
- interposeBy :: forall (e :: EffectF) (ef :: [EffectF]) ans a. e <| ef => (a -> Eff ('[] :: [EffectH]) ef ans) -> Interpreter e (Eff ('[] :: [EffectH]) ef) ans -> Eff ('[] :: [EffectH]) ef a -> Eff ('[] :: [EffectH]) ef ans
- interposeRecWith :: forall e (ef :: [EffectF]) (eh :: [EffectH]) a. e <| ef => (forall ans x. e x -> (x -> Eff eh ef ans) -> Eff eh ef ans) -> Eff eh ef a -> Eff eh ef a
- interposeH :: forall (e :: EffectH) (eh :: [EffectH]) (ef :: [EffectF]). (e <<| eh, HFunctor e) => (e ~~> Eff eh ef) -> Eff eh ef ~> Eff eh ef
- interposeRecHWith :: forall e (eh :: [EffectH]) (ef :: [EffectF]) a. (e <<| eh, HFunctor e) => (forall ans x. e (Eff eh ef) x -> (x -> Eff eh ef ans) -> Eff eh ef ans) -> Eff eh ef a -> Eff eh ef a
- iterEffBy :: forall (e :: Type -> Type) m ans a. Monad m => (a -> m ans) -> Interpreter e m ans -> Eff ('[] :: [EffectH]) '[e] a -> m ans
- iterEffHBy :: forall (e :: (Type -> Type) -> Type -> Type) m ans a. (Monad m, HFunctor e) => (a -> m ans) -> Interpreter (e (Eff '[e] ('[] :: [EffectF]))) m ans -> Eff '[e] ('[] :: [EffectF]) a -> m ans
- iterEffRecH :: forall (e :: (Type -> Type) -> Type -> Type) (m :: Type -> Type). (Monad m, HFunctor e) => (e ~~> m) -> Eff '[e] ('[] :: [EffectF]) ~> m
- iterEffRecHWith :: forall e m. (Monad m, HFunctor e) => (forall ans x. e m x -> (x -> m ans) -> m ans) -> Eff '[e] ('[] :: [EffectF]) ~> m
- iterEffRecHFWith :: forall eh ef m. (Monad m, HFunctor eh) => (forall ans x. eh m x -> (x -> m ans) -> m ans) -> (forall ans x. ef x -> (x -> m ans) -> m ans) -> Eff '[eh] '[ef] ~> m
- iterEffHFBy :: forall (eh :: (Type -> Type) -> Type -> Type) (ef :: EffectF) m ans a. (Monad m, HFunctor eh) => (a -> m ans) -> Interpreter (eh (Eff '[eh] '[ef])) m ans -> Interpreter ef m ans -> Eff '[eh] '[ef] a -> m ans
- iterAllEffHFBy :: forall (eh :: [EffectH]) (ef :: [EffectF]) m ans a. Monad m => (a -> m ans) -> Interpreter (UnionH eh (Eff eh ef)) m ans -> Interpreter (Union ef) m ans -> Eff eh ef a -> m ans
- stateless :: forall (e :: Type -> Type) (m :: Type -> Type) ans. Monad m => (e ~> m) -> Interpreter e m ans
- type StateElaborator s (e :: (Type -> Type) -> Type -> Type) (m :: Type -> Type) ans = StateInterpreter s (e m) m ans
- type StateInterpreter s (e :: Type -> Type) (m :: Type -> Type) ans = forall x. e x -> s -> (s -> x -> m ans) -> m ans
- interpretStateBy :: forall s (e :: Type -> Type) (ef :: [EffectF]) ans a. s -> (s -> a -> Eff ('[] :: [EffectH]) ef ans) -> StateInterpreter s e (Eff ('[] :: [EffectH]) ef) ans -> Eff ('[] :: [EffectH]) (e ': ef) a -> Eff ('[] :: [EffectH]) ef ans
- reinterpretStateBy :: forall s (e :: Type -> Type) (ef' :: [EffectF]) (ef :: [Type -> Type]) ans a. IsSuffixOf ef ef' => s -> (s -> a -> Eff ('[] :: [EffectH]) ef' ans) -> StateInterpreter s e (Eff ('[] :: [EffectH]) ef') ans -> Eff ('[] :: [EffectH]) (e ': ef) a -> Eff ('[] :: [EffectH]) ef' ans
- interpretStateRecWith :: forall s e (ef :: [EffectF]) (eh :: [EffectH]) a. s -> (forall ans x. e x -> s -> (s -> x -> Eff eh ef ans) -> Eff eh ef ans) -> Eff eh (e ': ef) a -> Eff eh ef a
- reinterpretStateRecWith :: forall s e (ef' :: [EffectF]) (ef :: [EffectF]) (eh :: [EffectH]) a. IsSuffixOf ef ef' => s -> (forall ans x. e x -> s -> (s -> x -> Eff eh ef' ans) -> Eff eh ef' ans) -> Eff eh (e ': ef) a -> Eff eh ef' a
- interposeStateBy :: forall s (e :: EffectF) (ef :: [EffectF]) ans a. e <| ef => s -> (s -> a -> Eff ('[] :: [EffectH]) ef ans) -> StateInterpreter s e (Eff ('[] :: [EffectH]) ef) ans -> Eff ('[] :: [EffectH]) ef a -> Eff ('[] :: [EffectH]) ef ans
- iterStateAllEffHFBy :: forall s (eh :: [EffectH]) (ef :: [EffectF]) m ans a. Monad m => s -> (s -> a -> m ans) -> StateInterpreter s (UnionH eh (Eff eh ef)) m ans -> StateInterpreter s (Union ef) m ans -> Eff eh ef a -> m ans
- transform :: forall (e :: Type -> Type) (e' :: Type -> Type) (ef :: [Type -> Type]) (eh :: [EffectH]). (e ~> e') -> Eff eh (e ': ef) ~> Eff eh (e' ': ef)
- transformH :: forall (e :: (Type -> Type) -> Type -> Type) (e' :: EffectH) (eh :: [EffectH]) (ef :: [EffectF]). HFunctor e => (e (Eff (e' ': eh) ef) ~> e' (Eff (e' ': eh) ef)) -> Eff (e ': eh) ef ~> Eff (e' ': eh) ef
- translate :: forall (e :: Type -> Type) (e' :: EffectF) (ef :: [EffectF]) (eh :: [EffectH]). e' <| ef => (e ~> e') -> Eff eh (e ': ef) ~> Eff eh ef
- translateH :: forall (e :: (Type -> Type) -> Type -> Type) (e' :: EffectH) (eh :: [EffectH]) (ef :: [EffectF]). (e' <<| eh, HFunctor e) => (e (Eff eh ef) ~> e' (Eff eh ef)) -> Eff (e ': eh) ef ~> Eff eh ef
- rewrite :: forall (e :: EffectF) (ef :: [EffectF]) (eh :: [EffectH]). e <| ef => (e ~> e) -> Eff eh ef ~> Eff eh ef
- rewriteH :: forall (e :: EffectH) (eh :: [EffectH]) (ef :: [EffectF]). (e <<| eh, HFunctor e) => (e (Eff eh ef) ~> e (Eff eh ef)) -> Eff eh ef ~> Eff eh ef
- transEff :: forall (ef :: [EffectF]) (ef' :: [EffectF]) (eh :: [EffectH]). (Union ef ~> Union ef') -> Eff eh ef ~> Eff eh ef'
- transEffH :: forall (eh :: [EffectH]) (eh' :: [EffectH]) (ef :: [EffectF]). (UnionH eh (Eff eh' ef) ~> UnionH eh' (Eff eh' ef)) -> Eff eh ef ~> Eff eh' ef
- transEffHF :: forall (eh :: [EffectH]) (eh' :: [EffectH]) (ef :: [EffectF]) (ef' :: [EffectF]). (UnionH eh (Eff eh' ef') ~> UnionH eh' (Eff eh' ef')) -> (Union ef ~> Union ef') -> Eff eh ef ~> Eff eh' ef'
- raise :: forall (e :: EffectF) (ef :: [EffectF]) (eh :: [EffectH]) x. Eff eh ef x -> Eff eh (e ': ef) x
- raises :: forall (ef :: [EffectF]) (ef' :: [EffectF]) (eh :: [EffectH]). IsSuffixOf ef ef' => Eff eh ef ~> Eff eh ef'
- raiseN :: forall (len :: Natural) (ef :: [EffectF]) (ef' :: [EffectF]) (eh :: [EffectH]). WeakenN len ef ef' => Eff eh ef ~> Eff eh ef'
- raiseUnder :: forall (e1 :: EffectF) (e2 :: EffectF) (ef :: [EffectF]) (eh :: [EffectH]) x. Eff eh (e1 ': ef) x -> Eff eh (e1 ': (e2 ': ef)) x
- raisesUnder :: forall (offset :: Natural) (ef :: [EffectF]) (ef' :: [EffectF]) (eh :: [EffectH]). WeakenUnder offset ef ef' => Eff eh ef ~> Eff eh ef'
- raiseNUnder :: forall (len :: Natural) (offset :: Natural) (ef :: [EffectF]) (ef' :: [EffectF]) (eh :: [EffectH]). WeakenNUnder len offset ef ef' => Eff eh ef ~> Eff eh ef'
- raiseH :: forall (e :: EffectH) (eh :: [EffectH]) (ef :: [EffectF]) x. Eff eh ef x -> Eff (e ': eh) ef x
- raisesH :: forall (eh :: [EffectH]) (eh' :: [EffectH]) (ef :: [EffectF]). IsSuffixOf eh eh' => Eff eh ef ~> Eff eh' ef
- raiseNH :: forall (len :: Natural) (eh :: [EffectH]) (eh' :: [EffectH]) (ef :: [EffectF]). WeakenN len eh eh' => Eff eh ef ~> Eff eh' ef
- raiseUnderH :: forall (e1 :: EffectH) (e2 :: EffectH) (eh :: [EffectH]) (ef :: [EffectF]) x. Eff (e1 ': eh) ef x -> Eff (e1 ': (e2 ': eh)) ef x
- raiseNUnderH :: forall (len :: Natural) (offset :: Natural) (eh :: [EffectH]) (eh' :: [EffectH]) (ef :: [EffectF]). WeakenNUnder len offset eh eh' => Eff eh ef ~> Eff eh' ef
- subsume :: forall (e :: EffectF) (ef :: [EffectF]) (eh :: [EffectH]). e <| ef => Eff eh (e ': ef) ~> Eff eh ef
- subsumes :: forall (ef :: [EffectF]) (ef' :: [EffectF]) (eh :: [EffectH]). Strengthen ef ef' => Eff eh ef ~> Eff eh ef'
- subsumeN :: forall (len :: Natural) (ef :: [EffectF]) (ef' :: [EffectF]) (eh :: [EffectH]). StrengthenN len ef ef' => Eff eh ef ~> Eff eh ef'
- subsumeUnder :: forall (e2 :: EffectF) (e1 :: EffectF) (ef :: [EffectF]) (eh :: [EffectH]). e2 <| ef => Eff eh (e1 ': (e2 ': ef)) ~> Eff eh (e1 ': ef)
- subsumesUnder :: forall (offset :: Natural) (ef :: [EffectF]) (ef' :: [EffectF]) (eh :: [EffectH]). StrengthenUnder offset ef ef' => Eff eh ef ~> Eff eh ef'
- subsumeNUnder :: forall (len :: Natural) (offset :: Natural) (ef :: [EffectF]) (ef' :: [EffectF]) (eh :: [EffectH]). StrengthenNUnder len offset ef ef' => Eff eh ef ~> Eff eh ef'
- subsumeH :: forall (e :: EffectH) (eh :: [EffectH]) (ef :: [EffectF]). e <<| eh => Eff (e ': eh) ef ~> Eff eh ef
- subsumesH :: forall (eh :: [EffectH]) (eh' :: [EffectH]) (ef :: [EffectF]). Strengthen eh eh' => Eff eh ef ~> Eff eh' ef
- subsumeNH :: forall (len :: Natural) (eh :: [EffectH]) (eh' :: [EffectH]) (ef :: [EffectF]). StrengthenN len eh eh' => Eff eh ef ~> Eff eh' ef
- subsumeUnderH :: forall (e2 :: EffectH) (e1 :: EffectH) (eh :: [EffectH]) (ef :: [EffectF]). e2 <<| eh => Eff (e1 ': (e2 ': eh)) ef ~> Eff (e1 ': eh) ef
- subsumeNUnderH :: forall (len :: Natural) (offset :: Natural) (eh :: [EffectH]) (eh' :: [EffectH]) (ef :: [EffectF]). StrengthenNUnder len offset eh eh' => Eff eh ef ~> Eff eh' ef
- bundle :: forall (ef :: [EffectF]) (bundle :: [EffectF]) (rest :: [EffectF]) (eh :: [EffectH]). Split ef bundle rest => Eff eh ef ~> Eff eh (Union bundle ': rest)
- bundleN :: forall (len :: Nat) (ef :: [EffectF]) (eh :: [EffectH]). KnownNat len => Eff eh ef ~> Eff eh (Union (Take len ef) ': Drop len ef)
- unbundle :: forall (ef :: [EffectF]) (bundle :: [EffectF]) (rest :: [EffectF]) (eh :: [EffectH]). Split ef bundle rest => Eff eh (Union bundle ': rest) ~> Eff eh ef
- unbundleN :: forall (len :: Nat) (ef :: [EffectF]) (eh :: [EffectH]). KnownNat len => Eff eh (Union (Take len ef) ': Drop len ef) ~> Eff eh ef
- bundleUnder :: forall (offset :: Natural) (bundle :: [EffectF]) (ef :: [EffectF]) (ef' :: [EffectF]) (eh :: [EffectH]). BundleUnder Union offset ef ef' bundle => Eff eh ef ~> Eff eh ef'
- unbundleUnder :: forall (offset :: Natural) (bundle :: [EffectF]) (ef :: [EffectF]) (ef' :: [EffectF]) (eh :: [EffectH]). BundleUnder Union offset ef ef' bundle => Eff eh ef' ~> Eff eh ef
- bundleAll :: forall (eh :: [EffectH]) (ef :: [EffectF]) x. Eff eh ef x -> Eff eh '[Union ef] x
- unbundleAll :: forall (eh :: [EffectH]) (ef :: [EffectF]) x. Eff eh '[Union ef] x -> Eff eh ef x
- bundleH :: forall (eh :: [EffectH]) (bundle :: [EffectH]) (rest :: [EffectH]) (ef :: [EffectF]). Split eh bundle rest => Eff eh ef ~> Eff (UnionH bundle ': rest) ef
- unbundleH :: forall (eh :: [EffectH]) (bundle :: [EffectH]) (rest :: [EffectH]) (ef :: [EffectF]). Split eh bundle rest => Eff (UnionH bundle ': rest) ef ~> Eff eh ef
- bundleUnderH :: forall (offset :: Natural) (bundle :: [EffectH]) (eh :: [EffectH]) (eh' :: [EffectH]) (ef :: [EffectF]). BundleUnder UnionH offset eh eh' bundle => Eff eh ef ~> Eff eh' ef
- unbundleUnderH :: forall (offset :: Natural) (bundle :: [EffectH]) (eh :: [EffectH]) (eh' :: [EffectH]) (ef :: [EffectF]). BundleUnder UnionH offset eh eh' bundle => Eff eh' ef ~> Eff eh ef
- bundleAllH :: forall (eh :: [EffectH]) (ef :: [EffectF]) x. Eff eh ef x -> Eff '[UnionH eh] ef x
- unbundleAllH :: forall (eh :: [EffectH]) (ef :: [EffectF]) x. Eff '[UnionH eh] ef x -> Eff eh ef x
- tag :: forall {k} (tag :: k) (e :: EffectF) (ef :: [EffectF]) (eh :: [EffectH]) x. Eff eh (e ': ef) x -> Eff eh ((e # tag) ': ef) x
- untag :: forall {k} (tag :: k) (e :: EffectF) (ef :: [Type -> Type]) (eh :: [EffectH]) x. Eff eh ((e # tag) ': ef) x -> Eff eh (e ': ef) x
- retag :: forall {k1} {k2} (tag' :: k1) (tag :: k2) (e :: EffectF) (ef :: [Type -> Type]) (eh :: [EffectH]) x. Eff eh ((e # tag) ': ef) x -> Eff eh ((e # tag') ': ef) x
- tagH :: forall {k} (tag :: k) (e :: (Type -> Type) -> Type -> Type) (ef :: [EffectF]) (eh :: [(Type -> Type) -> Type -> Type]). HFunctor e => Eff (e ': eh) ef ~> Eff ((e ## tag) ': eh) ef
- untagH :: forall {k} (tag :: k) (e :: (Type -> Type) -> Type -> Type) (eh :: [(Type -> Type) -> Type -> Type]) (ef :: [EffectF]). HFunctor e => Eff ((e ## tag) ': eh) ef ~> Eff (e ': eh) ef
- retagH :: forall {k1} {k2} (tag' :: k1) (tag :: k2) (e :: (Type -> Type) -> Type -> Type) (eh :: [(Type -> Type) -> Type -> Type]) (ef :: [EffectF]). HFunctor e => Eff ((e ## tag) ': eh) ef ~> Eff ((e ## tag') ': eh) ef
- unkey :: forall {k} (key :: k) (e :: EffectF) (ef :: [Type -> Type]) (eh :: [EffectH]) x. Eff eh ((key #> e) ': ef) x -> Eff eh (e ': ef) x
- rekey :: forall {k1} {k2} (key' :: k1) (key :: k2) (e :: EffectF) (ef :: [Type -> Type]) (eh :: [EffectH]) x. Eff eh ((key #> e) ': ef) x -> Eff eh ((key' #> e) ': ef) x
- unkeyH :: forall {k} (key :: k) (e :: (Type -> Type) -> Type -> Type) (eh :: [(Type -> Type) -> Type -> Type]) (ef :: [EffectF]). HFunctor e => Eff ((key ##> e) ': eh) ef ~> Eff (e ': eh) ef
- rekeyH :: forall {k1} {k2} (key' :: k1) (key :: k2) (e :: (Type -> Type) -> Type -> Type) (eh :: [(Type -> Type) -> Type -> Type]) (ef :: [EffectF]). HFunctor e => Eff ((key ##> e) ': eh) ef ~> Eff ((key' ##> e) ': eh) ef
- class HFunctor (h :: (Type -> Type) -> Type -> Type)
- data ReaderKey
- data WriterKey
- data StateKey
- data ErrorKey
- type Type = TYPE LiftedRep
- liftIO :: MonadIO m => IO a -> m a
- module Data.Effect.OpenUnion
- module Data.Effect
- module Data.Effect.TH
- module Control.Effect
Basics
data Eff (eh :: [EffectH]) (ef :: [EffectF]) a Source #
The Eff
monad represents computations with effects.
It supports higher-order effects eh
and first-order effects ef
.
Val a | A pure value. |
Op | An effectful operation, which can be either a higher-order effect or a first-order effect. |
Instances
type (:!!) = Eff infixr 4 Source #
Type-level infix operator for Eff
.
Allows writing eh :!! ef
instead of Eff eh ef
.
type (!!) (eh :: EffectH) (ef :: EffectF) = SumToRecUnionList UnionH eh :!! SumToRecUnionList Union ef infixr 5 Source #
type (+) = (:+:) :: (Type -> Type) -> (Type -> Type) -> Type -> Type infixr 5 Source #
Sum for first-order effects.
type (:+:) = (:+:) :: ((Type -> Type) -> Type -> Type) -> ((Type -> Type) -> Type -> Type) -> (Type -> Type) -> Type -> Type Source #
Sum for higher-order effects.
type ($$) (h :: (Type -> Type) -> Type -> Type) (f :: Type -> Type) = h f infixr 4 Source #
Type-level infix applcation for higher-order functors.
type Interpreter (e :: Type -> Type) (m :: Type -> Type) ans = forall x. e x -> (x -> m ans) -> m ans Source #
Type alias for an interpreter function.
Interpreter e m ans
transforms an effect e
into a computation in m
where the result type (answer type) is ans
.
type Elaborator (e :: (Type -> Type) -> Type -> Type) (m :: Type -> Type) ans = Interpreter (e m) m ans Source #
Type alias for an elaborator function.
An Elaborator
is an interpreter for higher-order effects.
type (~~>) (e :: (Type -> Type) -> Type -> Type) (f :: Type -> Type) = e f ~> f infix 2 Source #
Type alias for a natural transformation style elaborator.
send :: forall (e :: EffectF) (ef :: [EffectF]) (eh :: [EffectH]). e <| ef => e ~> Eff eh ef Source #
Send a first-order effect e
to the Eff
carrier.
sendH :: forall (e :: EffectH) (eh :: [EffectH]) (ef :: [EffectF]). e <<| eh => e (Eff eh ef) ~> Eff eh ef Source #
Send a higher-order effect e
to the Eff
carrier.
send0 :: forall e (eh :: [EffectH]) (ef :: [Type -> Type]) x. e x -> Eff eh (e ': ef) x Source #
Send the first-order effect e
at the head of the list to the Eff
carrier.
send0H :: forall e (eh :: [(Type -> Type) -> Type -> Type]) (ef :: [EffectF]) x. e (Eff (e ': eh) ef) x -> Eff (e ': eh) ef x Source #
Send the higher-order effect e
at the head of the list to the Eff
carrier.
sendN :: forall (i :: Nat) (ef :: [Type -> Type]) (eh :: [EffectH]). KnownNat i => ElemAt i ef ~> Eff eh ef Source #
Send the i
-th first-order effect in the list to the Eff
carrier.
sendNH :: forall (i :: Nat) (eh :: [(Type -> Type) -> Type -> Type]) (ef :: [EffectF]). KnownNat i => ElemAt i eh (Eff eh ef) ~> Eff eh ef Source #
Send the i
-th higher-order effect in the list to the Eff
carrier.
sendUnion :: forall (ef :: [EffectF]) a (eh :: [EffectH]). Union ef a -> Eff eh ef a Source #
Send an open union of all first-order effects to the Eff
carrier.
sendUnionBy :: forall a (eh :: [EffectH]) (ef :: [EffectF]) ans. (a -> Eff eh ef ans) -> Union ef a -> Eff eh ef ans Source #
Send an open union of all first-order effects, along with its continuation, to the Eff
carrier.
sendUnionH :: forall (eh :: [EffectH]) (ef :: [EffectF]) a. UnionH eh (Eff eh ef) a -> Eff eh ef a Source #
Send an open union of all higher-order effects to the Eff
carrier.
sendUnionHBy :: forall a (eh :: [EffectH]) (ef :: [EffectF]) ans. (a -> Eff eh ef ans) -> UnionH eh (Eff eh ef) a -> Eff eh ef ans Source #
Send an open union of all higher-order effects, along with its continuation, to the Eff
carrier.
Interpreting effects
Running Eff
runEff :: forall (m :: Type -> Type). Monad m => Eff ('[] :: [EffectH]) '[m] ~> m Source #
Lowers the computation into a monad m
by treating the effect as a monad.
runPure :: Eff ('[] :: [EffectH]) ('[] :: [EffectF]) a -> a Source #
Extracts the value from a computation that contains only pure values without any effect.
Standard functions
For first-order effects
:: forall (e :: Type -> Type) (ef :: [EffectF]) (eh :: [EffectH]). (e ~> Eff eh ef) | Effect handler |
-> Eff eh (e ': ef) ~> Eff eh ef |
Interprets the first-order effect e
at the head of the list using the provided natural transformation style handler.
:: forall (e :: Type -> Type) (ef :: [EffectF]) a. Interpreter e (Eff ('[] :: [EffectH]) ef) a | Effect handler |
-> Eff ('[] :: [EffectH]) (e ': ef) a | |
-> Eff ('[] :: [EffectH]) ef a |
Interprets the first-order effect e
at the head of the list using the provided continuational stateful handler.
:: forall (e :: Type -> Type) (ef :: [EffectF]) ans a. (a -> Eff ('[] :: [EffectH]) ef ans) | Value handler |
-> Interpreter e (Eff ('[] :: [EffectH]) ef) ans | Effect handler |
-> Eff ('[] :: [EffectH]) (e ': ef) a | |
-> Eff ('[] :: [EffectH]) ef ans |
Interprets the first-order effect e
at the head of the list using the provided value handler and continuational stateful handler.
:: forall e (ef :: [EffectF]) (eh :: [EffectH]) a. (forall ans x. e x -> (x -> Eff eh ef ans) -> Eff eh ef ans) | Effect handler |
-> Eff eh (e ': ef) a | |
-> Eff eh ef a |
Interprets the first-order effect e
at the head of the list using the provided continuational stateful handler.
Interpretation is performed recursively with respect to the scopes of unelaborated higher-order effects eh
.
Note that during interpretation, the continuational state is reset (delimited) and does not persist beyond scopes.
For higher-order effects
:: forall (e :: (Type -> Type) -> Type -> Type) (eh :: [EffectH]) (ef :: [EffectF]). HFunctor e | |
=> (e ~~> Eff eh ef) | Effect elaborator |
-> Eff (e ': eh) ef ~> Eff eh ef |
Interprets the higher-order effect e
at the head of the list using the provided natural transformation style elaborator.
:: forall (e :: (Type -> Type) -> Type -> Type) (eh :: [EffectH]) (ef :: [EffectF]) a. HFunctor e | |
=> Interpreter (e (Eff '[e] ef)) (Eff eh ef) a | Effect elaborator |
-> Eff '[e] ef a | |
-> Eff eh ef a |
Interprets the single higher-order effect e
using the provided continuational stateful elaborator.
:: forall (e :: (Type -> Type) -> Type -> Type) (eh :: [EffectH]) (ef :: [EffectF]) ans a. HFunctor e | |
=> (a -> Eff eh ef ans) | Value handler |
-> Interpreter (e (Eff '[e] ef)) (Eff eh ef) ans | Effect elaborator |
-> Eff '[e] ef a | |
-> Eff eh ef ans |
Interprets the single higher-order effect e
using the provided value handler and continuational stateful elaborator.
:: forall e (eh :: [(Type -> Type) -> Type -> Type]) (ef :: [EffectF]) a. HFunctor e | |
=> (forall ans x. e (Eff eh ef) x -> (x -> Eff eh ef ans) -> Eff eh ef ans) | Effect elaborator |
-> Eff (e ': eh) ef a | |
-> Eff eh ef a |
Interprets the higher-order effect e
at the head of the list using the provided continuational stateful elaborator.
Interpretation is performed recursively with respect to the scopes of unelaborated higher-order effects eh
.
Note that during interpretation, the continuational state is reset (delimited) and does not persist beyond scopes.
Reinterpretation functions
For first-order effects
reinterpret :: forall (e :: Type -> Type) (ef' :: [EffectF]) (ef :: [Type -> Type]) (eh :: [EffectH]). IsSuffixOf ef ef' => (e ~> Eff eh ef') -> Eff eh (e ': ef) ~> Eff eh ef' Source #
reinterpretN :: forall (n :: Natural) (e :: Type -> Type) (ef' :: [EffectF]) (ef :: [EffectF]) (eh :: [EffectH]). WeakenN n ef ef' => (e ~> Eff eh ef') -> Eff eh (e ': ef) ~> Eff eh ef' Source #
reinterpretNWith :: forall (n :: Natural) (e :: Type -> Type) (ef' :: [EffectF]) (ef :: [EffectF]) a. WeakenN n ef ef' => Interpreter e (Eff ('[] :: [EffectH]) ef') a -> Eff ('[] :: [EffectH]) (e ': ef) a -> Eff ('[] :: [EffectH]) ef' a Source #
reinterpretBy :: forall (e :: Type -> Type) (ef' :: [EffectF]) (ef :: [Type -> Type]) ans a. IsSuffixOf ef ef' => (a -> Eff ('[] :: [EffectH]) ef' ans) -> Interpreter e (Eff ('[] :: [EffectH]) ef') ans -> Eff ('[] :: [EffectH]) (e ': ef) a -> Eff ('[] :: [EffectH]) ef' ans Source #
reinterpretNBy :: forall (n :: Natural) (e :: Type -> Type) (ef' :: [EffectF]) (ef :: [EffectF]) ans a. WeakenN n ef ef' => (a -> Eff ('[] :: [EffectH]) ef' ans) -> Interpreter e (Eff ('[] :: [EffectH]) ef') ans -> Eff ('[] :: [EffectH]) (e ': ef) a -> Eff ('[] :: [EffectH]) ef' ans Source #
reinterpretRecWith :: forall e (ef' :: [EffectF]) (ef :: [EffectF]) (eh :: [EffectH]) a. IsSuffixOf ef ef' => (forall ans x. e x -> (x -> Eff eh ef' ans) -> Eff eh ef' ans) -> Eff eh (e ': ef) a -> Eff eh ef' a Source #
reinterpretRecNWith :: forall (n :: Natural) e (ef' :: [EffectF]) (ef :: [EffectF]) (eh :: [EffectH]) a. WeakenN n ef ef' => (forall ans x. e x -> (x -> Eff eh ef' ans) -> Eff eh ef' ans) -> Eff eh (e ': ef) a -> Eff eh ef' a Source #
For higher-order effects
reinterpretH :: forall (e :: (Type -> Type) -> Type -> Type) (eh :: [(Type -> Type) -> Type -> Type]) (eh' :: [EffectH]) (ef :: [EffectF]). (HFunctor e, IsSuffixOf eh eh') => (e ~~> Eff eh' ef) -> Eff (e ': eh) ef ~> Eff eh' ef Source #
reinterpretNH :: forall (n :: Natural) (e :: (Type -> Type) -> Type -> Type) (eh :: [EffectH]) (eh' :: [EffectH]) (ef :: [EffectF]). (HFunctor e, WeakenN n eh eh') => (e ~~> Eff eh' ef) -> Eff (e ': eh) ef ~> Eff eh' ef Source #
reinterpretHWith :: forall (e :: (Type -> Type) -> Type -> Type) (eh :: [EffectH]) (ef :: [EffectF]) a. HFunctor e => Interpreter (e (Eff '[e] ef)) (Eff eh ef) a -> Eff '[e] ef a -> Eff eh ef a Source #
reinterpretNHWith :: forall (n :: Natural) (e :: (Type -> Type) -> Type -> Type) (eh :: [EffectH]) (ef :: [EffectF]) a. (HFunctor e, WeakenN n ('[] :: [EffectH]) eh) => Interpreter (e (Eff '[e] ef)) (Eff eh ef) a -> Eff '[e] ef a -> Eff eh ef a Source #
reinterpretHBy :: forall (e :: (Type -> Type) -> Type -> Type) (eh :: [EffectH]) (ef :: [EffectF]) ans a. HFunctor e => (a -> Eff eh ef ans) -> Interpreter (e (Eff '[e] ef)) (Eff eh ef) ans -> Eff '[e] ef a -> Eff eh ef ans Source #
reinterpretNHBy :: forall (n :: Natural) (e :: (Type -> Type) -> Type -> Type) (eh :: [EffectH]) (ef :: [EffectF]) ans a. (HFunctor e, WeakenN n ('[] :: [EffectH]) eh) => (a -> Eff eh ef ans) -> Interpreter (e (Eff '[e] ef)) (Eff eh ef) ans -> Eff '[e] ef a -> Eff eh ef ans Source #
reinterpretRecHWith :: forall e (eh :: [(Type -> Type) -> Type -> Type]) (eh' :: [EffectH]) (ef :: [EffectF]) a. (HFunctor e, IsSuffixOf eh eh') => (forall ans x. e (Eff eh' ef) x -> (x -> Eff eh' ef ans) -> Eff eh' ef ans) -> Eff (e ': eh) ef a -> Eff eh' ef a Source #
reinterpretRecNHWith :: forall (n :: Natural) e (eh :: [(Type -> Type) -> Type -> Type]) (eh' :: [(Type -> Type) -> Type -> Type]) (ef :: [EffectF]) a. (HFunctor e, WeakenN n eh eh') => (forall ans x. e (Eff eh' ef) x -> (x -> Eff eh' ef ans) -> Eff eh' ef ans) -> Eff (e ': eh) ef a -> Eff eh' ef a Source #
Interposition functions
For first-order effects
:: forall (e :: EffectF) (ef :: [EffectF]) (eh :: [EffectH]). e <| ef | |
=> (e ~> Eff eh ef) | Effect handler |
-> Eff eh ef ~> Eff eh ef |
Reinterprets (hooks) the first-order effect e
in the list using the provided natural transformation style handler.
If multiple instances of e
exist in the list, the one closest to the head (with the smallest index) will be targeted.
:: forall (e :: EffectF) (ef :: [EffectF]) a. e <| ef | |
=> Interpreter e (Eff ('[] :: [EffectH]) ef) a | Effect handler |
-> Eff ('[] :: [EffectH]) ef a | |
-> Eff ('[] :: [EffectH]) ef a |
Reinterprets (hooks) the first-order effect e
in the list using the provided continuational stateful handler.
If multiple instances of e
exist in the list, the one closest to the head (with the smallest index) will be targeted.
:: forall (e :: EffectF) (ef :: [EffectF]) ans a. e <| ef | |
=> (a -> Eff ('[] :: [EffectH]) ef ans) | Value handler |
-> Interpreter e (Eff ('[] :: [EffectH]) ef) ans | Effect handler |
-> Eff ('[] :: [EffectH]) ef a | |
-> Eff ('[] :: [EffectH]) ef ans |
Reinterprets (hooks) the first-order effect e
in the list using the provided value handler and continuational stateful handler.
If multiple instances of e
exist in the list, the one closest to the head (with the smallest index) will be targeted.
:: forall e (ef :: [EffectF]) (eh :: [EffectH]) a. e <| ef | |
=> (forall ans x. e x -> (x -> Eff eh ef ans) -> Eff eh ef ans) | Effect handler |
-> Eff eh ef a | |
-> Eff eh ef a |
Reinterprets (hooks) the first-order effect e
in the list using the provided continuational stateful handler.
Interpretation is performed recursively with respect to the scopes of unelaborated higher-order effects eh
.
Note that during interpretation, the continuational state is reset (delimited) and does not persist beyond scopes.
If multiple instances of e
exist in the list, the one closest to the head (with the smallest index) will be targeted.
For higher-order effects
:: forall (e :: EffectH) (eh :: [EffectH]) (ef :: [EffectF]). (e <<| eh, HFunctor e) | |
=> (e ~~> Eff eh ef) | Effect elaborator |
-> Eff eh ef ~> Eff eh ef |
Reinterprets (hooks) the higher-order effect e
in the list using the provided natural transformation style elaborator.
If multiple instances of e
exist in the list, the one closest to the head (with the smallest index) will be targeted.
:: forall e (eh :: [EffectH]) (ef :: [EffectF]) a. (e <<| eh, HFunctor e) | |
=> (forall ans x. e (Eff eh ef) x -> (x -> Eff eh ef ans) -> Eff eh ef ans) | Effect elaborator |
-> Eff eh ef a | |
-> Eff eh ef a |
Reinterprets (hooks) the higher-order effect e
in the list using the provided continuational stateful elaborator.
Interpretation is performed recursively with respect to the scopes of unelaborated higher-order effects eh
.
Note that during interpretation, the continuational state is reset (delimited) and does not persist beyond scopes.
If multiple instances of e
exist in the list, the one closest to the head (with the smallest index) will be targeted.
Transformation to monads
:: forall (e :: Type -> Type) m ans a. Monad m | |
=> (a -> m ans) | Value handler |
-> Interpreter e m ans | Effect handler |
-> Eff ('[] :: [EffectH]) '[e] a | |
-> m ans |
Traverses a computation containing only a single first-order effect e
using the provided value handler and continuational stateful handler, transforming it into a monad m
.
:: forall (e :: (Type -> Type) -> Type -> Type) m ans a. (Monad m, HFunctor e) | |
=> (a -> m ans) | Value handler |
-> Interpreter (e (Eff '[e] ('[] :: [EffectF]))) m ans | Effect handler |
-> Eff '[e] ('[] :: [EffectF]) a | |
-> m ans |
Traverses a computation containing only a single higher-order effect e
using the provided value handler and continuational stateful elaborator, transforming it into a monad m
.
:: forall (e :: (Type -> Type) -> Type -> Type) (m :: Type -> Type). (Monad m, HFunctor e) | |
=> (e ~~> m) | Effect elaborator |
-> Eff '[e] ('[] :: [EffectF]) ~> m |
Traverses a computation containing only a single higher-order effect e
using the provided natural transformation elaborator, transforming it into a monad m
.
Traversal is performed recursively with respect to the scope of the higher-order effect e
.
Note that during traversal, the continuational state is reset (delimited) and does not persist beyond scopes.
:: forall e m. (Monad m, HFunctor e) | |
=> (forall ans x. e m x -> (x -> m ans) -> m ans) | Effect elaborator |
-> Eff '[e] ('[] :: [EffectF]) ~> m |
Traverses a computation containing only a single higher-order effect e
using the provided continuational stateful elaborator, transforming it into a monad m
.
Traversal is performed recursively with respect to the scope of the higher-order effect e
.
Note that during traversal, the continuational state is reset (delimited) and does not persist beyond scopes.
:: forall eh ef m. (Monad m, HFunctor eh) | |
=> (forall ans x. eh m x -> (x -> m ans) -> m ans) | Effect elaborator |
-> (forall ans x. ef x -> (x -> m ans) -> m ans) | Effect handler |
-> Eff '[eh] '[ef] ~> m |
Traverses a computation containing only higher-order effects eh
and first-order effects ef
using the provided continuational stateful elaborator, transforming it into a monad m
.
Traversal is performed recursively with respect to the scopes of higher-order effects. Note that during traversal, the continuational state is reset (delimited) and does not persist beyond scopes.
:: forall (eh :: (Type -> Type) -> Type -> Type) (ef :: EffectF) m ans a. (Monad m, HFunctor eh) | |
=> (a -> m ans) | Value handler |
-> Interpreter (eh (Eff '[eh] '[ef])) m ans | Effect elaborator |
-> Interpreter ef m ans | Effect handler |
-> Eff '[eh] '[ef] a | |
-> m ans |
Traverses a computation containing only higher-order effects eh
and first-order effects ef
using the provided value handler,
continuational stateful elaborator, and handler, transforming it into a monad m
.
:: forall (eh :: [EffectH]) (ef :: [EffectF]) m ans a. Monad m | |
=> (a -> m ans) | Value handler |
-> Interpreter (UnionH eh (Eff eh ef)) m ans | Effect elaborator |
-> Interpreter (Union ef) m ans | Effect handler |
-> Eff eh ef a | |
-> m ans |
Traverses all effects using the provided value handler, continuational stateful elaborator, and handler, transforming them into a monad m
.
Utilities
stateless :: forall (e :: Type -> Type) (m :: Type -> Type) ans. Monad m => (e ~> m) -> Interpreter e m ans Source #
Lifts a natural transformation into a continuational stateful interpreter.
Ad-hoc stateful interpretation
Theses entities provides an ad-hoc specialized version to accelerate interpretations that have a
single state type s
, especially for effects like State
or
Writer
.
type StateElaborator s (e :: (Type -> Type) -> Type -> Type) (m :: Type -> Type) ans = StateInterpreter s (e m) m ans Source #
An ad-hoc stateful version of Elaborator
for performance.
type StateInterpreter s (e :: Type -> Type) (m :: Type -> Type) ans = forall x. e x -> s -> (s -> x -> m ans) -> m ans Source #
An ad-hoc stateful version of Interpreter
for performance.
Interpretation functions
interpretStateBy :: forall s (e :: Type -> Type) (ef :: [EffectF]) ans a. s -> (s -> a -> Eff ('[] :: [EffectH]) ef ans) -> StateInterpreter s e (Eff ('[] :: [EffectH]) ef) ans -> Eff ('[] :: [EffectH]) (e ': ef) a -> Eff ('[] :: [EffectH]) ef ans Source #
reinterpretStateBy :: forall s (e :: Type -> Type) (ef' :: [EffectF]) (ef :: [Type -> Type]) ans a. IsSuffixOf ef ef' => s -> (s -> a -> Eff ('[] :: [EffectH]) ef' ans) -> StateInterpreter s e (Eff ('[] :: [EffectH]) ef') ans -> Eff ('[] :: [EffectH]) (e ': ef) a -> Eff ('[] :: [EffectH]) ef' ans Source #
interpretStateRecWith :: forall s e (ef :: [EffectF]) (eh :: [EffectH]) a. s -> (forall ans x. e x -> s -> (s -> x -> Eff eh ef ans) -> Eff eh ef ans) -> Eff eh (e ': ef) a -> Eff eh ef a Source #
reinterpretStateRecWith :: forall s e (ef' :: [EffectF]) (ef :: [EffectF]) (eh :: [EffectH]) a. IsSuffixOf ef ef' => s -> (forall ans x. e x -> s -> (s -> x -> Eff eh ef' ans) -> Eff eh ef' ans) -> Eff eh (e ': ef) a -> Eff eh ef' a Source #
Interposition functions
interposeStateBy :: forall s (e :: EffectF) (ef :: [EffectF]) ans a. e <| ef => s -> (s -> a -> Eff ('[] :: [EffectH]) ef ans) -> StateInterpreter s e (Eff ('[] :: [EffectH]) ef) ans -> Eff ('[] :: [EffectH]) ef a -> Eff ('[] :: [EffectH]) ef ans Source #
Transformation to monads
iterStateAllEffHFBy :: forall s (eh :: [EffectH]) (ef :: [EffectF]) m ans a. Monad m => s -> (s -> a -> m ans) -> StateInterpreter s (UnionH eh (Eff eh ef)) m ans -> StateInterpreter s (Union ef) m ans -> Eff eh ef a -> m ans Source #
Transforming effects
Rewriting effectful operations
transform :: forall (e :: Type -> Type) (e' :: Type -> Type) (ef :: [Type -> Type]) (eh :: [EffectH]). (e ~> e') -> Eff eh (e ': ef) ~> Eff eh (e' ': ef) Source #
Transforms the first-order effect e
at the head of the list into another
first-order effect e'
.
transformH :: forall (e :: (Type -> Type) -> Type -> Type) (e' :: EffectH) (eh :: [EffectH]) (ef :: [EffectF]). HFunctor e => (e (Eff (e' ': eh) ef) ~> e' (Eff (e' ': eh) ef)) -> Eff (e ': eh) ef ~> Eff (e' ': eh) ef Source #
Transforms the higher-order effect e
at the head of the list into another
higher-order effect e'
.
translate :: forall (e :: Type -> Type) (e' :: EffectF) (ef :: [EffectF]) (eh :: [EffectH]). e' <| ef => (e ~> e') -> Eff eh (e ': ef) ~> Eff eh ef Source #
Transforms the first-order effect e
at the head of the list into another
first-order effect e'
and embeds it into the list.
If multiple instances of e'
exist in the list, the one closest to the head
(with the smallest index) will be targeted.
translateH :: forall (e :: (Type -> Type) -> Type -> Type) (e' :: EffectH) (eh :: [EffectH]) (ef :: [EffectF]). (e' <<| eh, HFunctor e) => (e (Eff eh ef) ~> e' (Eff eh ef)) -> Eff (e ': eh) ef ~> Eff eh ef Source #
Transforms the higher-order effect e
at the head of the list into another
higher-order effect e'
and embeds it into the list.
If multiple instances of e'
exist in the list, the one closest to the head
(with the smallest index) will be targeted.
rewrite :: forall (e :: EffectF) (ef :: [EffectF]) (eh :: [EffectH]). e <| ef => (e ~> e) -> Eff eh ef ~> Eff eh ef Source #
Rewrites the first-order effect e
in the list.
If multiple instances of e
exist in the list, the one closest to the head
(with the smallest index) will be targeted.
rewriteH :: forall (e :: EffectH) (eh :: [EffectH]) (ef :: [EffectF]). (e <<| eh, HFunctor e) => (e (Eff eh ef) ~> e (Eff eh ef)) -> Eff eh ef ~> Eff eh ef Source #
Rewrites the higher-order effect e
in the list.
If multiple instances of e
exist in the list, the one closest to the head
(with the smallest index) will be targeted.
transEff :: forall (ef :: [EffectF]) (ef' :: [EffectF]) (eh :: [EffectH]). (Union ef ~> Union ef') -> Eff eh ef ~> Eff eh ef' Source #
Transforms all first-order effects in the open union at once.
transEffH :: forall (eh :: [EffectH]) (eh' :: [EffectH]) (ef :: [EffectF]). (UnionH eh (Eff eh' ef) ~> UnionH eh' (Eff eh' ef)) -> Eff eh ef ~> Eff eh' ef Source #
Transforms all higher-order effects in the open union at once.
transEffHF :: forall (eh :: [EffectH]) (eh' :: [EffectH]) (ef :: [EffectF]) (ef' :: [EffectF]). (UnionH eh (Eff eh' ef') ~> UnionH eh' (Eff eh' ef')) -> (Union ef ~> Union ef') -> Eff eh ef ~> Eff eh' ef' Source #
Transforms all higher-order and first-order effects in the open union at once.
Manipulating the effect list (without rewriting effectful operations)
Insertion functions
raise :: forall (e :: EffectF) (ef :: [EffectF]) (eh :: [EffectH]) x. Eff eh ef x -> Eff eh (e ': ef) x Source #
Adds an arbitrary first-order effect e
to the head of the list.
raises :: forall (ef :: [EffectF]) (ef' :: [EffectF]) (eh :: [EffectH]). IsSuffixOf ef ef' => Eff eh ef ~> Eff eh ef' Source #
Adds multiple arbitrary first-order effects to the head of the list.
raiseN :: forall (len :: Natural) (ef :: [EffectF]) (ef' :: [EffectF]) (eh :: [EffectH]). WeakenN len ef ef' => Eff eh ef ~> Eff eh ef' Source #
Adds a specified number len
of arbitrary first-order effects to the head
of the list.
raiseUnder :: forall (e1 :: EffectF) (e2 :: EffectF) (ef :: [EffectF]) (eh :: [EffectH]) x. Eff eh (e1 ': ef) x -> Eff eh (e1 ': (e2 ': ef)) x Source #
Inserts an arbitrary first-order effect e2
just below the head of the
list.
raisesUnder :: forall (offset :: Natural) (ef :: [EffectF]) (ef' :: [EffectF]) (eh :: [EffectH]). WeakenUnder offset ef ef' => Eff eh ef ~> Eff eh ef' Source #
Inserts multiple arbitrary first-order effects at a position offset
steps
below the head of the list.
raiseNUnder :: forall (len :: Natural) (offset :: Natural) (ef :: [EffectF]) (ef' :: [EffectF]) (eh :: [EffectH]). WeakenNUnder len offset ef ef' => Eff eh ef ~> Eff eh ef' Source #
Inserts len
arbitrary first-order effects at a position offset
steps
below the head of the list.
raiseH :: forall (e :: EffectH) (eh :: [EffectH]) (ef :: [EffectF]) x. Eff eh ef x -> Eff (e ': eh) ef x Source #
Adds a specified number len
of arbitrary higher-order effects to the head
of the list.
raisesH :: forall (eh :: [EffectH]) (eh' :: [EffectH]) (ef :: [EffectF]). IsSuffixOf eh eh' => Eff eh ef ~> Eff eh' ef Source #
Inserts an arbitrary higher-order effect e2
just below the head of the
list.
raiseNH :: forall (len :: Natural) (eh :: [EffectH]) (eh' :: [EffectH]) (ef :: [EffectF]). WeakenN len eh eh' => Eff eh ef ~> Eff eh' ef Source #
Adds a specified number len
of arbitrary higher-order effects to the head
of the list.
raiseUnderH :: forall (e1 :: EffectH) (e2 :: EffectH) (eh :: [EffectH]) (ef :: [EffectF]) x. Eff (e1 ': eh) ef x -> Eff (e1 ': (e2 ': eh)) ef x Source #
Inserts an arbitrary higher-order effect e2
just below the head of the
list.
raiseNUnderH :: forall (len :: Natural) (offset :: Natural) (eh :: [EffectH]) (eh' :: [EffectH]) (ef :: [EffectF]). WeakenNUnder len offset eh eh' => Eff eh ef ~> Eff eh' ef Source #
Inserts len
arbitrary higher-order effects at a position offset
steps
below the head of the list.
Merging functions
subsume :: forall (e :: EffectF) (ef :: [EffectF]) (eh :: [EffectH]). e <| ef => Eff eh (e ': ef) ~> Eff eh ef Source #
Merges the first first-order effect e
at the head of the list into the
same type of effect e
that is below it.
If multiple candidates of e
exist in the list, the one closest to the head
(with the smallest index) will be targeted.
subsumes :: forall (ef :: [EffectF]) (ef' :: [EffectF]) (eh :: [EffectH]). Strengthen ef ef' => Eff eh ef ~> Eff eh ef' Source #
Merges multiple first-order effects at the head of the list into effects of the same types that are below them.
subsumeN :: forall (len :: Natural) (ef :: [EffectF]) (ef' :: [EffectF]) (eh :: [EffectH]). StrengthenN len ef ef' => Eff eh ef ~> Eff eh ef' Source #
Merges a specified number len
of first-order effects at the head of the
list into effects of the same types that are below them.
subsumeUnder :: forall (e2 :: EffectF) (e1 :: EffectF) (ef :: [EffectF]) (eh :: [EffectH]). e2 <| ef => Eff eh (e1 ': (e2 ': ef)) ~> Eff eh (e1 ': ef) Source #
Merges the first-order effect e2
located just below the head into the
same type of effect e2
that is below it.
subsumesUnder :: forall (offset :: Natural) (ef :: [EffectF]) (ef' :: [EffectF]) (eh :: [EffectH]). StrengthenUnder offset ef ef' => Eff eh ef ~> Eff eh ef' Source #
Merges multiple first-order effects at an offset
below the head into
effects of the same types that are below them.
subsumeNUnder :: forall (len :: Natural) (offset :: Natural) (ef :: [EffectF]) (ef' :: [EffectF]) (eh :: [EffectH]). StrengthenNUnder len offset ef ef' => Eff eh ef ~> Eff eh ef' Source #
Merges len
first-order effects at an offset
below the head into effects
of the same types that are below them.
subsumeH :: forall (e :: EffectH) (eh :: [EffectH]) (ef :: [EffectF]). e <<| eh => Eff (e ': eh) ef ~> Eff eh ef Source #
Merges the first higher-order effect e
at the head of the list into the
same type of effect e
that is below it.
If multiple candidates of e
exist in the list, the one closest to the head
(with the smallest index) will be targeted.
subsumesH :: forall (eh :: [EffectH]) (eh' :: [EffectH]) (ef :: [EffectF]). Strengthen eh eh' => Eff eh ef ~> Eff eh' ef Source #
Merges multiple higher-order effects at the head of the list into effects of the same types that are below them.
subsumeNH :: forall (len :: Natural) (eh :: [EffectH]) (eh' :: [EffectH]) (ef :: [EffectF]). StrengthenN len eh eh' => Eff eh ef ~> Eff eh' ef Source #
Merges a specified number len
of higher-order effects at the head of the
list into effects of the same types that are below them.
subsumeUnderH :: forall (e2 :: EffectH) (e1 :: EffectH) (eh :: [EffectH]) (ef :: [EffectF]). e2 <<| eh => Eff (e1 ': (e2 ': eh)) ef ~> Eff (e1 ': eh) ef Source #
Merges the higher-order effect e2
located just below the head into the
same type of effect e2
that is below it.
subsumeNUnderH :: forall (len :: Natural) (offset :: Natural) (eh :: [EffectH]) (eh' :: [EffectH]) (ef :: [EffectF]). StrengthenNUnder len offset eh eh' => Eff eh ef ~> Eff eh' ef Source #
Merges len
higher-order effects at an offset
below the head into effects
of the same types that are below them.
Bundling functions
bundle :: forall (ef :: [EffectF]) (bundle :: [EffectF]) (rest :: [EffectF]) (eh :: [EffectH]). Split ef bundle rest => Eff eh ef ~> Eff eh (Union bundle ': rest) Source #
Bundles several effects at the head of the list into a single element using an open union.
bundleN :: forall (len :: Nat) (ef :: [EffectF]) (eh :: [EffectH]). KnownNat len => Eff eh ef ~> Eff eh (Union (Take len ef) ': Drop len ef) Source #
Bundles the first len
effects at the head of the list into a single
element using an open union.
unbundle :: forall (ef :: [EffectF]) (bundle :: [EffectF]) (rest :: [EffectF]) (eh :: [EffectH]). Split ef bundle rest => Eff eh (Union bundle ': rest) ~> Eff eh ef Source #
Expands effects that have been bundled into an open union.
unbundleN :: forall (len :: Nat) (ef :: [EffectF]) (eh :: [EffectH]). KnownNat len => Eff eh (Union (Take len ef) ': Drop len ef) ~> Eff eh ef Source #
Expands the first len
effects that have been bundled into an open union.
bundleUnder :: forall (offset :: Natural) (bundle :: [EffectF]) (ef :: [EffectF]) (ef' :: [EffectF]) (eh :: [EffectH]). BundleUnder Union offset ef ef' bundle => Eff eh ef ~> Eff eh ef' Source #
Expands effects at an offset
below the head of the list into a single
element using an open union.
unbundleUnder :: forall (offset :: Natural) (bundle :: [EffectF]) (ef :: [EffectF]) (ef' :: [EffectF]) (eh :: [EffectH]). BundleUnder Union offset ef ef' bundle => Eff eh ef' ~> Eff eh ef Source #
Expands effects that have been bundled into an open union at an offset
below the head of the list.
bundleAll :: forall (eh :: [EffectH]) (ef :: [EffectF]) x. Eff eh ef x -> Eff eh '[Union ef] x Source #
Bundles all first-order effects into a single open union.
unbundleAll :: forall (eh :: [EffectH]) (ef :: [EffectF]) x. Eff eh '[Union ef] x -> Eff eh ef x Source #
Expands all first-order effects from a single open union.
bundleH :: forall (eh :: [EffectH]) (bundle :: [EffectH]) (rest :: [EffectH]) (ef :: [EffectF]). Split eh bundle rest => Eff eh ef ~> Eff (UnionH bundle ': rest) ef Source #
Bundles several effects at the head of the list into a single element using an open union.
unbundleH :: forall (eh :: [EffectH]) (bundle :: [EffectH]) (rest :: [EffectH]) (ef :: [EffectF]). Split eh bundle rest => Eff (UnionH bundle ': rest) ef ~> Eff eh ef Source #
Expands effects that have been bundled into an open union.
bundleUnderH :: forall (offset :: Natural) (bundle :: [EffectH]) (eh :: [EffectH]) (eh' :: [EffectH]) (ef :: [EffectF]). BundleUnder UnionH offset eh eh' bundle => Eff eh ef ~> Eff eh' ef Source #
Expands effects at an offset
below the head of the list into a single
element using an open union.
unbundleUnderH :: forall (offset :: Natural) (bundle :: [EffectH]) (eh :: [EffectH]) (eh' :: [EffectH]) (ef :: [EffectF]). BundleUnder UnionH offset eh eh' bundle => Eff eh' ef ~> Eff eh ef Source #
Expands effects that have been bundled into an open union at an offset
below the head of the list.
bundleAllH :: forall (eh :: [EffectH]) (ef :: [EffectF]) x. Eff eh ef x -> Eff '[UnionH eh] ef x Source #
Bundles all higher-order effects into a single open union.
unbundleAllH :: forall (eh :: [EffectH]) (ef :: [EffectF]) x. Eff '[UnionH eh] ef x -> Eff eh ef x Source #
Expands all higher-order effects from a single open union.
Manipulating Tags & Keys
tag :: forall {k} (tag :: k) (e :: EffectF) (ef :: [EffectF]) (eh :: [EffectH]) x. Eff eh (e ': ef) x -> Eff eh ((e # tag) ': ef) x Source #
Attaches the tag
to the first-order effect at the head of the list.
untag :: forall {k} (tag :: k) (e :: EffectF) (ef :: [Type -> Type]) (eh :: [EffectH]) x. Eff eh ((e # tag) ': ef) x -> Eff eh (e ': ef) x Source #
Removes the tag
from the tagged first-order effect at the head of the list.
retag :: forall {k1} {k2} (tag' :: k1) (tag :: k2) (e :: EffectF) (ef :: [Type -> Type]) (eh :: [EffectH]) x. Eff eh ((e # tag) ': ef) x -> Eff eh ((e # tag') ': ef) x Source #
Changes the tag
of the tagged first-order effect at the head of the list
to another tag tag'
.
tagH :: forall {k} (tag :: k) (e :: (Type -> Type) -> Type -> Type) (ef :: [EffectF]) (eh :: [(Type -> Type) -> Type -> Type]). HFunctor e => Eff (e ': eh) ef ~> Eff ((e ## tag) ': eh) ef Source #
Attaches the tag
to the higher-order effect at the head of the list.
untagH :: forall {k} (tag :: k) (e :: (Type -> Type) -> Type -> Type) (eh :: [(Type -> Type) -> Type -> Type]) (ef :: [EffectF]). HFunctor e => Eff ((e ## tag) ': eh) ef ~> Eff (e ': eh) ef Source #
Removes the tag
from the tagged higher-order effect at the head of the
list.
retagH :: forall {k1} {k2} (tag' :: k1) (tag :: k2) (e :: (Type -> Type) -> Type -> Type) (eh :: [(Type -> Type) -> Type -> Type]) (ef :: [EffectF]). HFunctor e => Eff ((e ## tag) ': eh) ef ~> Eff ((e ## tag') ': eh) ef Source #
Changes the tag
of the tagged higher-order effect at the head of the list
to another tag tag'
.
unkey :: forall {k} (key :: k) (e :: EffectF) (ef :: [Type -> Type]) (eh :: [EffectH]) x. Eff eh ((key #> e) ': ef) x -> Eff eh (e ': ef) x Source #
Removes the key
from the keyed first-order effect at the head of the list.
rekey :: forall {k1} {k2} (key' :: k1) (key :: k2) (e :: EffectF) (ef :: [Type -> Type]) (eh :: [EffectH]) x. Eff eh ((key #> e) ': ef) x -> Eff eh ((key' #> e) ': ef) x Source #
Changes the key
of the keyed first-order effect at the head of the list
to another key key'
.
unkeyH :: forall {k} (key :: k) (e :: (Type -> Type) -> Type -> Type) (eh :: [(Type -> Type) -> Type -> Type]) (ef :: [EffectF]). HFunctor e => Eff ((key ##> e) ': eh) ef ~> Eff (e ': eh) ef Source #
Removes the key
from the keyed higher-order effect at the head of the list.
rekeyH :: forall {k1} {k2} (key' :: k1) (key :: k2) (e :: (Type -> Type) -> Type -> Type) (eh :: [(Type -> Type) -> Type -> Type]) (ef :: [EffectF]). HFunctor e => Eff ((key ##> e) ': eh) ef ~> Eff ((key' ##> e) ': eh) ef Source #
Changes the key
of the keyed higher-order effect at the head of the list
to another key key'
.
Misc
class HFunctor (h :: (Type -> Type) -> Type -> Type) #
This class represents higher-order functors (Johann, Ghani, POPL '08) which are endofunctors on the category of endofunctors.
Instances
() => HFunctor Fix | |
() => HFunctor ChooseH | |
() => HFunctor Resource | |
() => HFunctor Reset | |
() => HFunctor (ChronicleH c) | |
Defined in Data.Effect.Chronicle hfmap :: forall (f :: Type -> Type) (g :: Type -> Type). (f :-> g) -> ChronicleH c f :-> ChronicleH c g # | |
() => HFunctor (Thread' tid) | |
() => HFunctor (Catch e) | |
() => HFunctor (Local r) | |
() => HFunctor (Shift_' b) | |
() => HFunctor (UnliftBase b) | |
Defined in Data.Effect.Unlift hfmap :: forall (f :: Type -> Type) (g :: Type -> Type). (f :-> g) -> UnliftBase b f :-> UnliftBase b g # | |
() => HFunctor (WriterH w) | |
HFunctor (LiftFOE ins) | |
HFunctor (UnionH es) Source # | |
() => HFunctor (Shift' r b) | |
HFunctor (HCont ff g) | |
Functor f => HFunctor (Compose f :: (Type -> Type) -> Type -> Type) | |
HFunctor f => HFunctor (f :&: a) | |
(HFunctor f, HFunctor g) => HFunctor (f :+: g) | |
() => HFunctor (Provider' ctx i b) | |
HFunctor sig => HFunctor (KeyH key sig) | |
HFunctor sig => HFunctor (TagH sig tag) | |
A key to be attached to the effect targeted by the MonadReader
instance.
Since MonadReader
has a functional dependency on r
, this is needed to uniquely specify r
.
A key to be attached to the effect targeted by the MonadWriter
instance.
Since MonadWriter
has a functional dependency on w
, this is needed to uniquely specify w
.
A key to be attached to the effect targeted by the MonadState
instance.
Since MonadState
has a functional dependency on s
, this is needed to uniquely specify s
.
A key to be attached to the effect targeted by the MonadError
instance.
Since MonadError
has a functional dependency on e
, this is needed to uniquely specify e
.
liftIO :: MonadIO m => IO a -> m a #
Lift a computation from the IO
monad.
This allows us to run IO computations in any monadic stack, so long as it supports these kinds of operations
(i.e. IO
is the base monad for the stack).
Example
import Control.Monad.Trans.State -- from the "transformers" library printState :: Show s => StateT s IO () printState = do state <- get liftIO $ print state
Had we omitted
, we would have ended up with this error:liftIO
• Couldn't match type ‘IO’ with ‘StateT s IO’ Expected type: StateT s IO () Actual type: IO ()
The important part here is the mismatch between StateT s IO ()
and
.IO
()
Luckily, we know of a function that takes an
and returns an IO
a(m a)
:
,
enabling us to run the program and see the expected results:liftIO
> evalStateT printState "hello" "hello" > evalStateT printState 3 3
module Data.Effect.OpenUnion
module Data.Effect
module Data.Effect.TH
module Control.Effect