Documentation

PfsProgs25.Unit11.Monads

Monads #

Monads m: Type u → Type v are a common structure for sequencing computations that can:

Operations #

Monads have the following operations:

These are not independent. The definition of monads only requires pure and bind, but map and flatten can be defined in terms of them.

Do notation #

The value of monads is that we can use the do notation to avoid explicitly writing bind and pure. Formally, a do block is just syntax for a term in Lean, with type of the form m α for some α. The do block is translated into a series of bind and pure calls.

Example: Stack #

This is just like a list but we put elements at the end.

inductive Stack (α : Type) :
Instances For
    instance instInhabitedStack {a✝ : Type} :
    Equations
    • instInhabitedStack = { default := Stack.empty }
    instance instReprStack {α✝ : Type} [Repr α✝] :
    Repr (Stack α✝)
    Equations
    • instReprStack = { reprPrec := reprStack✝ }
    def Stack.last? {α : Type} :
    Stack αOption α
    Equations
    • Stack.empty.last? = none
    • (a.push a_1).last? = some a_1
    Instances For
      def Stack.pop? {α : Type} :
      Stack αOption (Stack α × α)
      Equations
      • Stack.empty.pop? = none
      • (a.push a_1).pop? = some (a, a_1)
      Instances For
        Equations
        • Stack.eg = ((Stack.empty.push 1).push 2).push 3
        Instances For
          def Stack.pure {α : Type} (a : α) :
          Equations
          Instances For
            def Stack.map {α β : Type} (f : αβ) (s : Stack α) :
            Equations
            Instances For
              Equations
              Instances For
                Equations
                Instances For
                  def Stack.append {α : Type} (s₁ s₂ : Stack α) :
                  Equations
                  • s₁.append Stack.empty = s₁
                  • s₁.append (a.push a_1) = (s₁.append a).push a_1
                  Instances For
                    def Stack.flatten {α : Type} (ss : Stack (Stack α)) :
                    Equations
                    • Stack.empty.flatten = Stack.empty
                    • (ss_2.push s).flatten = ss_2.flatten.append s
                    Instances For
                      def Stack.flatMap {α β : Type} (f : αStack β) (s : Stack α) :
                      Equations
                      Instances For

                        Why flatten: example #

                        Equations
                        Instances For

                          In the following, flatMap is used to apply half? to the result of half?. However, do notation lets us get it conveniently.

                          First we see a naive version using map.

                          Equations
                          Instances For
                            Equations
                            Instances For

                              A simple monad is Id, which is just the identity function. It is useful for writing do blocks that do not involve any monadic operations.