Created
November 19, 2012 15:03
-
-
Save tel/4111150 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
intros b c H. destruct b. | |
simpl in H. rewrite -> H. reflexivity. simpl in H. | |
(** There are no hard and fast rules for how proofs should be | |
formatted in Coq -- in particular, where lines should be broken | |
and how sections of the proof should be indented to indicate their | |
nested structure. However, if the places where multiple subgoals | |
are generated are marked with explicit [Case] tactics placed at | |
the beginning of lines, then the proof will be readable almost no | |
matter what choices are made about other aspects of layout. | |
This is a good place to mention one other piece of (possibly | |
obvious) advice about line lengths. Beginning Coq users sometimes | |
tend to the extremes, either writing each tactic on its own line | |
or entire proofs on one line. Good style lies somewhere in the | |
middle. In particular, one reasonable convention is to limit | |
yourself to 80-character lines. Lines longer than this are hard | |
to read and can be inconvenient to display and print. Many | |
editors have features that help enforce this. *) | |
(* ###################################################################### *) | |
(** * Induction *) | |
(** We proved above that [0] is a neutral element for [+] on | |
the left using a simple partial evaluation argument. The fact | |
that it is also a neutral element on the _right_... *) | |
Theorem plus_0_r_firsttry : forall n:nat, | |
n + 0 = n. | |
(** ... cannot be proved in the same simple way. Just applying | |
[reflexivity] doesn't work: the [n] in [n + 0] is an arbitrary | |
unknown number, so the [match] in the definition of [+] can't be | |
simplified. 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, but in the branch where [n = S n'] for some [n'] | |
we get stuck in exactly the same way. We could use [destruct n'] to | |
get one step further, but since [n] can be arbitrarily large, if we | |
try to keep on going this way we'll never be done. *) | |
Proof. | |
intros n. | |
simpl. (* Does nothing! *) | |
Admitted. | |
(** Case analysis gets us a little further, but not all the way: *) | |
Theorem plus_0_r_secondtry : forall n:nat, | |
n + 0 = n. | |
Proof. | |
intros n. destruct n as [| n']. | |
Case "n = 0". | |
reflexivity. (* so far so good... *) | |
Case "n = S n'". | |
simpl. (* ...but here we are stuck again *) | |
Admitted. | |
(** To prove such facts -- indeed, to prove most interesting | |
facts about numbers, lists, and other inductively defined sets -- | |
we need a more powerful reasoning principle: _induction_. | |
Recall (from high school) 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 [n], we can | |
reason like this: | |
- show that [P(O)] holds; | |
- show that, for any [n'], if [P(n')] holds, then so does | |
[P(S n')]; | |
- conclude that [P(n)] holds for all [n]. | |
In Coq, the steps are the same but the order is backwards: we | |
begin with the goal of proving [P(n)] for all [n] and break it | |
down (by applying the [induction] tactic) into two separate | |
subgoals: first showing [P(O)] and then showing [P(n') -> P(S | |
n')]. Here's how this works for the theorem we are trying to | |
prove at the moment: *) | |
Theorem plus_0_r : forall n:nat, n + 0 = n. | |
Proof. | |
intros n. induction n as [| n']. | |
Case "n = 0". reflexivity. | |
Case "n = S n'". simpl. rewrite -> IHn'. reflexivity. Qed. | |
(** Like [destruct], the [induction] tactic takes an [as...] | |
clause that specifies the names of the variables to be introduced | |
in the subgoals. In the first branch, [n] is replaced by [0] and | |
the goal becomes [0 + 0 = 0], which follows by simplification. In | |
the second, [n] is replaced by [S n'] and the assumption [n' + 0 = | |
n'] is added to the context (with the name [IHn'], i.e., the | |
Induction Hypothesis for [n']). The goal in this case becomes [(S | |
n') + 0 = S n'], which simplifies to [S (n' + 0) = S n'], which in | |
turn follows from the induction hypothesis. *) | |
Theorem minus_diag : forall n, | |
minus n n = 0. | |
Proof. | |
(* WORKED IN CLASS *) | |
intros n. induction n as [| n']. | |
Case "n = 0". | |
simpl. reflexivity. | |
Case "n = S n'". | |
simpl. rewrite -> IHn'. reflexivity. Qed. | |
(** **** Exercise: 2 stars, recommended (basic_induction) *) | |
Theorem mult_0_r : forall n:nat, | |
n * 0 = 0. | |
Proof. | |
intros n. | |
induction n |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment