`.
**Example:**
Theorem one_x_one : forall (x : nat),
1 + x + 1 = 2 + x.
Proof.
intro. simpl.
1 subgoal
x : nat
-------------------(1/1)
S (x + 1) = S (S x)
We believe that `x + 1` and `S x` are equal, so we can use `replace` to assert
that this equality is true and then prove it later.
Theorem one_x_one : forall (x : nat),
1 + x + 1 = 2 + x.
Proof.
intro. simpl.
replace (x + 1) with (S x).
2 subgoals
x : nat
-------------------(1/2)
S (S x) = S (S x)
-------------------(2/2)
S x = x + 1
## Breaking apart goals and hypotheses
The following tactics break apart goals (or hypotheses) into several simpler
subgoals (or hypotheses).
### split
If the goal is a conjunction `A /\ B`, the `split` tactic replaces the goal
with two subgoals `A` and `B`.
**Example:**
Theorem implies_and : forall (P Q R : Prop),
P -> (P -> Q) -> (P -> R) -> (Q /\ R).
Proof.
intros P Q R P_holds.
intros P_implies_Q P_implies_R.
1 subgoal
P, Q, R : Prop
P_holds : P
P_implies_Q : P -> Q
P_implies_R : P -> R
-------------------(1/1)
Q /\ R
In order to make progress in the proof, we use `split` to break up
`Q /\ R` into two subgoals.
Theorem implies_and : forall (P Q R : Prop),
P -> (P -> Q) -> (P -> R) -> (Q /\ R).
Proof.
intros P Q R P_holds.
intros P_implies_Q P_implies_R.
split.
2 subgoals
P, Q, R : Prop
P_holds : P
P_implies_Q : P -> Q
P_implies_R : P -> R
-------------------(1/2)
Q
-------------------(2/2)
R
### destruct (and / or)
If there is a hypothesis containing a conjunction or a disjunction in the
context, you can use the `destruct` tactic to break them apart.
A hypothesis `A /\ B` means that both `A` and `B` hold, so it can be destructed
into two new hypotheses `A` and `B`. You can also use the `destruct..as [...]`
syntax to give your own name to these new hypotheses. See Example 1.
On the other hand, a hypothesis `A \/ B` means that at least one of `A` and `B`
holds, so in order to make use of this hypothesis, you must prove that the goal
holds when `A` is true (and `B` may not be) and when `B` is true (and `A` may
not be). You can also use the `destruct..as [... | ...]` syntax to provide
your own names to the hypotheses that are generated (note the presence of the
the vertical bar). See Example 2.
**Example 1:**
Theorem and_left : forall (P Q : Prop),
(P /\ Q) -> P.
Proof.
intros P Q P_and_Q.
1 subgoal
P, Q : Prop
P_and_Q : P /\ Q
-------------------(1/1)
P
Since there's a conjunction `P /\ Q` in our context, using `destruct` on it
will give us both `P` and `Q` as separate hypotheses.
Theorem and_left : forall (P Q : Prop),
(P /\ Q) -> P.
Proof.
intros P Q P_and_Q.
destruct P_and_Q.
1 subgoal
P, Q : Prop
H : P
H0 : Q
-------------------(1/1)
P
The names that Coq chose for the new hypotheses aren't very descriptive, so
let's provide our own.
Theorem and_left : forall (P Q : Prop),
(P /\ Q) -> P.
Proof.
intros P Q P_and_Q.
destruct P_and_Q as [P_holds Q_holds].
1 subgoal
P, Q : Prop
P_holds : P
Q_holds : Q
-------------------(1/1)
P
**Example 2:**
Theorem or_comm : forall (P Q : Prop),
P \/ Q -> Q \/ P.
Proof.
intros P Q P_or_Q.
1 subgoal
P, Q : Prop
P_or_Q : P \/ Q
-------------------(1/1)
Q \/ P
We can `destruct` the hypothesis `P \/ Q` to replace our current goal with two
new subgoals `P \/ Q` with different contexts: one in which `P` holds and one
in which `Q` holds.
Theorem or_comm : forall (P Q : Prop),
P \/ Q -> Q \/ P.
Proof.
intros P Q P_or_Q.
destruct P_or_Q as [P_holds | Q_holds].
2 subgoals
P, Q : Prop
P_holds : P
-------------------(1/2)
Q \/ P
-------------------(2/2)
Q \/ P
After we've proven the first subgoal, we observe that, in the context for the
second subgoal, we have the hypothesis that `Q` holds instead.
Theorem or_comm : forall (P Q : Prop),
P \/ Q -> Q \/ P.
Proof.
intros P Q P_or_Q.
destruct P_or_Q as [P_holds | Q_holds].
- right. assumption.
-
1 subgoal
P, Q : Prop
Q_holds : Q
-------------------(1/1)
Q \/ P
### destruct (case analysis)
The `destruct` tactic can also be used for more general case analysis by
destructing on a term or variable whose type is an inductive type.
**Example:**
Inductive element :=
| grass : element
| fire : element
| water : element.
Definition weakness (e : element) : element :=
match e with
| grass => fire
| fire => water
| water => grass
end.
Theorem never_weak_to_self : forall (e : element),
weakness e <> e.
Proof.
1 subgoal
-------------------(1/1)
forall e : element, weakness e <> e
In order to proceed with this proof, we need to prove that it holds for each
constructor of `element` case-by-case, so we use `destruct`.
Theorem never_weak_to_self : forall (e : element),
weakness e <> e.
Proof.
destruct e.
3 subgoals
-------------------(1/3)
weakness grass <> grass
-------------------(2/3)
weakness fire <> fire
-------------------(3/3)
weakness water <> water
### induction
Using the `induction` tactic is the same as using the `destruct` tactic, except
that it also introduces induction hypotheses as appropriate.
Once again, you can use the `induction..as [...]` syntax to give names to the
terms and hypotheses produced in the different cases.
See lecture, notes, and lab 22 for more on induction.
**Example:**
Theorem n_plus_n : forall (n : nat),
n + n = n * 2.
Proof.
induction n as [| x IH].
2 subgoals
-------------------(1/2)
0 + 0 = 0 * 2
-------------------(2/2)
S x + S x = S x * 2
The base case `0` doesn't produce anything new, so we don't need to provide any
names there. The inductive case `S x` produces a new term `x` and a new
hypothesis, so we give those names. The vertical bar separates the two cases.
After proving the base case, we move on to the inductive case. Hey, Coq came
up with the correct induction hypothesis for us. Thanks, Coq!
Theorem n_plus_n : forall (n : nat),
n + n = n * 2.
Proof.
induction n as [| x IH].
- reflexivity.
- simpl.
1 subgoal
x : nat
IH : x + x = x * 2
-------------------(1/1)
S (x + S x) = S (S (x * 2))
From here, we can make use of the induction hypothesis with `rewrite` and then
apply `auto` to knock out the rest of the proof.
Theorem n_plus_n : forall (n : nat),
n + n = n * 2.
Proof.
induction n as [| x IH].
- reflexivity.
- simpl. rewrite <- IH. auto.
No more subgoals.
## Solving specific types of goals
The tactics in this section are automated tactics that are specialized for
solving certain types of goals.
### ring
The `ring` tactic can solve any goal that contains only addition and
multiplication operations.
You must first use the command `Require Import Arith.` in order to use `ring`.
**Example:**
Require Import Arith.
Theorem foil : forall a b c d,
(a + b) * (c + d) = a*c + b*c + a*d + b*d.
Proof.
intros. ring.
No more subgoals.
It would be pretty painful to prove this using simpler tactics, but fortunately
`ring` is here to save the day.
### tauto
The `tauto` tactic can solve any goal that's a tautology (in constructive
logic). A tautology is a logical formula that's always true, regardless of the
values of the variables in it.
**Example:**
Theorem demorgan : forall (P Q : Prop),
~(P \/ Q) -> ~P /\ ~Q.
Proof.
tauto.
No more subgoals.
DeMorgan's law is a tautology, so it can be proven by applying `tauto`.
### field
The `field` tactic can solve any goal that contains addition, subtraction
(the additive inverse), multiplication, and division (the multiplicative
inverse).
Note that `field` cannot be used on the natural numbers or integers, because
integer division is not the inverse of multiplication (e.g. `(1 / 2) * 2` does
not equal 1).
You must first use the command `Require Import Field.` in order to use `field`.
See [lecture notes 22][notes22] for more information on `field`.
[notes22]: http://www.cs.cornell.edu/courses/cs3110/2017fa/l/22-coq-induction/notes.v
## Tacticals
The following *tacticals* are "higher-order tactics" that operate on tactics.
### ; (semicolon)
The `;` tactical applies the tactic on the right side of the semicolon to all
the subgoals produced by tactic on the left side.
**Example:**
Theorem and_comm : forall (P Q : Prop),
P /\ Q -> Q /\ P.
Proof.
intros P Q P_and_Q.
destruct P_and_Q.
split.
- assumption.
- assumption.
Qed.
The two subgoals generated by `split` were solved using the same tactic. We can
use `;` to make the code more concise.
Theorem and_comm : forall (P Q : Prop),
P /\ Q -> Q /\ P.
Proof.
intros P Q P_and_Q.
destruct P_and_Q.
split; assumption.
Qed.
### try
Many tactics will fail if they are not applicable. The `try` tactical lets you
attempt to use a tactic and allows the tactic to go through even if it
fails. This can be particularly useful when chaining tactics together using
`;`.
**Example:**
Inductive element :=
| grass : element
| fire : element
| water : element.
Definition weakness (e : element) : element :=
match e with
| grass => fire
| fire => water
| water => grass
end.
Theorem fire_weak_implies_grass :
forall (e : element),
weakness e = fire -> e = grass.
Proof.
destruct e.
3 subgoals
-------------------(1/3)
weakness grass = fire -> grass = grass
-------------------(2/3)
weakness fire = fire -> fire = grass
-------------------(3/3)
weakness water = fire -> water = grass
We'd like to use `discriminate` to take care of the second and third subgoals,
but we can't simply write `destruct e; discriminate.` because `discriminate`
will fail when Coq tries to apply it to the first subgoal. This is where the
`try` tactic comes in handy.
Theorem fire_weak_implies_grass :
forall (e : element),
weakness e = fire -> e = grass.
Proof.
destruct e; try discriminate.
1 subgoal
-------------------(1/1)
weakness grass = fire -> grass = grass
### || (or)
The `||` tactical first tries the tactic on the left side; if it fails, then it
applies the tactic on the right side.
**Example:**
Theorem fire_weak_implies_grass :
forall (e : element),
weakness e = fire -> e = grass.
Proof.
destruct e; try discriminate.
1 subgoal
-------------------(1/1)
weakness grass = fire -> grass = grass
Let's use this theorem from the last section again. `discriminate` took care
of the other two subgoals, and we know that `trivial` can solve this one. In
other words, we apply either `discriminate` or `trivial` to the subgoals
generated by `destruct e`, so we can use `||` to shorten the proof.
Theorem fire_weak_implies_grass :
forall (e : element),
weakness e = fire -> e = grass.
Proof.
destruct e; discriminate || trivial.
No more subgoals.
### all:
The `all:` tactical applies a tactic to all the remaining subgoals in the
proof.
**Example:**
Theorem fire_weak_implies_grass :
forall (e : element),
weakness e = fire -> e = grass.
Proof.
destruct e.
all: discriminate || trivial.
1 subgoal
-------------------(1/1)
weakness grass = fire -> grass = grass
An alternative proof for the previous theorem using `all:`.
### repeat
The `repeat` tactical repeatedly applies a tactic until it fails.
Note that `repeat` will never fail, even if it applies the given tactic zero
times.
**Example:**
Require Import Arith.
Theorem add_assoc_4 : forall (a b c d : nat),
(a + b + c) + d = a + (b + c + d).
Proof.
intros.
1 subgoal
a, b, c, d : nat
-------------------(1/1)
a + b + c + d = a + (b + c + d)
Coq provides a theorem
`Nat.add_assoc : forall n m p : nat, n + (m + p) = n + m + p`
in the `Arith` library that we can make use of two times for this proof.
Require Import Arith.
Theorem add_assoc_4 : forall (a b c d : nat),
(a + b + c) + d = a + (b + c + d).
Proof.
intros.
repeat rewrite -> Nat.add_assoc.
1 subgoal
a, b, c, d : nat
-------------------(1/1)
a + b + c + d = a + b + c + d
* * *
**Acknowledgement:** Inspired by the [Coq Tactic Index][tacticsindex] by Joseph
Redmon.
[tacticsindex]: https://pjreddie.com/coq-tactics/