# Review

To prove the following theorem, which tactics will we need besides intros and reflexivity? (1) none, (2) rewrite, (3) destruct, (4) both rewrite and destruct, or (5) can't be done with the tactics we've seen.
Theorem review1: (orb true false) = true.

Theorem review2: b, (orb true b) = true.
Which tactics do we need besides intros and reflexivity? (1) none (2) rewrite, (3) destruct, (4) both rewrite and destruct, or (5) can't be done with the tactics we've seen.

What if we change the order of the arguments of orb?
Theorem review3: b, (orb b true) = true.
Which tactics do we need besides intros and reflexivity? (1) none (2) rewrite, (3) destruct, (4) both rewrite and destruct, or (5) can't be done with the tactics we've seen.

Theorem review4 : n : nat, 0 + n = n.
(1) none, (2) rewrite, (3) destruct, (4) both rewrite and destruct, or (5) can't be done with the tactics we've seen.

Theorem review5 : n : nat, n + 0 = n.
(1) none, (2) rewrite, (3) destruct, (4) both rewrite and destruct, or (5) can't be done with the tactics we've seen.

# Separate Compilation

(We need to first use coqc to compile Basics.v into Basics.vo so it can be imported here -- detailed instructions are in the full version of this chapter...)

From LF Require Export Basics.

# Proof by Induction

We proved in the last chapter that 0 is a neutral element for + on the left using just reflexivity. The proof that it is also a neutral element on the right is trickier...

Theorem plus_n_O_firsttry : n:nat,
n = n + 0.
Proof.
intros n.
simpl. (* Does nothing! *)
Abort.
And reasoning by cases using destruct n doesn't get us much further: the branch of the case analysis where we assume n = 0 goes through fine, but in the branch where n = S n' for some n' we get stuck in exactly the same way.

Theorem plus_n_O_secondtry : n:nat,
n = n + 0.
Proof.
intros n. destruct n as [| n'] eqn:E.
- (* n = 0 *)
reflexivity. (* so far so good... *)
- (* n = S n' *)
simpl. (* ...but here we are stuck again *)
Abort.
We need a bigger hammer: the principle of induction over natural numbers...
• If P(n) is some proposition involving a natural number n, and we want to show that P holds for all numbers, we can reason like this:
• show that P(O) holds
• show that, if P(n') holds, then so does P(S n')
• conclude that P(n) holds for all n.
For example...

Theorem plus_n_O : n:nat, n = n + 0.
Proof.
intros n. induction n as [| n' IHn'].
- (* n = 0 *) reflexivity.
- (* n = S n' *) simpl. rewrite <- IHn'. reflexivity. Qed.
Let's try this one together:

Theorem minus_diag : n,
minus n n = 0.
Proof.
(* WORK IN CLASS *) Admitted.
Here's another related fact about addition, which we'll need later. (The proof is left as an exercise.)

Theorem plus_comm : n m : nat,
n + m = m + n.
Proof.
(* FILL IN HERE *) Admitted.

# Proofs Within Proofs

Here's a way to use an in-line assertion instead of a separate lemma. New tactic: assert.

Theorem mult_0_plus' : n m : nat,
(0 + n) × m = n × m.
Proof.
intros n m.
assert (H: 0 + n = n). { reflexivity. }
rewriteH.
reflexivity. Qed.
Another example of assert...

Theorem plus_rearrange_firsttry : n m p q : nat,
(n + m) + (p + q) = (m + n) + (p + q).
Proof.
intros n m p q.
(* We just need to swap (n + m) for (m + n)... seems
like plus_comm should do the trick! *)

rewriteplus_comm.
(* Doesn't work... Coq rewrites the wrong plus! :-( *)
Abort.
To use plus_comm at the point where we need it, we can introduce a local lemma stating that n + m = m + n (for the particular m and n that we are talking about here), prove this lemma using plus_comm, and then use it to do the desired rewrite.

Theorem plus_rearrange : n m p q : nat,
(n + m) + (p + q) = (m + n) + (p + q).
Proof.
intros n m p q.
assert (H: n + m = m + n).
{ rewriteplus_comm. reflexivity. }
rewriteH. reflexivity. Qed.

# Formal vs. Informal Proof

"Informal proofs are algorithms; formal proofs are code."

Theorem plus_assoc' : n m p : nat,
n + (m + p) = (n + m) + p.
Proof. intros n m p. induction n as [| n' IHn']. reflexivity.
simpl. rewriteIHn'. reflexivity. Qed.
Comments and bullets can make things clearer...

Theorem plus_assoc'' : n m p : nat,
n + (m + p) = (n + m) + p.
Proof.
intros n m p. induction n as [| n' IHn'].
- (* n = 0 *)
reflexivity.
- (* n = S n' *)
simpl. rewriteIHn'. reflexivity. Qed.
... but it's still nowhere near as readable for a human as a careful informal proof:
• Theorem: For any n, m and p,
n + (m + p) = (n + m) + p.
Proof: By induction on n.
• First, suppose n = 0. We must show
0 + (m + p) = (0 + m) + p.
This follows directly from the definition of +.
• Next, suppose n = S n', where
n' + (m + p) = (n' + m) + p.
We must show
(S n') + (m + p) = ((S n') + m) + p.
By the definition of +, this follows from
S (n' + (m + p)) = S ((n' + m) + p),
which is immediate from the induction hypothesis. Qed.