Skip to content

Commit b00d397

Browse files
authored
feat: examples of printing axioms (#601)
This PR rearranges the discussion of axioms, primarily in order to add several more examples of the use of `#print axioms <ident>`. Also links the #print axioms spec back to the docs on axioms. Follow-up from discussion with @jcreedcmu.
1 parent 4487ff5 commit b00d397

File tree

2 files changed

+117
-25
lines changed

2 files changed

+117
-25
lines changed

Manual/Axioms.lean

Lines changed: 116 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -176,41 +176,33 @@ Because they occur only in a proof, the compiler has no problem generating code:
176176
```
177177
:::
178178

179-
# Displaying Axiom Dependencies
180-
%%%
181-
tag := "print-axioms"
182-
%%%
183-
184-
The command {keywordOf Lean.Parser.Command.printAxioms}`#print axioms` displays all the axioms that a declaration transitively relies on.
185-
In other words, if a proof uses another proof, which itself uses an axiom, then the axiom is reported by {keywordOf Lean.Parser.Command.printAxioms}`#print axioms` for both.
186-
This can be used to audit the assumptions made by a proof.
187-
Together with {keywordOf Lean.guardMsgsCmd}`#guard_msgs`, it can also ensure that updates to libraries from other projects don't silently introduce unwanted dependencies on axioms.
188-
189179
# Standard Axioms
190180
%%%
191181
tag := "standard-axioms"
192182
%%%
193183

194-
Lean includes the following mathematical axioms:
184+
There are seven standard axioms in Lean. The first three axioms are important parts of how mathematics is done in Lean:
195185
* ```signature
196-
propext {a b : Prop} : (a ↔ b) → a = b
186+
Classical.choice.{u} {α : Sort u} : Nonempty α → α
197187
```
198188
* ```signature
199-
Classical.choice.{u} {α : Sort u} : Nonempty α → α
189+
propext {a b : Prop} : (a ↔ b) → a = b
200190
```
201191
* ```signature
202192
Quot.sound.{u} {α : Sort u}
203193
{r : α → α → Prop} {a b : α} :
204194
r a b → Quot.mk r a = Quot.mk r b
205195
```
206196

207-
Three additional axioms allow the Lean kernel to invoke code generated by the compiler, rather than using its internal reduction engine.
208-
This can greatly improve performance of implementations of proof by reflection.
209-
Rather than using these axioms directly, they are usually invoked via the {tactic}`native_decide` tactic.
210-
Both {name}`Lean.reduceBool` and {name}`Lean.reduceNat` contain references to {name}`Lean.trustCompiler`, which ensures that the fact that a proof trusts the correctness of the compiler is tracked.
197+
All three of these axioms are discussed in the book [Theorem Proving in Lean](https://lean-lang.org/theorem_proving_in_lean4/find/?domain=Verso.Genre.Manual.section&name=axioms-and-computation).
198+
199+
The axiom {name}`sorryAx` is used as part of the implementation of the {tactic}`sorry` tactic and {lean}`sorry` term.
200+
Uses of this axiom are not intended to occur in finished proofs, as it can be used to prove anything:
201+
* ```signature
202+
sorryAx {α : Sort u} (synthetic := true) : α
203+
```
211204

212-
These axioms do not truly exist for their _mathematical_ content; after all, {name}`Lean.reduceBool` and {name}`Lean.reduceNat` are essentially the identity function.
213-
However, they allow the use of compiled code in proofs to be carefully controlled, and tracking them as axioms allows {keywordOf Lean.Parser.Command.printAxioms}`#print axioms` to be used to audit theorems.
205+
Three final axioms do not truly exist for their _mathematical_ content; from a mathematical perspective they prove trivial statements:
214206

215207
* ```signature
216208
Lean.trustCompiler : True
@@ -223,10 +215,110 @@ However, they allow the use of compiled code in proofs to be carefully controlle
223215
Lean.ofReduceNat (a b : Nat) : Lean.reduceNat a = b → a = b
224216
```
225217

226-
:::keepEnv
227-
```lean -show
228-
axiom Anything : Type
218+
These axioms instead track proofs that depend on the correctness of the entire compiler, and not just on the much smaller {tech}`kernel`.
219+
220+
:::example "Creating and Tracking Proofs That Trust the Compiler"
221+
The functions {name}`Lean.reduceBool` and {name}`Lean.reduceNat` can be invoked to have the compiler perform a calculation; this can greatly improve performance of implementations of proof by reflection.
222+
223+
```lean
224+
def largeNumber : Nat := Lean.reduceNat (230_000 + 4_500 + 1_000_067)
225+
```
226+
227+
The resulting term depends on the axiom {name}`Lean.trustCompiler` in order to track the fact that this calculation depends on the correctness of the compiler.
228+
229+
```lean (name := printAxExC1)
230+
#print axioms largeNumber
231+
```
232+
```leanOutput printAxExC1
233+
'largeNumber' depends on axioms: [Lean.trustCompiler]
234+
```
235+
236+
The most common way that proofs end up trusting the compiler is through the {tactic}`native_decide` tactic:
237+
238+
```lean (name := printAxExC2)
239+
def bigSum : (List.range 1_001).sum = 500_500 := by native_decide
240+
#print axioms bigSum
241+
```
242+
```leanOutput printAxExC2
243+
'bigSum' depends on axioms: [Lean.ofReduceBool, Lean.trustCompiler]
244+
```
245+
:::
246+
247+
# Displaying Axiom Dependencies
248+
%%%
249+
tag := "print-axioms"
250+
%%%
251+
252+
The command {keywordOf Lean.Parser.Command.printAxioms}`#print axioms`, followed by a defined identifier, displays all the axioms that a definition transitively relies on.
253+
In other words, if a proof uses another proof, which itself uses an axiom, then the axiom is reported by {keywordOf Lean.Parser.Command.printAxioms}`#print axioms` for both.
254+
255+
::::keepEnv
256+
257+
This can be used to audit the assumptions made by a proof, for instance detecting that a proof transitively depends on the {tactic}`sorry` tactic.
258+
259+
```lean
260+
def lazy : 4 == 2 + 1 + 1 := by sorry
261+
```
262+
```lean (name := printAxEx4)
263+
#print axioms lazy
264+
```
265+
```leanOutput printAxEx4
266+
'lazy' depends on axioms: [sorryAx]
267+
```
268+
269+
:::example "Printing Axioms of Simple Definitions" (keep := true)
270+
271+
Consider the following three constants:
272+
273+
```lean
274+
def addThree (n : Nat) : Nat := 1 + n + 2
275+
theorem excludedMiddle (P : Prop) : P ∨ ¬ P := Classical.em P
276+
theorem simpleEquality (P : Prop) : (P ∨ False) = P := or_false P
277+
```
278+
279+
Regular functions like {lean}`addThree` that we might want to actually evaluation typically do not depend on any axioms:
280+
281+
```lean (name := printAxEx2)
282+
#print axioms addThree
283+
```
284+
```leanOutput printAxEx2
285+
'addThree' does not depend on any axioms
286+
```
287+
288+
The excluded middle theorem is only true if we use classical reasoning, so the foundation for classical reasoning shows up alongside other axioms:
289+
290+
```lean (name := printAxEx1)
291+
#print axioms excludedMiddle
292+
```
293+
```leanOutput printAxEx1
294+
'excludedMiddle' depends on axioms: [propext, Classical.choice, Quot.sound]
295+
```
296+
297+
Finally, the idea that two equivalent propositions are equal directly relies on {tech}[propositional extensionality].
298+
299+
```lean (name := printAxEx3)
300+
#print axioms simpleEquality
301+
```
302+
```leanOutput printAxEx3
303+
'simpleEquality' depends on axioms: [propext]
229304
```
230-
Finally, the axiom {name}`sorryAx` is used as part of the implementation of the {tactic}`sorry` tactic and {lean (type := "Anything")}`sorry` term.
231-
Uses of this axiom are not intended to occur in finished proofs, and this can be confirmed using {keywordOf Lean.Parser.Command.printAxioms}`#print axioms`.
232305
:::
306+
307+
:::example "Using {keywordOf Lean.Parser.Command.printAxioms}`#print axioms` with {keywordOf Lean.guardMsgsCmd}`#guard_msgs`"
308+
309+
You can use {keywordOf Lean.Parser.Command.printAxioms}`#print axioms` together with {keywordOf Lean.guardMsgsCmd}`#guard_msgs` to ensure that updates to libraries from other projects cannot silently introduce unwanted dependencies on axioms.
310+
311+
Perhaps you are worried that some future update to {lean}`or_false` in the previous example's {lean}`simpleEquality` proof might quietly introduce a new axiom dependency.
312+
You can guard against this by writing a command that will fail if {lean}`simpleEquality` uses any axioms besides {lean}`propext`:
313+
314+
```lean
315+
/--
316+
info: 'simpleEquality' depends on axioms: [propext]
317+
-/
318+
#guard_msgs in
319+
#print axioms simpleEquality
320+
```
321+
:::
322+
323+
324+
::::

Manual/Interaction.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,7 @@ Adds the string literal to Lean's {tech}[message log].
307307
#print axioms $t
308308
```
309309

310-
Lists all axioms that the constant transitively relies on.
310+
Lists all axioms that the constant transitively relies on. See {ref "print-axioms"}[the documentation for axioms] for more information.
311311
:::
312312

313313
:::example "Printing Axioms"

0 commit comments

Comments
 (0)