Built with doc-gen4, running Lean4. Bubbles () indicate interactive fragments: hover for details, tap to reveal contents. Use Ctrl+↑Ctrl+↓to navigate, Ctrl+🖱️to focus. On Mac, use Cmdinstead of Ctrl.
import Mathlib
/-!
# Examples of Proofs

We see our first proofs, most of which involve the `≤` relation on natural numbers. 

We will see that the natural numbers are "defined" in terms of the `zero` and `succ` constructors.

* `Nat.zero : ℕ` 
* `Nat.succ : ℕ → ℕ`

Analogous to this, (modulo renaming) the `≤` relation is defined in terms of the `le_refl` and `le_step` constructors.

* `Nat.le : ℕ → ℕ → Prop`
* `Nat.le_refl : ∀ n : ℕ, n ≤ n`
* `Nat.le_step : ∀ {n m : ℕ}, n ≤ m → n ≤ Nat.succ m`

However, we will first focus on a simpler relation.
-/


Nat.zero : ℕ
Nat.zero:
Nat.zero
Nat.succ (n : ℕ) : ℕ
Nat.succ:
Nat.succ
Nat.le (n a✝ : ℕ) : Prop
Nat.le: Prop
Nat.le
Nat.le_step {n m : ℕ} (h : n ≤ m) : n ≤ Nat.succ m
Nat.le_step: ∀ {n m : }, n mn Nat.succ m
Nat.le_step
Nat.le_refl (n : ℕ) : n ≤ n
Nat.le_refl: ∀ (n : ), n n
Nat.le_refl
/-! ### Example: a proof by reflexivity of equality Our first example is simpler: just a proof of equality. Note that a proof of a theorem in lean is very similar, both conceptually and syntactically, to a definition. In a definition, we give a name, a type and a value (though sometimes the type is inferred so can be omitted). In a theorem, we give a name, a statement and a proof. The statement is essentially a type, and the proof is a value of that type. Technically a statement is a proposition which is a special sort of type as we see below, but in these examples it is best to think of it as just a type. -/ /-- The theorem that `1 + 1 = 2` -/ theorem
one_plus_one_is_two: 1 + 1 = 2
one_plus_one_is_two
:
1: ?m.7
1
+
1: ?m.18
1
=
2: ?m.39
2
:=
rfl: ∀ {α : Sort ?u.264} {a : α}, a = a
rfl
/-! We look more closely at the right hand side, i.e., the _proof_. Below is the description in Lean of `rfl`, which corresponds to _reflexivity of equality_, i.e., the fact that any term is equal to itself: > `rfl : a = a` is the unique constructor of the equality type. This is the same as `Eq.refl` except that it takes `a` implicitly instead of explicitly. > This is a more powerful theorem than it may appear at first, because although the statement of the theorem is `a = a`, lean will allow anything that is definitionally equal to that type. So, for instance, `2 + 2 = 4` is proven in lean by `rfl`, because both sides are the same up to definitional equality. To clarify what is meant by _implicit_ and _explicit_ parameters, we look at the types of `rfl` and `Eq.refl`. Both these represent the statement that if `α` is a type and `a : α` is a term of type `α` then `a = a`. ```lean #check rfl -- rfl.{u} {α : Sort u} {a : α} : a = a #check Eq.refl -- Eq.refl.{u_1} {α : Sort u_1} (a : α) : a = a ``` Notice that in `rfl` _both_ the arguments `α` and `a` are in braces while in `Eq.refl` the argument `α` is in braces while `a` in in parenthesis. When calling a function, the arguments in parenthesis are to be specified, while those in braces are to be _inferred_ (if possible). If we prepend `@` to a function name then all arguments become explicit. Conversely we can ask Lean to infer arguments by using `_`. The following examples of similar proofs should clarify these. ```lean /- argument `a` given explicitly -/ example : 2 = 2 := Eq.refl 2 /- notation `@` used and both `α` and `a` are given explicitly-/ example : 3 = 3 := @Eq.refl ℕ 3 /- the argument `a` is inferred-/ example : 1 + 2 = 3 := Eq.refl _ /- notation `@` used but `α` is inferred-/ example : 3 = 3 := @Eq.refl _ 3 ``` ### Incorrect proofs Of course the right hand side may not be a proof of the statement in the left hand side. As mentioned above, this is equivalent to the term on the right-hand side having the _type_ specified in the left hand side. For example, consdier the following (incorrect) proof. ```lean theorem wrong : 1 + 2 = 2 := rfl ``` We get the following error message: ```lean type mismatch rfl has type 1 + 2 = 1 + 2 : Prop but is expected to have type 1 + 2 = 2 : Prop ``` This is because Lean inferred that `a` is `1 + 2` (and `α` is `ℕ`) and deduced that the type of the right hand side is `1 + 2 = 1 + 2`. This is not equal to the type specified in the left hand side, `1 + 2 = 2`. We get a different type of error if the statement we are trying to prove is not an equality. For example, consider the following (incorrect) proof. ```lean example : 1 ≤ 2 := rfl ``` Here Lean is not able to infer `a` (or even `α`) and so we get the following error message: ```lean type mismatch rfl has type ?m.690 = ?m.690 : Prop but is expected to have type 1 ≤ 2 : Prop ``` All that Lean knows about `rfl` is that it is a proof that `a = a`, but the statement is not an equality. So Lean assign a _metavariable_ `?m.690` to `a` and cannot _solve_ for the metavariable, giving an error as above. -/
rfl.{u} {α : Sort u} {a : α} : a = a
rfl: ∀ {α : Sort u} {a : α}, a = a
rfl
-- rfl.{u} {α : Sort u} {a : α} : a = a
Eq.refl.{u_1} {α : Sort u_1} (a : α) : a = a
Eq.refl: ∀ {α : Sort u_1} (a : α), a = a
Eq.refl
-- Eq.refl.{u_1} {α : Sort u_1} (a : α) : a = a -- example : 2 = 2 := 2 = 2 -- theorem wrong : 1 + 2 = 2 := rfl
example: 1 + 2 = 3
example
:
1: ?m.276
1
+
2: ?m.287
2
=
3: ?m.306
3
:=
Eq.refl: ∀ {α : Sort ?u.524} (a : α), a = a
Eq.refl
_: ?m.525
_
-- example : 1 ≤ 2 := rfl -- def not_a_nat : ℕ := "you cannot fool me" /-! ### Proofs versus Definitions; Sorts and Types To clarify the similarities and differences between a definition and a theorem, as well as sorts and types, we look at the following example. -/ /-- Definition of `two` for comparison -/ def
two:
two
:
: Type
:=
2: ?m.533
2
-- def two' : ℕ := ℕ /-! As we have remarked, this is formally very similar to the proof of a theorem. To see the differences, we see some associated types: ```lean #check 1 = 1 -- 1 = 1 : Prop #check ℕ -- ℕ : Type /- The universe of propositions. Prop ≡ Sort 0-/ #check Prop -- Prop : Type /- A type universe. Type ≡ Type 0, Type u ≡ Sort (u + 1)-/ #check Type -- Type : Type 1 ``` The main difference between the two cases is that the type of a theorem is a _proposition_, which is a special _type_ (i.e., a type in `Prop`). The type of `Prop` is `Type`, which is a type in the next universe up and is the type of `ℕ`. The universes form so called _Sorts_, with all but the first being _Types_. In other closely related foundational systems (such as _Homotopy Type Theory_), this distinction is not present and all uninverses are _Types_. In Lean _propositions_, i.e., elements of `Prop` (such as `1 = 1`) have a special property that two terms (i.e., proofs) of a proposition are equal by definition. Propositions are taken to be at "Types at level -1", i.e., "Sorts at level 0". This makes it convenient to exclude propositions in some cases where it is necessary to do so (as we will see later). -/
example: 2 = 2
example
:
2: ?m.552
2
=
2: ?m.566
2
:=
Eq.refl: ∀ {α : Sort ?u.619} (a : α), a = a
Eq.refl
2: ?m.622
2
example: 3 = 3
example
:
3: ?m.640
3
=
3: ?m.654
3
:= @
Eq.refl: ∀ {α : Sort ?u.707} (a : α), a = a
Eq.refl
: Type
3: ?m.709
3
example: 3 = 3
example
:
3: ?m.717
3
=
3: ?m.731
3
:= @
Eq.refl: ∀ {α : Sort ?u.784} (a : α), a = a
Eq.refl
_: Sort ?u.784
_
3: ?m.787
3
1 = 1 : Prop
1: ?m.804
1
=
1: ?m.820
1
-- 1 = 1 : Prop
ℕ : Type
: Type
-- ℕ : Type /- The universe of propositions. Prop ≡ Sort 0-/
Prop : Type
Prop: Type
Prop
-- Prop : Type /- A type universe. Type ≡ Type 0, Type u ≡ Sort (u + 1)-/
Type : Type 1
Type: Type 1
Type
-- Type : Type 1