Jump to content

Lean theorem prover/Foundations/The three axioms: Difference between revisions

From The Invariance Itself
PMA Publisher (talk | contribs)
Published from the Principia Machina source
 
PMA Publisher (talk | contribs)
Published from the Principia Machina source
 
Line 1: Line 1:
{{DISPLAYTITLE:The three axioms}}
{{DISPLAYTITLE:The three axioms}}
{{Plebeian|Lean theorem prover/Explainers/What the axioms are}}
{{Plebeian|Lean theorem prover/Explainers/What the axioms are}}
{{Lean theorem prover map}}


Lean's type theory, with its dependent functions, universes, inductive types and quotients,
Lean's type theory, with its dependent functions, universes, inductive types and quotients,

Latest revision as of 19:34, 15 October 2026

Plain-language version: What the axioms are
Lean theorem prover: map
Reading the edition
Three levels of reading
Glossary
Notation
Chronology
Reading by level
Start here: What a proof assistant does
The type theory: Terms, types and judgments
How Lean works: Elaboration
The history: Automath
The applications: Research mathematics
Sources
Sources
Bibliography
Further reading
Related
The move to Lean

Lean's type theory, with its dependent functions, universes, inductive types and quotients, is extended in the core library by three axioms: propositional extensionality (propext), the soundness of quotients (Quot.sound) and global choice (Classical.choice). An axiom is a constant with a type and no definition; it does not reduce, and the compiler cannot generate code for it.[1] Lean records, for every definition and theorem, which axioms it depends on, and prints the list on request. This page states the three as Lean prints them, says what each makes possible, shows the dependency audit on examples, and sets out the further axioms that are not mathematics at all.

As Lean prints them

#print propext
#print Quot.sound
#print Classical.choice
axiom propext : ∀ {a b : Prop}, (a ↔ b) → a = b
axiom Quot.sound.{u} : ∀ {α : Sort u} {r : α → α → Prop} {a b : α}, r a b → Quot.mk r a = Quot.mk r b
axiom Classical.choice.{u} : {α : Sort u} → Nonempty α → α

In Lean 4.34.1 propext is stated in the file Init/Core.lean, and the other two in Init/Prelude.lean.[2] As rules, with a,b:Prop:

Γ⊢h:a↔bΓ⊢propexth:a=bΓ⊢p:rabΓ⊢Quot.soundp:Quot.mkra=Quot.mkrbΓ⊢h:NonemptyαΓ⊢Classical.choiceh:α

The first two conclude equations, which are propositions. The third concludes an element of an arbitrary type. That difference decides how each one interacts with computation.

What each makes possible

Propositional extensionality says that logically equivalent propositions are equal, so that one may be replaced by the other in any context. The reference manual notes that the ordinary connectives respect logical equivalence provably, without the axiom, but that it is needed for an unknown predicate P : Prop → Prop applied to equivalent arguments, and for equality between propositions itself.[3] It is valid intuitionistically.[3] Theorem Proving in Lean 4 adds that it agrees with set-theoretic readings in which every proposition is either empty or a one-element set.[4]

Quotient soundness identifies the classes of related elements in a quotient type. It is also the only axiom behind function extensionality, which Lean proves as a theorem from quotients; the proof is on propositional equality. With propext it gives an extensional theory of sets represented as predicates: two predicates true of the same elements are equal.[4]

Global choice turns a proof that a type is inhabited into an element of it. Nonempty α is a proposition, and a proof of it carries no information about which element exists. Classical.choice nevertheless returns one, and returns the same one for any proof, since all proofs of a proposition are equal. Theorem Proving in Lean 4 derives from it the principle of indefinite description, and, with the other two axioms, excluded middle, the decidability of every proposition and Hilbert's epsilon operator.[4] That derivation is classical logic from choice.

The first two can block evaluation in Lean's kernel, because a cast along an equation proved by an axiom does not reduce, but they are compatible with compiled code, which erases proofs. Choice is not: it manufactures data from a proposition, and definitions that use it for data must be marked noncomputable.[4]

The audit: #print axioms

#print axioms lists every axiom a constant depends on, directly or through the definitions and theorems it uses.[1] Five small theorems show the range from none to all three:

theorem two_add_two : 2 + 2 = 4 := rfl

theorem and_swap (p q : Prop) : p ∧ q ↔ q ∧ p :=
  ⟨fun ⟨hp, hq⟩ => ⟨hq, hp⟩, fun ⟨hq, hp⟩ => ⟨hp, hq⟩⟩

theorem and_swap_eq (p q : Prop) : (p ∧ q) = (q ∧ p) :=
  propext (and_swap p q)

theorem add_zero_fun : (fun n : Nat => n + 0) = (fun n => n) :=
  funext fun _ => rfl

theorem em' (p : Prop) : p ∨ ¬p := Classical.em p

#print axioms two_add_two
#print axioms and_swap
#print axioms and_swap_eq
#print axioms add_zero_fun
#print axioms em'
'two_add_two' does not depend on any axioms
'and_swap' does not depend on any axioms
'and_swap_eq' depends on axioms: [propext]
'add_zero_fun' depends on axioms: [Quot.sound]
'em'' depends on axioms: [propext, Classical.choice, Quot.sound]

Here the computation checked by rfl and the logical equivalence need nothing, the equation between propositions needs propext, and the equation between functions needs Quot.sound, through funext. Excluded middle needs all three, because the proof of Classical.em in the core library uses choice, propext and funext.[2]

sorry and sorryAx

The term sorry closes any goal. It elaborates to the axiom sorryAx, which inhabits every type, and so it is used for unfinished work and never belongs in a finished proof.[1]

#print sorryAx

theorem unfinished : 1 = 2 := sorry

theorem uses_unfinished : 2 = 3 := congrArg (· + 1) unfinished

#print axioms uses_unfinished
axiom sorryAx.{u} : (α : Sort u) → Bool → α
'uses_unfinished' depends on axioms: [sorryAx]

Lean warns once, with declaration uses `sorry`, at unfinished, where sorry is written. The theorem uses_unfinished raises no warning of its own, yet it proves a falsehood, and only the axiom list shows why. The reference manual makes the same point about the editor's check marks: they appear even when a dependency uses sorry, and printing the axioms is what detects it.[5]

Axioms that are not mathematics

Any user can write an axiom, and Lean accepts it. Lean cannot check that a new axiom is consistent with the others.[1]

axiom everything_is_equal : ∀ (a b : Nat), a = b

theorem one_eq_two : 1 = 2 := everything_is_equal 1 2

#print axioms one_eq_two

The last line prints 'one_eq_two' depends on axioms: [everything_is_equal]. The theorem is checked and accepted; the audit is what exposes its premise.

An axiom can also be harmless on its own and inconsistent with the standard three. The reference manual's example is a "free theorem" of parametricity, which says that a function polymorphic in the element type of a list commutes with mapping over the list. With excluded middle every proposition is decidable, so a function can test whether its type argument is Nat and behave differently when it is. That function is not parametric, and together with the free theorem it proves False.[1]

The core library itself states three further axioms, Lean.trustCompiler, Lean.ofReduceBool and Lean.ofReduceNat. The reference manual describes them as mathematically trivial: they mark proofs that depend on the correctness of the whole compiler rather than only on Lean's small kernel.[1] The tactic native_decide, which settles a decidable statement by running compiled code, creates a dedicated axiom for each use, stating exactly the fact the compiled code asserted:[1]

theorem big : 123456 * 654321 = 80779853376 := by native_decide

#print axioms big

Lean 4.34.1 prints 'big' depends on axioms: [big._native.native_decide.ax_1_1]. Such a theorem rests on the correctness of the whole compiler, not only on Lean's kernel and the three axioms: each use of the tactic widens what has to be trusted.[5]

Why audit per theorem

The three standard axioms are, in the reference manual's words, "known to be consistent".[1] Carneiro's model of Lean's type theory in set theory, published in 2019, covers all three axioms together;[6] it is described, with its limits, in consistency and the metatheory. Every other axiom is a premise the reader has to accept separately. The manual's guide to validating a proof therefore asks that #print axioms report only propext, Classical.choice and Quot.sound: a sorryAx means an incomplete proof, Lean.trustCompiler means trust in native evaluation, and anything else means a custom axiom on which the result is conditional.[5]

A list of axioms also says what kind of result a theorem is. A theorem whose list omits Classical.choice uses no classical reasoning obtained from it, and one with an empty list holds in the type theory alone. The check can be made permanent. The manual suggests pairing #print axioms with #guard_msgs, so that a change in a library one depends on cannot silently add an axiom:[1]

/-- info: 'two_add_two' does not depend on any axioms -/
#guard_msgs in
#print axioms two_add_two

If the proof of two_add_two ever came to depend on an axiom, the message would change, and this command would fail.

Next

Classical logic from choice follows the third axiom into excluded middle.

References

  1. ↑ 1.0 1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 The Lean Language Reference, version 4.34.0, chapter 8 "Axioms": the introduction, §8.2 "Consistency", §8.3 "Reduction", §8.4 "Standard Axioms" and §8.5 "Displaying Axiom Dependencies". https://lean-lang.org/doc/reference/4.34.0/Axioms/
  2. ↑ 2.0 2.1 Lean 4 source, version 4.34.1: files src/Init/Core.lean (propext), src/Init/Prelude.lean (Quot.sound, Classical.choice, sorryAx) and src/Init/Classical.lean (the proof of Classical.em). Apache License 2.0. https://github.com/leanprover/lean4/tree/v4.34.1/src/Init
  3. ↑ 3.0 3.1 The Lean Language Reference, version 4.34.0, §4.2 "Propositions" (the axiom propext and its documentation). https://lean-lang.org/doc/reference/4.34.0/The-Type-System/Propositions/
  4. ↑ 4.0 4.1 4.2 4.3 Jeremy Avigad, Leonardo de Moura, Soonho Kong and Sebastian Ullrich, Theorem Proving in Lean 4, chapter 12 "Axioms and Computation". https://lean-lang.org/theorem_proving_in_lean4/Axioms-and-Computation/
  5. ↑ 5.0 5.1 5.2 The Lean Language Reference, version 4.34.0, "Validating a Lean Proof", sections "The Blue Double Check Marks", "Printing Axioms" and "On Lean.trustCompiler (up to Lean 4.28.0)". https://lean-lang.org/doc/reference/4.34.0/ValidatingProofs/
  6. ↑ Mario Carneiro, The Type Theory of Lean, Master's thesis, Carnegie Mellon University, 2019; abstract, §2.7 (pp. 12–13) and Corollary 6.8 (p. 41). https://github.com/digama0/lean-type-theory/releases/tag/v1.0