Formal Software Verification

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.

MyNat.Nat.succ : MyNat.Nat MyNat.Nat#check MyNat.Nat.succ
MyNat.Nat.succ : MyNat.Nat  MyNat.Nat
inductive MyNat.Nat : Type number of parameters: 0 constructors: MyNat.Nat.zero : MyNat.Nat MyNat.Nat.succ : MyNat.Nat MyNat.Nat#print MyNat.Nat
inductive MyNat.Nat : Type
number of parameters: 0
constructors:
MyNat.Nat.zero : MyNat.Nat
MyNat.Nat.succ : MyNat.Nat  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.

MyNat.Nat.zero.succ.succ.succ : MyNat.Nat#check MyNat.Nat.succ (MyNat.Nat.succ (MyNat.Nat.succ MyNat.Nat.zero))
MyNat.Nat.zero.succ.succ.succ : MyNat.Nat

Example 2. An enumeration is an inductive type whose constructors carry no data.

inductive Answer : Type where | yes : Answer | no : Answer | maybe : Answer Answer.maybe : Answer#check Answer.maybe
Answer.maybe : Answer

Example 3. The expression (x + 3) * y is a value of AExp. The constructor applications mirror the shape of the expression.

((AExp.var "x").add (AExp.num 3)).mul (AExp.var "y") : AExp#check AExp.mul (AExp.add (AExp.var "x") (AExp.num 3)) (AExp.var "y")
((AExp.var "x").add (AExp.num 3)).mul (AExp.var "y") : AExp

Example 4. The list containing 3 and 7 is two applications of cons ending in nil.

MyList.List.cons 3 (MyList.List.cons 7 MyList.List.nil) : MyList.List #check MyList.List.cons 3 (MyList.List.cons 7 MyList.List.nil)
MyList.List.cons 3 (MyList.List.cons 7 MyList.List.nil) : MyList.List 

Example 5. A constructor can take several arguments. The type below packs two integers.

inductive Interval : Type where | mk : Interval Interval.mk 1 5 : Interval#check Interval.mk 1 5
Interval.mk 1 5 : Interval

Example 6. #print lists the constructors of a type.

inductive MyList.List : Type Type number of parameters: 1 constructors: MyList.List.nil : {α : Type} MyList.List α MyList.List.cons : {α : Type} α MyList.List α MyList.List α#print MyList.List
inductive MyList.List : Type  Type
number of parameters: 1
constructors:
MyList.List.nil : {α : Type}  MyList.List α
MyList.List.cons : {α : Type}  α  MyList.List α  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.

(AExp.var "x").div (AExp.num 0) : AExp#check AExp.div (AExp.var "x") (AExp.num 0)
(AExp.var "x").div (AExp.num 0) : AExp

Example 8. Lean's own numerals elaborate to the core Nat. The reconstruction and the original are distinct types.

3 : #check (3 : )
3 : 

Example 9. The empty list over ℤ requires a type annotation, since nil alone does not determine α.

MyList.List.nil : MyList.List #check (MyList.List.nil : MyList.List )
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 inductive Direction : Type number of parameters: 0 constructors: Direction.north : Direction Direction.south : Direction Direction.east : Direction Direction.west : Direction#print Direction
inductive Direction : Type
number of parameters: 0
constructors:
Direction.north : Direction
Direction.south : Direction
Direction.east : Direction
Direction.west : Direction