Continuation Monad #
Monad encapsulating continuation passing programming style, similar to
Haskell's Cont, ContT and MonadCont:
https://hackage.haskell.org/package/mtl-2.2.2/docs/Control-Monad-Cont.html
https://hackage.haskell.org/package/transformers-0.6.2.0/docs/Control-Monad-Trans-Cont.html
A Label α m β is a jump target for MonadCont.callCC: it wraps a continuation α → m β,
which represents the rest of the computation surrounding the callCC block,
pending the value of type α.
Jumping to a label with MonadCont.goto abandons the rest of the block and finishes it immediately.
The result type β is arbitrary: a jump never returns control to the jump site,
so the m β it "returns" is never consumed (compare throw).
- apply : α → m β
The continuation to jump to. Use
MonadCont.gotorather than calling this directly.
Instances For
Jump to a label: abandon the rest of the enclosing MonadCont.callCC block
and finish the block immediately, with x as its result.
Equations
- MonadCont.goto f x = f.apply x
Instances For
The class of monads equipped with callCC ("call with current continuation").
At any point in a monadic computation, the "current continuation" is the rest of the computation:
everything that is waiting to consume the value produced so far.
callCC f captures the current continuation, packages it as a first-class value
(a MonadCont.Label), and hands it to f.
The label then acts as an escape hatch out of f, allowing possibilities like
early termination of the computation.
The canonical instance is the continuation monad transformer ContT.
Capture the current continuation as a
Labeland pass it to the given block.
Instances
The laws a well-behaved callCC must satisfy.
- seq_assoc {α β γ : Type u} (x : m α) (g : m (α → β)) (h : m (β → γ)) : h <*> (g <*> x) = Function.comp <$> h <*> g <*> x
- callCC_bind_right {α ω γ : Type u} (cmd : m α) (next : MonadCont.Label ω m γ → α → m ω) : (MonadCont.callCC fun (f : MonadCont.Label ω m γ) => cmd >>= next f) = do let x ← cmd MonadCont.callCC fun (f : MonadCont.Label ω m γ) => next f x
Actions performed before the label is available can be moved out of the block.
- callCC_bind_left {α : Type u} (β : Type u) (x : α) (dead : MonadCont.Label α m β → β → m α) : (MonadCont.callCC fun (f : MonadCont.Label α m β) => MonadCont.goto f x >>= dead f) = pure x
A jump discards everything sequenced after it.
- callCC_dummy {α β : Type u} (dummy : m α) : (MonadCont.callCC fun (x : MonadCont.Label α m β) => dummy) = dummy
A block that never uses its label is just the underlying computation.
Instances
The continuation transformer, the canonical instance of the MonadCont class.
Given a return type r, a type transformer (typically a monad) m, and a type α,
ContT r m α represents computations that take a continuation function from α to m r
and return an m r.
This allows for continuation-passing style programming, where control flow can be manipulated by capturing and invoking continuations.
Instances For
Transform the continuation of a computation.
Equations
- ContT.withContT f x g = x (f g)
Instances For
Note that tryCatch does not have correct behavior in this monad:
def foo : ContT Bool (Except String) Bool := do
let x ← try
pure true
catch _ =>
return false
throw s!"oh no {x}"
#eval foo.run pure
-- `Except.ok false`, no error
Here, the throwError is being run inside the try.
See Zulip
for further discussion.
Equations
- One or more equations did not get rendered due to their size.
Lift a jump target along ExceptT: jumping with a becomes a jump in the base monad
with Except.ok a.
Instances For
The callCC operation of ExceptT ε m, delegating to callCC in the base monad.
Equations
- ExceptT.callCC f = ExceptT.mk (MonadCont.callCC fun (x : MonadCont.Label (Except ε α) m β) => (f (ExceptT.mkLabel x)).run)
Instances For
Equations
- instMonadContExceptT = { callCC := fun {α β : Type ?u.2} => ExceptT.callCC }
Lift a jump target along OptionT: jumping with a becomes a jump in the base monad
with some a.
Instances For
The callCC operation of OptionT m, delegating to callCC in the base monad.
Equations
- OptionT.callCC f = OptionT.mk (MonadCont.callCC fun (x : MonadCont.Label (Option α) m β) => (f (OptionT.mkLabel x)).run)
Instances For
Equations
- instMonadContOptionT = { callCC := fun {α β : Type ?u.2} => OptionT.callCC }
Lift a jump target along WriterT (with EmptyCollection log):
jumping with a becomes a jump in the base monad with (a, ∅),
resetting the accumulated log to the start of the block.
Instances For
Lift a jump target along WriterT (with Monoid log):
jumping with a becomes a jump in the base monad with (a, 1),
resetting the accumulated log to the start of the block.
Instances For
The callCC operation of WriterT ω m (with EmptyCollection log),
delegating to callCC in the base monad.
Equations
Instances For
Equations
- instMonadContWriterTOfMonadOfEmptyCollection ω = { callCC := fun {α β : Type ?u.2} => WriterT.callCC }
Lift a jump target along StateT: jumping with a becomes a jump in the base monad
with (a, s), where s is the state at the jump site.
Equations
Instances For
The callCC operation of StateT σ m, delegating to callCC in the base monad;
the state at the jump site is carried through the jump.
Equations
- StateT.callCC f = StateT.mk fun (r : σ) => MonadCont.callCC fun (f' : MonadCont.Label (α × σ) m (β × σ)) => (f (StateT.mkLabel f')).run r
Instances For
Equations
- instMonadContStateT = { callCC := fun {α β : Type ?u.2} => StateT.callCC }
Lift a jump target along ReaderT; the jump does not depend on the environment.
Instances For
The callCC operation of ReaderT ε m, delegating to callCC in the base monad.
Equations
- ReaderT.callCC f = ReaderT.mk fun (r : ε) => MonadCont.callCC fun (f' : MonadCont.Label α m β) => (f (ReaderT.mkLabel ε f')).run r
Instances For
Equations
- instMonadContReaderT = { callCC := fun {α β : Type ?u.2} => ReaderT.callCC }
reduce the equivalence between two continuation passing monads to the equivalence between their underlying monad
Equations
- One or more equations did not get rendered due to their size.