(A supplement to @It'sNotALie's answer.) My understanding is that when you do:
inductive mynat : Type
| zero : mynat
| succ : mynat → mynat
then Lean is adding four new "things" to the context:
inductive mynat : Type
constructor mynat.zero : mynat
constructor mynat.succ : mynat → mynat
protected eliminator mynat.rec : Π {motive : mynat → Sort l},
motive mynat.zero → (Π (ᾰ : mynat), motive ᾰ → motive ᾰ.succ) → Π (n : mynat), motive n
These "things" could be thought of as axioms, but unlike typical axioms there is no danger of these being inconsistent with whatever axioms and theorems are already in the environment (assuming Lean's theory and implementation are consistent, and the axioms in the context are as well). So it is more normal to think of them more like automatic definitions and theorems that Lean adds for you.
The inductive type mynat
and the two constructors mynat.zero
and mynat.succ
are clear and just come from the inductive defintion. The elimination principle mynat.rec
is the workhorse of inductive definitions. It is what is used to do anything we want with mynat
including:
- Prove the basic structural facts about
zero
and succ
, including the first three Peano axioms.
- Define any recursive functions on
mynat
, including the usual +
and *
along with their four definitional (Peano axiom) equalities.
- Prove the induction principle.
The elimination principle rec
is discussed in Theorem Proving in Lean, 7. Inductive Types. And if you want more detail, the first chapter of The HoTT Book is a great introduction to dependent type theory.
But also note, you will almost never need to use the elimination principle rec
directly. First, Lean automatically defines a number of definitions and theorems based on rec
. (Unlike rec
these are not "axioms". They have proofs/definitions.) For mynat
, here are a list of all the automatically generated theorems and definitions that Lean creates for mynat
.
#print mynat.below
#print mynat.binduction_on
#print mynat.brec_on
#print mynat.cases_on
#print mynat.has_sizeof_inst
#print mynat.ibelow
#print mynat.no_confusion
#print mynat.no_confusion_type
#print mynat.rec_on
#print mynat.sizeof
#print mynat.succ.inj
#print mynat.succ.inj_arrow
#print mynat.succ.inj_eq
#print mynat.succ.sizeof_spec
#print mynat.zero.inj
#print mynat.zero.inj_arrow
#print mynat.zero.inj_eq
#print mynat.zero.sizeof_spec
For example, mynat.succ.inj
is the usual Peano axiom saying that successor is injective:
def mynat.succ.inj : ∀ {ᾰ ᾰ_1 : mynat}, ᾰ.succ = ᾰ_1.succ → ᾰ = ᾰ_1 :=
λ {ᾰ ᾰ_1 : mynat} (a : ᾰ.succ = ᾰ_1.succ), mynat.no_confusion a (λ (ᾰ_eq : ᾰ = ᾰ_1), ᾰ_eq)
Second, the tools in Lean for working with inductive definitions such as the induction
and cases
tactics, as well as match
statements all use (or de-sugar in the case of match
) to using these built-in theorems and definitions.
And as @It'sNotALie implied, you can see this by printing out any proof to see what it becomes underneath (and use set option pp.all true
to remove any syntactic sugar if needed).