Inductive types and trees #
As we have seen, inductive types are given by constructors. To fully understand these, we must understand:
- What are the allowed types of the constructors?
- What are the corresponding types of the
rec
functions? - What identities are satisfied by these?
Since the constructs give elements of T
, they must be (dependent) functions with codomain T
, or (dependent) functions with codomain (dependent) functions with codomain T
, etc. Thus, possible types of constructors are:
T
.- If
X
(= ... → T
) is a possible type andA
is defined in the context, thenA → X
. - If
X
(= ... → T
) is a possible type, thenT → X
. - If
X
(= ... → T
) is a possible type andA
is defined in the context, then(A → T) → X
is a possible type (we can generalize toA → B → T
etc. and families).
Parameterized inductive types #
We also have parametrized inductive types like lists, where we are defining a family of types List α
for each α
. In this case, the constructors can depend on the parameter α
.
To be precise, a family of types is one of:
- A type
T : Type u
. - Given a type
A
and a family of typesX
, the typeA → X
. - Given a type
A
, and, for eacha : A
, a family of typesX a
, the typeΠ (a : A), X a = (a: A) → X a
. - Given a type
A
and a family of typesX
, the typeList A → X
(this is in Lean, but not, for example in Homotopy Type Theory).
Indexed inductive types #
This is a more subtle notion. We will return to this later. We have already seen an example of this: MyNat.le
is an indexed inductive type.
Trees #
We see various kinds of trees, giving various inductive types.
Equations
- instInhabitedBinTree = { default := BinTree.leaf default }
Equations
- BinTree.eg₂ = (BinTree.leaf 3).node (BinTree.leaf 4)
Instances For
Equations
- BinTree.eg₃ = ((BinTree.leaf 3).node (BinTree.leaf 4)).node (BinTree.leaf 5)
Instances For
Equations
- (BinTree.leaf a).toList = [a]
- (a.node a_1).toList = a.toList ++ a_1.toList
Instances For
Equations
- (BinTree.leaf a).sum = a
- (t₁.node t₂).sum = t₁.sum + t₂.sum
Instances For
Equations
- BinTree.sum' = BinTree.rec (fun (a : ℕ) => a) fun (_t₁ _t₂ : BinTree ℕ) (sum₁ sum₂ : ℕ) => sum₁ + sum₂
Instances For
Equations
- instInhabitedBinTree' = { default := BinTree'.leaf default }
Equations
- natListSum [] = 0
- natListSum (head :: tail) = head + natListSum tail
Instances For
Equations
- BoolTree.eg₂ = BoolTree.node fun (x : Bool) => BoolTree.leaf 3
Instances For
Equations
- BoolTree.eg₃ = BoolTree.node fun (b : Bool) => if b = true then BoolTree.leaf 3 else BoolTree.leaf 4
Instances For
Equations
- (BoolTree.leaf a).toList = [a]
- (BoolTree.node f).toList = (f true).toList ++ (f false).toList
Instances For
Equations
- (BoolTree.leaf a).toBinTree = BinTree.leaf a
- (BoolTree.node f).toBinTree = (f true).toBinTree.node (f false).toBinTree
Instances For
Equations
- BoolTree.ofBinTree (BinTree.leaf a) = BoolTree.leaf a
- BoolTree.ofBinTree (a.node a_1) = BoolTree.node fun (b : Bool) => if b = true then BoolTree.ofBinTree a else BoolTree.ofBinTree a_1
Instances For
Equations
- instInhabitedListTree = { default := ListTree.node default }
Equations
Instances For
Equations
Instances For
Equations
- (ListTree.leaf a).toList = [a]
- (ListTree.node []).toList = []
- (ListTree.node (t :: ts)).toList = t.toList ++ (ListTree.node ts).toList
Instances For
Lean is pragmatic and allows imperative programming. We can define the sum of a list. Technically, this is in a monad.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
- listSumNat' l = List.foldl (fun (sum : ℤ) (n : ℕ) => sum + ↑n) 0 l
Instances For
Equations
- listTillFlat n = (listTill n).flatMap listTill
Instances For
Equations
- FinTree.ofBinTree (BinTree.leaf a) = FinTree.leaf a
- FinTree.ofBinTree (a.node a_1) = FinTree.node fun (k : Fin 2) => match k with | ⟨0, _pf⟩ => FinTree.ofBinTree a | ⟨1, _pf⟩ => FinTree.ofBinTree a_1
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
The idea of Cantor's theorem is to show that we can define p: T → Bool
such that p (node p) ≠ p p
. If not for the positivity condition, we could define p (node x) = ¬ x (node x)
.
Equations
Instances For
Equations
- CantorTree.flip' = Eq.rec (motive := fun (x : Type) (h : CantorTree.T = x) => x → Bool) CantorTree.flip CantorTree.TisT'