6.1. Inductive Types and Their Principles
An inductive type is defined by listing its constructors. Every value of the type is built by applying those constructors, and each value is built in just one way. Lecture 3 used this to build ℕ from Nat.zero and Nat.succ and List from List.nil and List.cons. For a type of data such as ℕ, Lean generates from the constructors four principles, and naming them explains where the tools of the earlier lectures come from.
The recursor T.rec is the primitive principle of the type. It is the raw form of structural recursion, and read on a proposition-valued motive it is the raw form of structural induction. Its type for ℕ shows the two cases a function on ℕ must supply, one for Nat.zero and one for Nat.succ, and the second case receives the value at the predecessor, which is the recursive result.
#check @Nat.rec
#check @Nat.succ.injEq
The casesOn principle is the non-recursive special case of the recursor, the one that the cases tactic of Lecture 1 elaborates into. Pattern matching and the equation compiler turn the surface syntax of Lecture 3 into applications of the recursor. The definition below computes with Nat.rec directly, and the same function by pattern matching is the one Lecture 3 would have written; the two are equal.
namespace Func
def usingRec (n : ℕ) : ℕ :=
Nat.rec (motive := fun _ => ℕ) 0 (fun _ ih => ih + 2) n
example : usingRec 3 = 6 := rfl
end Func
The remaining two principles concern the constructors themselves. Each constructor is injective, so equal constructor applications have equal arguments, and Lean generates the equation Nat.succ.injEq recording this. Distinct constructors are disjoint, so no application of Nat.succ equals Nat.zero. Injectivity and disjointness hold for a type of data like ℕ; for a type of proofs, where all proofs of one proposition are equal, they do not. The second output above is the injectivity equation, and the two examples below use injectivity and disjointness.
namespace Func
example (m n : ℕ) (h : Nat.succ m = Nat.succ n) :
m = n := m:ℕn:ℕh:m.succ = n.succ⊢ m = n
All goals completed! 🐙
example (n : ℕ) : Nat.succ n ≠ 0 :=
Nat.succ_ne_zero n
end Func
The induction tactic of Lecture 4 is the recursor read on a proposition, and Lecture 7 derives it in general and proves the laws that this lecture states. Here the recursor is only named, as the source of the recursion and case analysis already in use.
Margin notes. The Guide, chapter 5. Avigad, de Moura, Kong, Ullrich, Theorem Proving in Lean 4, the chapter on inductive types. The Lean language reference on the inductive command.