Documentation

Cslib.Foundations.Control.Monad.Free.Effects

Free Monad #

This file defines several canonical instances on the free monad.

Main definitions #

Implementation #

To execute or interpret these computations, we provide two approaches:

  1. Hand-written interpreters (FreeState.run, FreeWriter.run, FreeCont.run) that directly pattern-match on the tree structure
  2. Canonical interpreters (FreeState.toStateM, FreeWriter.toWriterT, FreeCont.toContT) derived from the universal property via liftM

We prove that these approaches are equivalent, demonstrating that the implementation aligns with the theory. We also provide uniqueness theorems for the canonical interpreters, which follow from the universal property.

Tags #

Free monad, state monad, writer monad, continuation monad

State Monad via FreeM #

inductive Cslib.FreeM.StateF (σ : Type u) :
Type u → Type u

Type constructor for state operations.

Instances For
    @[reducible, inline]
    abbrev Cslib.FreeM.FreeState (σ : Type u) (α : Type u_1) :
    Type (max (u + 1) u_1)

    State monad via the FreeM monad.

    Equations
    Instances For
      Equations
      • One or more equations did not get rendered due to their size.
      @[simp]
      theorem Cslib.FreeM.FreeState.set_def {σ : Type u} (s : σ) :
      def Cslib.FreeM.FreeState.toStateM {σ α : Type u} (comp : FreeState σ α) :
      StateM σ α

      Convert a FreeState computation into a StateM computation. This is the canonical interpreter derived from liftM.

      Equations
      Instances For
        theorem Cslib.FreeM.FreeState.toStateM_unique {σ α : Type u} (g : FreeState σ αStateM σ α) (h : Interprets (fun {ι : Type u} => stateInterp) g) :

        toStateM is the unique interpreter extending stateInterp.

        def Cslib.FreeM.FreeState.run {σ : Type u} {α : Type v} (comp : FreeState σ α) (s₀ : σ) :
        α × σ

        Run a state computation, returning both the result and final state.

        Equations
        Instances For
          @[simp]
          theorem Cslib.FreeM.FreeState.run_toStateM {σ α : Type u} (comp : FreeState σ α) :

          The canonical interpreter toStateM derived from liftM agrees with the hand-written recursive interpreter run for FreeState.

          @[simp]
          theorem Cslib.FreeM.FreeState.run_pure {σ : Type u} {α : Type v} (a : α) (s₀ : σ) :
          run (FreeM.pure a) s₀ = (a, s₀)
          @[simp]
          theorem Cslib.FreeM.FreeState.run_get {σ : Type u} {α : Type v} (k : σFreeState σ α) (s₀ : σ) :
          run (liftBind StateF.get k) s₀ = (k s₀).run s₀
          @[simp]
          theorem Cslib.FreeM.FreeState.run_set {σ : Type u} {α : Type v} (s' : σ) (k : PUnit.{u + 1}FreeState σ α) (s₀ : σ) :
          run (liftBind (StateF.set s') k) s₀ = (k PUnit.unit).run s'
          def Cslib.FreeM.FreeState.run' {σ : Type u} {α : Type v} (c : FreeState σ α) (s₀ : σ) :
          α

          Run a state computation, returning only the result.

          Equations
          Instances For
            @[simp]
            theorem Cslib.FreeM.FreeState.run'_toStateM {σ α : Type u} (comp : FreeState σ α) :
            @[simp]
            theorem Cslib.FreeM.FreeState.run'_pure {σ : Type u} {α : Type v} (a : α) (s₀ : σ) :
            run' (FreeM.pure a) s₀ = a
            @[simp]
            theorem Cslib.FreeM.FreeState.run'_get {σ : Type u} {α : Type v} (k : σFreeState σ α) (s₀ : σ) :
            run' (liftBind StateF.get k) s₀ = (k s₀).run' s₀
            @[simp]
            theorem Cslib.FreeM.FreeState.run'_set {σ : Type u} {α : Type v} (s' : σ) (k : PUnit.{u + 1}FreeState σ α) (s₀ : σ) :
            run' (liftBind (StateF.set s') k) s₀ = (k PUnit.unit).run' s'

            Writer Monad via FreeM #

            inductive Cslib.FreeM.WriterF (ω : Type u) :
            Type v → Type u

            Type constructor for writer operations. Writer has a single effect, so the definition has just one constructor.

            Instances For
              @[reducible, inline]
              abbrev Cslib.FreeM.FreeWriter (ω : Type u) (α : Type u_1) :
              Type (max (max (u_2 + 1) u) u_1)

              Writer monad implemented via the FreeM monad construction. This provides a more efficient implementation than the traditional WriterT transformer, as it avoids buffering the log.

              Equations
              Instances For
                def Cslib.FreeM.FreeWriter.writerInterp {ω α : Type u} :
                WriterF ω αWriterT ω Id α

                Interpret WriterF operations into WriterT.

                Equations
                Instances For
                  def Cslib.FreeM.FreeWriter.toWriterT {ω α : Type u} [Monoid ω] (comp : FreeWriter ω α) :
                  WriterT ω Id α

                  Convert a FreeWriter computation into a WriterT computation. This is the canonical interpreter derived from liftM.

                  Equations
                  Instances For
                    theorem Cslib.FreeM.FreeWriter.toWriterT_unique {ω α : Type u} [Monoid ω] (g : FreeWriter ω αWriterT ω Id α) (h : Interprets (fun {ι : Type u} => writerInterp) g) :

                    toWriterT is the unique interpreter extending writerInterp.

                    @[reducible, inline]

                    Writes a log entry. This creates an effectful node in the computation tree.

                    Equations
                    Instances For
                      @[simp]
                      theorem Cslib.FreeM.FreeWriter.tell_def {ω : Type u} (w : ω) :
                      def Cslib.FreeM.FreeWriter.run {ω : Type u} {α : Type v} [Monoid ω] :
                      FreeWriter ω αα × ω

                      Interprets a FreeWriter computation by recursively traversing the tree, accumulating log entries with the monoid operation, and returns the final value paired with the accumulated log.

                      Equations
                      Instances For
                        @[simp]
                        theorem Cslib.FreeM.FreeWriter.run_pure {ω : Type u} {α : Type v} [Monoid ω] (a : α) :
                        @[simp]
                        theorem Cslib.FreeM.FreeWriter.run_liftBind_tell {ω : Type u} {α : Type v} [Monoid ω] (w : ω) (k : PUnit.{u_1 + 1}FreeWriter ω α) :
                        run (liftBind (WriterF.tell w) k) = match (k PUnit.unit).run with | (a, w') => (a, w * w')
                        @[simp]
                        theorem Cslib.FreeM.FreeWriter.run_toWriterT {ω α : Type u} [Monoid ω] (comp : FreeWriter ω α) :
                        comp.toWriterT.run = comp.run

                        The canonical interpreter toWriterT derived from liftM agrees with the hand-written recursive interpreter run for FreeWriter.

                        def Cslib.FreeM.FreeWriter.listen {ω : Type u} {α : Type v} [Monoid ω] :
                        FreeWriter ω αFreeWriter ω (α × ω)

                        listen captures the log produced by a subcomputation incrementally. It traverses the computation, emitting log entries as encountered, and returns the accumulated log as a result.

                        Equations
                        Instances For
                          @[simp]
                          theorem Cslib.FreeM.FreeWriter.listen_pure {ω : Type u} {α : Type v} [Monoid ω] (a : α) :
                          @[simp]
                          theorem Cslib.FreeM.FreeWriter.listen_liftBind_tell {ω : Type u} {α : Type v} [Monoid ω] (w : ω) (k : PUnit.{u_1 + 1}FreeWriter ω α) :
                          listen (liftBind (WriterF.tell w) k) = liftBind (WriterF.tell w) fun (x : PUnit.{u_2 + 1}) => do let x(k PUnit.unit).listen match x with | (a, w') => pure (a, w * w')
                          def Cslib.FreeM.FreeWriter.pass {ω : Type u} {α : Type v} [Monoid ω] (m : FreeWriter ω (α × (ωω))) :

                          pass allows a subcomputation to modify its own log. After traversing the computation and accumulating its log, the resulting function is applied to rewrite the accumulated log before re-emission.

                          Equations
                          Instances For
                            @[simp]
                            theorem Cslib.FreeM.FreeWriter.pass_def {ω : Type u} {α : Type v} [Monoid ω] (m : FreeWriter ω (α × (ωω))) :
                            m.pass = match m.run with | ((a, f), w) => liftBind (WriterF.tell (f w)) fun (x : PUnit.{u_2 + 1}) => FreeM.pure a
                            Equations
                            • One or more equations did not get rendered due to their size.

                            Continuation Monad via FreeM #

                            inductive Cslib.FreeM.ContF (r : Type u) (α : Type v) :
                            Type (max u v)

                            Type constructor for continuation operations.

                            • callCC {r : Type u} {α : Type v} : ((αr)r)ContF r α

                              Call with current continuation: provides access to the current continuation.

                            Instances For
                              Equations
                              • One or more equations did not get rendered due to their size.
                              @[reducible, inline]
                              abbrev Cslib.FreeM.FreeCont (r : Type u) (α : Type u_1) :
                              Type (max (max (u_2 + 1) u_2 u) u_1)

                              Continuation monad via the FreeM monad.

                              Equations
                              Instances For
                                def Cslib.FreeM.FreeCont.contInterp {r : Type u} {α : Type v} :
                                ContF r αContT r Id α

                                Interpret ContF r operations into ContT r Id.

                                Equations
                                Instances For
                                  def Cslib.FreeM.FreeCont.toContT {r α : Type u} (comp : FreeCont r α) :
                                  ContT r Id α

                                  Convert a FreeCont computation into a ContT computation. This is the canonical interpreter derived from liftM.

                                  Equations
                                  Instances For
                                    theorem Cslib.FreeM.FreeCont.toContT_unique {r α : Type u} (g : FreeCont r αContT r Id α) (h : Interprets (fun {ι : Type u} => contInterp) g) :

                                    toContT is the unique interpreter extending contInterp.

                                    def Cslib.FreeM.FreeCont.run {r : Type u} {α : Type v} :
                                    FreeCont r α(αr)r

                                    Run a continuation computation with the given continuation.

                                    Equations
                                    Instances For
                                      @[simp]
                                      theorem Cslib.FreeM.FreeCont.run_toContT {r α : Type u} (comp : FreeCont r α) :
                                      comp.toContT.run = comp.run

                                      The canonical interpreter toContT derived from liftM agrees with the hand-written recursive interpreter run for FreeCont.

                                      @[simp]
                                      theorem Cslib.FreeM.FreeCont.run_pure {r : Type u} {α : Type v} (a : α) (k : αr) :
                                      run (FreeM.pure a) k = k a
                                      @[simp]
                                      theorem Cslib.FreeM.FreeCont.run_liftBind_callCC {r : Type u} {α : Type v} {β : Type w} (g : (αr)r) (cont : αFreeCont r β) (k : βr) :
                                      run (liftBind (ContF.callCC g) cont) k = g fun (a : α) => (cont a).run k
                                      def Cslib.FreeM.FreeCont.callCC {r : Type u} {α : Type v} {β : Type w} (f : MonadCont.Label α (FreeCont r) βFreeCont r α) :

                                      Call with current continuation for the Free continuation monad.

                                      Equations
                                      • One or more equations did not get rendered due to their size.
                                      Instances For
                                        @[simp]
                                        theorem Cslib.FreeM.FreeCont.callCC_def {r : Type u} {α : Type v} {β : Type w} (f : MonadCont.Label α (FreeCont r) βFreeCont r α) :
                                        callCC f = liftBind (ContF.callCC fun (k : αr) => (f { apply := fun (x : α) => liftBind (ContF.callCC fun (x_1 : βr) => k x) pure }).run k) pure
                                        @[simp]
                                        theorem Cslib.FreeM.FreeCont.run_callCC {r : Type u} {α : Type v} {β : Type w} (f : MonadCont.Label α (FreeCont r) βFreeCont r α) (k : αr) :
                                        (callCC f).run k = (f { apply := fun (x : α) => liftBind (ContF.callCC fun (x_1 : βr) => k x) pure }).run k

                                        run of a callCC node simplifies to running the handler with the current continuation.