Documentation

Mathlib.Control.Monad.Cont

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

structure MonadCont.Label (α : Type w) (m : Type u → Type v) (β : Type u) :
Type (max v w)

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.goto rather than calling this directly.

Instances For
    @[reducible, inline]
    abbrev MonadCont.goto {α : Type u_1} {β : Type u} {m : Type u → Type v} (f : Label α m β) (x : α) :
    m β

    Jump to a label: abandon the rest of the enclosing MonadCont.callCC block and finish the block immediately, with x as its result.

    Equations
    Instances For
      class MonadCont (m : Type u → Type v) :
      Type (max (u + 1) v)

      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.

      • callCC {α β : Type u} : (Label α m β → m α) → m α

        Capture the current continuation as a Label and pass it to the given block.

      Instances
        class LawfulMonadCont (m : Type u → Type v) [Monad m] [MonadCont m] extends LawfulMonad m :

        The laws a well-behaved callCC must satisfy.

        Instances
          def ContT (r : Type u) (m : Type u → Type v) (α : Type w) :
          Type (max v w)

          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.

          Equations
          • ContT r m α = ((α → m r) → m r)
          Instances For
            @[reducible, inline]
            abbrev Cont (r : Type u) (α : Type w) :
            Type (max u w)

            The continuation monad: ContT over the identity monad.

            Equations
            Instances For
              def ContT.mk {r : Type u} {m : Type u → Type v} {α : Type w} (f : (α → m r) → m r) :
              ContT r m α

              Build a ContT from a function taking a continuation callback.

              Equations
              Instances For
                def ContT.run {r : Type u} {m : Type u → Type v} {α : Type w} (x : ContT r m α) :
                (α → m r) → m r

                Run a ContT with a provided callback.

                Equations
                Instances For
                  def ContT.map {r : Type u} {m : Type u → Type v} {α : Type w} (f : m r → m r) (x : ContT r m α) :
                  ContT r m α

                  Compose a given function with the continuation computation.

                  Equations
                  Instances For
                    theorem ContT.run_contT_map_contT {r : Type u} {m : Type u → Type v} {α : Type w} (f : m r → m r) (x : ContT r m α) :
                    (map f x).run = f ∘ x.run
                    def ContT.withContT {r : Type u} {m : Type u → Type v} {α β : Type w} (f : (β → m r) → α → m r) (x : ContT r m α) :
                    ContT r m β

                    Transform the continuation of a computation.

                    Equations
                    Instances For
                      theorem ContT.run_withContT {r : Type u} {m : Type u → Type v} {α β : Type w} (f : (β → m r) → α → m r) (x : ContT r m α) :
                      (withContT f x).run = x.run ∘ f
                      theorem ContT.ext {r : Type u} {m : Type u → Type v} {α : Type w} {x y : ContT r m α} (h : ∀ (f : α → m r), x.run f = y.run f) :
                      x = y
                      theorem ContT.ext_iff {r : Type u} {m : Type u → Type v} {α : Type w} {x y : ContT r m α} :
                      x = y ↔ ∀ (f : α → m r), x.run f = y.run f
                      @[instance_reducible]
                      instance ContT.instMonad {r : Type u} {m : Type u → Type v} :
                      Monad (ContT r m)
                      Equations
                      • One or more equations did not get rendered due to their size.
                      @[simp]
                      theorem ContT.run_mk {r : Type u} {m : Type u → Type v} {α : Type w} (f : (α → m r) → m r) (k : α → m r) :
                      (mk f).run k = f k
                      @[simp]
                      theorem ContT.run_pure {r : Type u} {m : Type u → Type v} {α : Type w} (a : α) (k : α → m r) :
                      (pure a).run k = k a
                      @[simp]
                      theorem ContT.run_bind {r : Type u} {m : Type u → Type v} {α β : Type w} (x : ContT r m α) (f : α → ContT r m β) (k : β → m r) :
                      (x >>= f).run k = x.run fun (x : α) => (f x).run k
                      @[simp]
                      theorem ContT.run_map {r : Type u} {m : Type u → Type v} {α β : Type w} (f : α → β) (x : ContT r m α) (k : β → m r) :
                      (f <$> x).run k = x.run (k ∘ f)
                      @[simp]
                      theorem ContT.run_seq {r : Type u} {m : Type u → Type v} {α β : Type w} (f : ContT r m (α → β)) (x : ContT r m α) (k : β → m r) :
                      (f <*> x).run k = f.run fun (f : α → β) => x.run (k ∘ f)
                      @[simp]
                      theorem ContT.run_seqLeft {r : Type u} {m : Type u → Type v} {α β : Type w} (x : ContT r m α) (y : ContT r m β) (k : α → m r) :
                      (x <* y).run k = x.run fun (x : α) => y.run fun (x_1 : β) => k x
                      @[simp]
                      theorem ContT.run_seqRight {r : Type u} {m : Type u → Type v} {α β : Type w} (x : ContT r m α) (y : ContT r m β) (k : β → m r) :
                      (x *> y).run k = x.run fun (x : α) => y.run k
                      instance ContT.instLawfulMonad {r : Type u} {m : Type u → Type v} :
                      @[instance_reducible]
                      instance ContT.instMonadLiftOfMonad {r : Type u} {m : Type u → Type v} [Monad m] :
                      Equations
                      @[simp]
                      theorem ContT.run_monadLift {r : Type u} {m : Type u → Type v} [Monad m] {α : Type u} (x : m α) (k : α → m r) :
                      (monadLift x).run k = x >>= k
                      theorem ContT.monadLift_bind {r : Type u} {m : Type u → Type v} [Monad m] [LawfulMonad m] {α β : Type u} (x : m α) (f : α → m β) :
                      @[instance_reducible]
                      instance ContT.instMonadCont {r : Type u} {m : Type u → Type v} :
                      Equations
                      • One or more equations did not get rendered due to their size.
                      @[simp]
                      theorem ContT.run_callCC {r : Type u} {m : Type u → Type v} {α β : Type w} (f : Label α (ContT r m) β → ContT r m α) (k : α → m r) :
                      (MonadCont.callCC f).run k = (f { apply := fun (x : α) => mk fun (x_1 : β → m r) => k x }).run k
                      instance ContT.instLawfulMonadCont {r : Type u} {m : Type u → Type v} :
                      @[instance_reducible]
                      instance ContT.instMonadExceptOf {r : Type u} {m : Type u → Type v} (ε : Type u_1) [MonadExceptOf ε m] :

                      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.
                      @[simp]
                      theorem ContT.run_throw {r : Type u} {m : Type u → Type v} {α : Type w} {ε : Type u_1} [MonadExceptOf ε m] (e : ε) (f : α → m r) :
                      (throw e).run f = throw e
                      @[simp]
                      theorem ContT.run_tryCatch {r : Type u} {m : Type u → Type v} {α : Type w} {ε : Type u_1} [MonadExceptOf ε m] (act : ContT r m α) (h : ε → ContT r m α) (f : α → m r) :
                      (tryCatch act h).run f = tryCatch (act.run f) fun (e : ε) => (h e).run f
                      def ExceptT.mkLabel {m : Type u → Type v} [Monad m] {α β ε : Type u} :
                      MonadCont.Label (Except ε α) m β → MonadCont.Label α (ExceptT ε m) β

                      Lift a jump target along ExceptT: jumping with a becomes a jump in the base monad with Except.ok a.

                      Equations
                      Instances For
                        theorem ExceptT.goto_mkLabel {m : Type u → Type v} [Monad m] {α β ε : Type u} (x : MonadCont.Label (Except ε α) m β) (i : α) :
                        def ExceptT.callCC {m : Type u → Type v} [Monad m] {ε : Type u} [MonadCont m] {α β : Type u} (f : MonadCont.Label α (ExceptT ε m) β → ExceptT ε m α) :
                        ExceptT ε m α

                        The callCC operation of ExceptT ε m, delegating to callCC in the base monad.

                        Equations
                        Instances For
                          @[instance_reducible]
                          instance instMonadContExceptT {m : Type u → Type v} [Monad m] {ε : Type u} [MonadCont m] :
                          Equations
                          def OptionT.mkLabel {m : Type u → Type v} [Monad m] {α β : Type u} :

                          Lift a jump target along OptionT: jumping with a becomes a jump in the base monad with some a.

                          Equations
                          Instances For
                            theorem OptionT.goto_mkLabel {m : Type u → Type v} [Monad m] {α β : Type u} (x : MonadCont.Label (Option α) m β) (i : α) :
                            def OptionT.callCC {m : Type u → Type v} [Monad m] [MonadCont m] {α β : Type u} (f : MonadCont.Label α (OptionT m) β → OptionT m α) :
                            OptionT m α

                            The callCC operation of OptionT m, delegating to callCC in the base monad.

                            Equations
                            Instances For
                              @[simp]
                              theorem run_callCC {m : Type u → Type v} [Monad m] [MonadCont m] {α β : Type u} (f : MonadCont.Label α (OptionT m) β → OptionT m α) :
                              @[instance_reducible]
                              instance instMonadContOptionT {m : Type u → Type v} [Monad m] [MonadCont m] :
                              Equations
                              def WriterT.mkLabel {m : Type u → Type v} [Monad m] {α : Type u_1} {β ω : Type u} [EmptyCollection ω] :
                              MonadCont.Label (α × ω) m β → MonadCont.Label α (WriterT ω m) β

                              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.

                              Equations
                              Instances For
                                def WriterT.mkLabel' {m : Type u → Type v} [Monad m] {α : Type u_1} {β ω : Type u} [Monoid ω] :
                                MonadCont.Label (α × ω) m β → MonadCont.Label α (WriterT ω m) β

                                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.

                                Equations
                                Instances For
                                  theorem WriterT.goto_mkLabel {m : Type u → Type v} [Monad m] {α : Type u_1} {β ω : Type u} [EmptyCollection ω] (x : MonadCont.Label (α × ω) m β) (i : α) :
                                  theorem WriterT.goto_mkLabel' {m : Type u → Type v} [Monad m] {α : Type u_1} {β ω : Type u} [Monoid ω] (x : MonadCont.Label (α × ω) m β) (i : α) :
                                  def WriterT.callCC {m : Type u → Type v} [Monad m] [MonadCont m] {α β ω : Type u} [EmptyCollection ω] (f : MonadCont.Label α (WriterT ω m) β → WriterT ω m α) :
                                  WriterT ω m α

                                  The callCC operation of WriterT ω m (with EmptyCollection log), delegating to callCC in the base monad.

                                  Equations
                                  Instances For
                                    def WriterT.callCC' {m : Type u → Type v} [Monad m] [MonadCont m] {α β ω : Type u} [Monoid ω] (f : MonadCont.Label α (WriterT ω m) β → WriterT ω m α) :
                                    WriterT ω m α

                                    The callCC operation of WriterT ω m (with Monoid log), delegating to callCC in the base monad.

                                    Equations
                                    Instances For
                                      @[instance_reducible]
                                      Equations
                                      @[instance_reducible]
                                      instance instMonadContWriterTOfMonadOfMonoid {m : Type u → Type v} (ω : Type u) [Monad m] [Monoid ω] [MonadCont m] :
                                      Equations
                                      def StateT.mkLabel {m : Type u → Type v} {α β σ : Type u} :
                                      MonadCont.Label (α × σ) m (β × σ) → MonadCont.Label α (StateT σ m) β

                                      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
                                        theorem StateT.goto_mkLabel {m : Type u → Type v} {α β σ : Type u} (x : MonadCont.Label (α × σ) m (β × σ)) (i : α) :
                                        MonadCont.goto (mkLabel x) i = mk fun (s : σ) => MonadCont.goto x (i, s)
                                        def StateT.callCC {m : Type u → Type v} {σ : Type u} [MonadCont m] {α β : Type u} (f : MonadCont.Label α (StateT σ m) β → StateT σ m α) :
                                        StateT σ m α

                                        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
                                        Instances For
                                          @[instance_reducible]
                                          instance instMonadContStateT {m : Type u → Type v} {σ : Type u} [MonadCont m] :
                                          Equations
                                          def ReaderT.mkLabel {m : Type u → Type v} {α : Type u_1} {β : Type u} (ρ : Type u) :
                                          MonadCont.Label α m β → MonadCont.Label α (ReaderT ρ m) β

                                          Lift a jump target along ReaderT; the jump does not depend on the environment.

                                          Equations
                                          Instances For
                                            theorem ReaderT.goto_mkLabel {m : Type u → Type v} {α : Type u_1} {ρ β : Type u} (x : MonadCont.Label α m β) (i : α) :
                                            def ReaderT.callCC {m : Type u → Type v} {ε : Type u} [MonadCont m] {α β : Type u} (f : MonadCont.Label α (ReaderT ε m) β → ReaderT ε m α) :
                                            ReaderT ε m α

                                            The callCC operation of ReaderT ε m, delegating to callCC in the base monad.

                                            Equations
                                            Instances For
                                              @[instance_reducible]
                                              instance instMonadContReaderT {m : Type u → Type v} {ρ : Type u} [MonadCont m] :
                                              Equations
                                              def ContT.equiv {m₁ : Type u₀ → Type v₀} {m₂ : Type u₁ → Type v₁} {α₁ r₁ : Type u₀} {α₂ r₂ : Type u₁} (F : m₁ r₁ ≃ m₂ r₂) (G : α₁ ≃ α₂) :
                                              ContT r₁ m₁ α₁ ≃ ContT r₂ m₂ α₂

                                              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.
                                              Instances For