3.2. Inductive Types
An inductive command defines a new type by listing its constructors. The type contains exactly the values built by finitely many constructor applications, and nothing else. The definition below reconstructs the natural numbers inside a namespace, since the name Nat already belongs to Lean.
namespace MyNat
inductive Nat : Type where
| zero : Nat
| succ : Nat → Nat
end MyNat
The commands #check and #print inspect the result. The constructor succ takes a Nat and builds the next one.
#check MyNat.Nat.succ
#print MyNat.Nat
Constructors can carry data of other types. The type below represents arithmetic expressions with integer constants, variables named by strings, and four operators. It is the abstract syntax of a small language, and the imperative language of the final lectures extends it.
inductive AExp : Type where
| num : ℤ → AExp
| var : String → AExp
| add : AExp → AExp → AExp
| sub : AExp → AExp → AExp
| mul : AExp → AExp → AExp
| div : AExp → AExp → AExp
Finally, lists. A list over α is either empty or an element followed by a list. As with Nat, Lean already provides List, so the reconstruction lives in a namespace.
namespace MyList
inductive List (α : Type) : Type where
| nil : List α
| cons : α → List α → List α
end MyList
3.2.1. Examples
The examples below build values of the inductive types of this section and inspect them with #check and #print.
Example 1. The numeral three is three applications of succ to zero.
#check MyNat.Nat.succ
(MyNat.Nat.succ (MyNat.Nat.succ MyNat.Nat.zero))
Example 2. An enumeration is an inductive type whose constructors carry no data.
inductive Answer : Type where
| yes : Answer
| no : Answer
| maybe : Answer
#check Answer.maybe
Example 3. The expression (x + 3) * y is a value of AExp. The constructor applications mirror the shape of the expression.
#check AExp.mul
(AExp.add (AExp.var "x") (AExp.num 3))
(AExp.var "y")
Example 4. The list containing 3 and 7 is two applications of cons ending in nil.
#check MyList.List.cons 3
(MyList.List.cons 7 MyList.List.nil)
Example 5. A constructor can take several arguments. The type below packs two integers.
inductive Interval : Type where
| mk : ℤ → ℤ → Interval
#check Interval.mk 1 5
Example 6. #print lists the constructors of a type.
#print MyList.List
Example 7. Constructor applications nest to any depth. The value below is the expression x / 0, a legal piece of syntax whose evaluation the next sections discuss.
#check AExp.div (AExp.var "x") (AExp.num 0)
Example 8. Lean's own numerals elaborate to the core Nat. The reconstruction and the original are distinct types.
#check (3 : ℕ)
Example 9. The empty list over ℤ requires a type annotation, since nil alone does not determine α.
#check (MyList.List.nil : MyList.List ℤ)
Example 10. The four cardinal directions as an enumeration, printed.
inductive Direction : Type where
| north : Direction
| south : Direction
| east : Direction
| west : Direction
#print Direction