Monads #
Monads m: Type u → Type v are a common structure for sequencing computations that can:
- involve elements in a collection such as a list
List, - fail or have no result, such as
Option, - depend on and alter state, such as
StateM, - take a long time, such as
Task, - have side effects, such as
IO, ...
Operations #
Monads have the following operations:
pure : α → m αlifts a value into the monad;returnis closely related.bind : m α → (α → m β) → m βsequences two computations, also calledflatMapin concrete cases.map : (α → β) → m α → m βapplies a function to the result of a computation.flatten : m (m α) → m αcollapses nested monadic layers.
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.
Equations
- Stack.pure a = Stack.empty.push a
Instances For
Equations
- Stack.flatMap f s = (Stack.map f s).flatten
Instances For
Why flatten: example #
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
- Monads.quarter? n = do let n' ← Monads.half? n let n'' ← Monads.half? n' pure n''
Instances For
Equations
- Monads.quarter?' n = (Monads.half? n).bind Monads.half?
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.