| Copyright | (c) 2024 Sayo Koyoneda |
|---|---|
| License | MPL-2.0 (see the LICENSE file) |
| Maintainer | ymdfield@outlook.jp |
| Safe Haskell | None |
| Language | GHC2021 |
Control.Monad.Hefty
Description
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) =>Effeh (Log ': ef)~>Effeh ef runLog =interpret\(Log msg) -> liftIO $ putStrLn $ "[LOG] " <> msg runSpan :: (IO<|ef) =>Eff(Span ': eh) ef~>Effeh ef runSpan =interpretH\(Span name m) -> doliftIO$putStrLn$ "[Start span '" <> name <> "']" r <- mliftIO$putStrLn$ "[End span '" <> name <> "']"purer 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
makeEffectFandmakeEffectH. - The first
Efftype 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 =interpretHelabCatch elabCatch :: (eThrow<|ef) =>Catche~~>Eff'[] ef elabCatch (action hdl) = action &CatchinterposeWith\(e) _ -> hdl eThrowHere,
elabCatchis the elaborator for theCatcheffect.
- 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 theEffeh ef ~>Effeh' ef'Effmonad as an argument. In the previous example,elabCatchis the interpreter function for theCatcheffect, andrunCatchis the interpretation function for theCatcheffect.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
Throweffect.runThrow ::
Eff'[] (e ': r) a ->ThrowEff'[] r (Eithere a) runThrow =interpretBy(pure.Right) handleThrow handleThrow ::Interpreter(e) (ThrowEff'[] r) (Eithere a) handleThrow (e) _ =Throwpure$LefteHere,
handleThrowis the continuational stateful handler for theThroweffect.By calling the continuation argument multiple times, it allows for non-deterministic computations like the Data.Effect.NonDet effect.
runNonDet :: forall f ef a . (
Alternativef) =>Eff'[] (':ChooseEmpty': ef) a ->Eff'[] ef (f a) runNonDet =bundleN@2>>>interpretBy(pure.pure) ( (\k ->ChooseliftA2(<|>) (kFalse) (kTrue))!+(\_ ->Emptypureempty)!+nil)The function passed as the second argument to
interpretByis the continuational stateful handler.Additionally, what is passed as the first argument to
interpretByis 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~>Effeh ef ->Eff(e ': eh) ef ~>Effeh efinterpretH:: e (Effeh ef)~>Effeh ef ->Eff(e ': eh) ef~>Effeh efNote:
~>binds more tightly than->.
Functions may additionally have
WithorByat 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
Byfamily take two arguments: a value handler and a continuational stateful effect interpreter. They are the most generalized form. - Functions in the
Withfamily omit the value handler and take only the effect interpreter as an argument. - The difference between
interpretBy ret f mandinterpretWith f m >>= retis that, during interpretation, the delimited continuation passed as the second argumentktofin the former extends up to whenretfinishes, whereas in the latter, it only goes untilmfinishes (just beforeret), soretis not included ink. - Functions without
WithorBycannot 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
Recadditionally added.Non-recursive continuational stateful interpretation functions like
interpretWithcannot be used unless the higher-order effects are empty:interpretWith:: e ~> Eff '[] ef =>Eff'[] (e ': ef) ~>Eff'[] efThe
Recversions can be used even whenehis not empty.interpretRecWith:: e ~>Effeh (e ': ef) ~>Effeh 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 String
makeEffectF [''SomeEff]
-- | Throws an exception when 'SomeAction' is encountered
runSomeEff :: (Throw String <| 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 `catch` \(_ :: String) -> 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 :: (eThrow<|ef) =>Eff'[e] efCatch~>Eff'[] ef runCatch =interpretHelabCatch elabCatch :: (eThrow<|ef) =>Catche~~>Eff'[] ef elabCatch (action hdl) = action &CatchinterposeWith\(e) _ -> hdl eThrow
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) ->catchpure"caught" ==>throw"not caught" `` \(_ :: String) ->catchpure"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) ->catchpure"caught" ==>interposeWith(\(e) _ ->Throwpure"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) ->catchpure"caught" ==>interposeWith(\(@Throwe) _ ->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.
IOis just an opaque algebraic data type whose definition you cannot see, no different from others.- The runtime system treats the value
mainas 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
IOtype 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::Effeh (s ': ef)State~>Effeh 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 =runEffdo 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 resets 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 =runEffdo 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,CatchInt] '[CatchString,ThrowInt] ()Throw
In this case, you may get stuck trying to use runCatch.
This is because runCatch has the following type signature:
runCatch :: (eThrow<|ef) =>Eff'[e] efCatch~>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 $ progIn 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,ThrowInt] () prog' =ThrowinterpretH(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.
Constructors
| 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
Arguments
| :: 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.
Arguments
| :: 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.
Arguments
| :: 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.
Arguments
| :: 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
Arguments
| :: 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.
Arguments
| :: 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.
Arguments
| :: 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.
Arguments
| :: 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
Arguments
| :: 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.
Arguments
| :: 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.
Arguments
| :: 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.
Arguments
| :: 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
Arguments
| :: 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.
Arguments
| :: 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
Arguments
| :: 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.
Arguments
| :: 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.
Arguments
| :: 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.
Arguments
| :: 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.
Arguments
| :: 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.
Arguments
| :: 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.
Arguments
| :: 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.
Minimal complete definition
Instances
| () => HFunctor Fix | |
| () => HFunctor ChooseH | |
| () => HFunctor Resource | |
| () => HFunctor Reset | |
| () => HFunctor (ChronicleH c) | |
Defined in Data.Effect.Chronicle Methods 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 Methods 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