The answer is "no, Coq does not introduce an axiom", but this is not the whole story, because type theory does not operate by postulating axioms. Instead, Coq has some primitive building blocks from which the natural numbers, and other inductive types, can be built.
Let's see how it is done for induction on natural number. If you Print nat_ind.
you get:
nat_ind =
fun (P : nat -> Prop) (f : P 0) (h : forall n : nat, P n -> P (S n)) =>
fix F (n : nat) : P n :=
match n as k return (P k) with
| 0 => f
| S k => h k (F k)
end
: forall P : nat -> Prop,
P 0 -> (forall n : nat, P n -> P (S n)) -> forall n : nat, P n
The fix
construct is used for recursive definitions. Here is the same definition written without fix
:
Fixpoint my_nat_ind (P : nat -> Prop) (b : P 0)
(h : forall k, P k -> P (S k))
(n : nat) : P n :=
match n with
| 0 => b
| S k => h k (my_nat_ind P b h k)
end.
We see that b
is the base case, and h
is the induction step. Notice that we make a recursive call to my_nat_ind
in the induction step.
If we are allowed to make arbitrary recursive definitions, then we can prove False
very easily:
Definition nonsense : False := nonsense.
Of course, Coq disallows this. When you make a recursive definition, it verifies that all recursive calls will actually terminate. In the case of my_nat_ind
it can tell that the fourth argument n
has one fewer constructors S
applied in the recursive call, so it allows it. This is known as "guardedness condition".
In summary, Coq does not postulate any new axioms when you define nat
. Instead, it defines induction using guarded recursion.
Let me also explain why you want to be careful with the word "axiom" when you speak to type theorists. In type theory, an axiom is the same thing as a constant c
of a type A
. For example, one might postulate excluded middle as an axiom by introducing a new constant
$$\textstyle
\mathtt{lem} : \Pi_{p : \mathtt{Prop}}.\, p \lor \neg p
$$
This approach does not work well, because it messes up the nice computational properties of type theory. When $\mathtt{lem}$ appears in the middle of some term, the engine won't know how to compute with it.
Print nat_ind
shows you the definition. The principle is derived using guarded recursion. $\endgroup$Print Assumptions
. $\endgroup$