| Safe Haskell | Safe-Inferred |
|---|---|
| Language | Haskell2010 |
Bluefin.Algae.DelCont
Description
Delimited continuations
Native multi-prompt delimited continuations.
These primitives let us manipulate slices of the call stack/evaluation
context delimited by reset.
This module serves as a foundation for algebraic effect handlers, a more structured interface for manipulating continuations and implementing user-defined effects.
The behavior of reset and shift0 is summarized by the following equations:
reset(\_ ->purex) =purexreset(\t -> C (shift0t f)) = f (\x ->reset(\t -> C x))
where C is an evaluation context (in which t may occur), i.e.,
a term of the following form:
C x ::= C x >>= k -- for any function k
| H (\h -> C x) -- for any handler H ∈ { reset, (`runState` s), ... }
| xThis module ensures type safety. The rank-2 type of reset
guarantees that shift0 will always have a maching reset on the stack.
References
- Delimited continuation primops (GHC proposal, implemented in GHC 9.6.1).
- Shift to Control (2004) by Chung-chieh Shan. The name
shift0follows the nomenclature in that paper.
Synopsis
- data PromptTag ss a s
- reset :: forall a ss. (forall s. PromptTag ss a s -> Eff (s :& ss) a) -> Eff ss a
- shift0 :: forall s a b ss ss0. s :> ss0 => PromptTag ss a s -> (Continuation ss0 ss b a -> Eff ss a) -> Eff ss0 b
- data Continuation t s b a
- weakenC1 :: Continuation t s b a -> Continuation (e :& t) (e :& s) b a
- resume :: Continuation t s b a -> Eff t b -> Eff s a
- continue :: Continuation t s b a -> b -> Eff s a
- cancel :: Continuation t s b a -> Eff s ()
Documentation
reset :: forall a ss. (forall s. PromptTag ss a s -> Eff (s :& ss) a) -> Eff ss a Source #
Run the enclosed computation under a prompt of type Eff ss a.
f : forall s.PromptTagss a s ->Eff(s:&ss) a -------------------------------------------------reset(\t -> f t) :Effss a
The enclosed computation f is given a tag which identifies that prompt
and remembers its type.
The scope parameter s prevents the tag from being used outside of the
computation.
A prompt (reset) delimits a slice of the call stack (or evaluation context),
which can be captured with shift0. This slice, a continuation,
becomes a function of type Eff ss0 b -> Eff ss a (where Eff ss0 b is the
result type of shift0 at its calling site).
Calling the continuation restores the slice on the stack.
shift0 :: forall s a b ss ss0. s :> ss0 => PromptTag ss a s -> (Continuation ss0 ss b a -> Eff ss a) -> Eff ss0 b Source #
Capture the continuation up to the tagged prompt.
_ : s :> ss0 t :PromptTagss a s f : (Effss0 b ->Effss a) ->Effss a ---------------------------------------shift0t (\k -> f k) :Effss0 b
The prompt (reset) is reinserted on the stack when the continuation is called:
reset(\t -> C (shift0t f)) = f (\x ->reset(\t -> C x))
data Continuation t s b a Source #
Continuations are slices of the call stack, or evaluation context.
The Continuation type is abstract since not all functions
represent evaluation contexts. In particular, Eff t b -> Eff s aweakenC1 is not definable for arbitrary
such functions.
For example, in
reset \tag0 ->
reset \tag1 ->
reset \tag2 ->
shift0 tag1 f >>= etc
shift0 captures a continuation, the slice represented by the following
function:
MkContinuation \hole ->
reset \tag1 ->
reset \tag2 ->
hole >>= etc
That continuation has type where Continuation t s b aEff t b is the type of the hole,
and Eff s a is the type of the result once the hole is plugged.
The second argument of shift0, f, is applied to the continuation:
reset \tag0 ->
f (MkContinuation \hole ->
reset \tag1 ->
reset \tag2 ->
hole >>= etc)
weakenC1 :: Continuation t s b a -> Continuation (e :& t) (e :& s) b a Source #
Extend the context of a continuation.
resume :: Continuation t s b a -> Eff t b -> Eff s a Source #
Resume a continuation with a computation under it.
continue :: Continuation t s b a -> b -> Eff s a Source #
Resume a cancellable continuation with a result.
In other words, this converts a cancellable continuation to a simple continuation.
cancel :: Continuation t s b a -> Eff s () Source #
Cancel a continuation: resume by throwing a scoped exception and catch it.
The continuation SHOULD re-throw unknown exceptions. (That is guaranteed if you don't use Exception.Dynamic.)