Consider the following partial proof:
Theorem test : forall (n m : nat),
n = m -> S n = S m.
Proof.
intros n m H.
Executing until this point gives me the following:
1 subgoal
n, m : nat
H : n = m
______________________________________(1/1)
S n = S m
I would like to remove the Ss from the goal, obtaining the goal n = m. Is there a tactic that does this?
You are looking for the f_equal tactic.
Related
I'm trying to prove eqb_neq:
Theorem eqb_neq : forall x y : nat,
x =? y = false <-> x <> y.
This is my current proof status:
During the proof I reached a final step where I just need to prove the additional helper theorem:
Theorem eqb_false_helper : forall n m : nat,
n <> m -> S n <> S m.
I've tried multiple strategies but now I'm not even sure it's possible to prove this helper theorem.
I'm not sure how to prove the base case using induction:
What else can I try? Any tips for eqb_neq or the helper theorem?
Thanks
It is actually quite simple for your helper theorem if you just unfold not :
Theorem eqb_false_helper : forall n m : nat,
n <> m -> S n <> S m.
Proof.
unfold not; intros.
apply H; injection H0; intro; assumption.
Qed.
You actually just need to prove that S n = S m -> False, you assume that n = m -> False, thus you can prove that S n = S m -> n = m, which is done injecting hypothesis S n = S m.
I am facing a pretty strange problem: coq doesn't want to move forall variable into the context.
In the old times it did:
Example and_exercise :
forall n m : nat, n + m = 0 -> n = 0 /\ m = 0.
Proof.
intros n m.
It generates:
n, m : nat
============================
n + m = 0 -> n = 0 /\ m = 0
But when we have forall inside forall, it doesn't work:
(* Auxilliary definition *)
Fixpoint All {T : Type} (P : T -> Prop) (l : list T) : Prop :=
(* ... *)
Lemma All_In :
forall T (P : T -> Prop) (l : list T),
(forall x, In x l -> P x) <->
All P l.
Proof.
intros T P l. split.
- intros H.
After this we get:
T : Type
P : T -> Prop
l : list T
H : forall x : T, In x l -> P x
============================
All P l
But how to move x outside of H and destruct it into smaller pieces? I tried:
destruct H as [x H1].
But it gives an error:
Error: Unable to find an instance for the variable x.
What is it? How to fix?
The problem is that forall is nested to the left of an implication rather than the right. It does not make sense to introduce x from a hypothesis of the form forall x, P x, just like it wouldn't make sense to introduce the n in plus_comm : forall n m, n + m = m + n into the context of another proof. Instead, you need to use the H hypothesis by applying it at the right place. I can't give you the answer to this question, but you might want to refer to the dist_not_exists exercise in the same chapter.
Trying to solve eqb_trans I became stuck:
Theorem eqb_trans : forall n m p,
n =? m = true ->
m =? p = true ->
n =? p = true.
Obviously, we should use eqb_true to solve it:
Theorem eqb_true : forall n m,
n =? m = true -> n = m.
--------------------------------------------
Proof.
intros n m p H1 H2. apply eqb_true in H1.
apply eqb_true with (n:=m)(m:=p) in H2.
At this point we have:
n, m, p : nat
H1 : n = m
H2 : m = p
============================
(n =? p) = true
Now I wanted to use eqb_true upon the goal:
apply eqb_true with (m:=p).
But here we get an error:
Unable to unify "?M1056 = p" with "(n =? p) = true".
Why doesn't it work? How to fix?
When you apply a lemma to the goal, it is the conclusion of the lemma that must unify with the goal rather than its premise. The conclusion of this lemma is of the form _ = _, while your goal is (_ =? _) = true. These two cannot be unified, which leads to the error you see.
To prove eqb_trans, you need the converse of eqb_true, namely
forall n m, n = m -> (n =? m) = true,
which, after some simplification, is equivalent to
forall n, (n =? n) = true.
Theorem eqb_trans : forall n m p,
n =? m = true ->
m =? p = true ->
n =? p = true.
Proof.
intros n m p.
repeat rewrite Nat.eqb_eq.
intros.
rewrite H.
exact H0.
Qed.
-- Check Nat.eqb_eq.
Nat.eqb_eq
: forall n m : nat, (n =? m) = true <-> n = m
After destructing n in my proof, I am stuck at the following:
1 subgoal
n : nat
X : Type
h : X
t : list X
n' : nat
E : n = S n'
H' : length t = n'
IHl : length t = n -> nth_error t n = None
______________________________________(1/1)
nth_error t n' = None
I want to rewrite using IHl, but that is not possible. How do I compose IHl and H' to make sense and prove this theorem?
I am just trying to elaborate on #Arthur answer.
I was able to reproduce your goal with the following script:
Require Import List.
Lemma toto (n : nat) (X : Type) (l : list nat) : length l = n -> nth_error l n = None.
Proof.
induction l as [ | h t IHl].
case_eq n.
simpl; auto.
simpl; discriminate.
case_eq n.
simpl; discriminate.
intros n' E.
simpl; intros E'; injection E'; clear E'; intros H'.
and I agree that this goal cannot be proved. Now, if you instead start your proof with the following text (the Proof and induction lines have to be replaced), it will be provable (I checked).
Proof.
revert n.
induction l as [ | h t IHl]; intros n.
The difference is that the induction hypothesis now has the following statement.
forall n : nat, length t = n -> nth_error t n = None
What happened? In the first (faulty) variant, you attempt to prove a statement for all lists whose length is equal to a precise n, because n is fixed before you start the proof by induction. In the second (correct) variant, you attempt to prove a statement for all lists l, and this statement accepts any n as long as length l = n.
In the first variant, n is fixed and the equality length l = n restricts l to be among those that have length precisely n. In the second case, l is chosen first, and n is not fixed, but the equality length l = n restricts n to follow the length of l.
This is called "loading the induction" because the statement forall n, length l = n -> nth_error l n = None is stronger (it is loaded) than the statement that you attempt to prove in the first variant (just for one specific n), but surprisingly it is easier to prove.
You cannot, because your induction hypothesis is not general enough. Here is a statement that should be easier to prove:
forall (X : Type) (t : list X), nth_error t (length t) = None
Consider the following toy exercise:
Theorem swap_id: forall (m n : nat), m = n -> (m, n) = (n, m).
Proof.
intros m n H.
At this point I have the following:
1 subgoal
m, n : nat
H : m = n
______________________________________(1/1)
(m, n) = (n, m)
I would like to split the goal into two subgoals, m = n and n = m. Is there a tactic which does that?
Solve using the f_equal tactic:
Theorem test: forall (m n : nat), m = n -> (m, n) = (n, m).
Proof.
intros m n H. f_equal.
With state:
2 subgoals
m, n : nat
H : m = n
______________________________________(1/2)
m = n
______________________________________(2/2)
n = m