3.6. Theorem Statements
A theorem is a definition whose type is a proposition. Stating it requires no proof; the placeholder sorry stands where the proof will go, and Lean flags every use of it. The statements below specify the functions of this lecture, and the namespace keeps their names from clashing with Mathlib's.
namespace SorryTheorems
theorem add_comm (m n : ℕ) :
add m n = add n m := m:ℕn:ℕ⊢ add m n = add n m
All goals completed! 🐙
theorem add_assoc (l m n : ℕ) :
add (add l m) n = add l (add m n) := l:ℕm:ℕn:ℕ⊢ add (add l m) n = add l (add m n)
All goals completed! 🐙
theorem mul_comm (m n : ℕ) :
mul m n = mul n m := m:ℕn:ℕ⊢ mul m n = mul n m
All goals completed! 🐙
theorem mul_assoc (l m n : ℕ) :
mul (mul l m) n = mul l (mul m n) := l:ℕm:ℕn:ℕ⊢ mul (mul l m) n = mul l (mul m n)
All goals completed! 🐙
theorem mul_add (l m n : ℕ) :
mul l (add m n) = add (mul l m) (mul l n) := l:ℕm:ℕn:ℕ⊢ mul l (add m n) = add (mul l m) (mul l n)
All goals completed! 🐙
theorem reverse_reverse {α : Type} (xs : List α) :
reverse (reverse xs) = xs := α:Typexs:List α⊢ reverse (reverse xs) = xs
All goals completed! 🐙
end SorryTheorems
Computation cannot prove them. rfl settles add 2 7 = add 7 2, since both sides compute to 9, but in add m n = add n m the variables block computation, and the general law needs structural induction, the subject of the coming lectures.
Axioms are the other way to assert without proving, and they deserve more suspicion. An opaque constant has a type and no definition, and an axiom asserts a proposition with no proof at all. Nothing checks it, so an inconsistent axiom silently breaks the whole development. The course states axioms only to discuss them.
opaque a : ℤ
opaque b : ℤ
axiom a_less_b : a < b
3.6.1. Examples
The examples below read the statements back, separate what computation settles from what it does not, and track which axioms a proof rests on. The namespace MoreTheorems keeps the new names clear of Mathlib.
Example 1. A statement with named binders is a universally quantified proposition.
#check @SorryTheorems.add_comm
Example 2. An implicit binder appears in braces, and the statement quantifies over the type as well.
#check @SorryTheorems.reverse_reverse
Example 3. The command #print axioms reports what a proof rests on, and sorry leaves the trace sorryAx.
#print axioms SorryTheorems.add_comm
Example 4. A law that computation settles needs no induction. Zero on the right matches the first equation of add, so rfl proves it for every n.
namespace MoreTheorems
theorem add_zero_right (n : ℕ) : add n 0 = n := rfl
end MoreTheorems
#print axioms MoreTheorems.add_zero_right
Example 5. The same holds for the first equation of eval, whatever the environment.
namespace MoreTheorems
theorem eval_num (env : String → ℤ) (i : ℤ) :
eval env (AExp.num i) = i := rfl
end MoreTheorems
#check @MoreTheorems.eval_num
Example 6. A ground equation deserves a name as much as a general law does.
namespace MoreTheorems
theorem fib_seven : fib 7 = 13 := rfl
theorem reverse_nil : reverse ([] : List ℕ) = [] := rfl
end MoreTheorems
Example 7. Binders to the left of the colon and an explicit ∀ state the same proposition.
namespace MoreTheorems
theorem all_add_zero : ∀ n : ℕ, add n 0 = n :=
fun _ => rfl
end MoreTheorems
#check @MoreTheorems.all_add_zero
Example 8. Applying a stated theorem to arguments instantiates the statement, whether or not a proof exists yet.
#check SorryTheorems.add_comm 2 3
Example 9. Whatever a proof uses, #print axioms shows. The proof below rests on the axiom of this section, and on propext, which Mathlib's lemma uses.
namespace MoreTheorems
theorem a_ne_b : a ≠ b := ne_of_lt a_less_b
end MoreTheorems
#print axioms MoreTheorems.a_ne_b
Example 10. Variables block computation, so the law below waits for structural induction and carries sorryAx in the meantime.
namespace MoreTheorems
theorem half_double (n : ℕ) : half (add n n) = n := n:ℕ⊢ half (add n n) = n
All goals completed! 🐙
end MoreTheorems
#print axioms MoreTheorems.half_double