So I have two hypotheses, one that is h : A -> B, and the other which is h2 : A. How can I get h3 : B to appear in my hypotheses?
pose proof (h h2) as h3.
introduces h3 : B as a new hypothesis,
specialize (h h2).
modifies h : A -> B into h : B -- this can be useful if you won't need h later, and symmetrically,
apply h in h2.
converts h2 : A into h2 : B.
Another (not very convenient) way would be to
assert B as h3 by exact (h h2).
That's what the pose proof variant is equivalent to.
Also, in a simple case like the following, you can solve your goal without introducing a new hypothesis:
Goal forall (A B : Prop), (A -> B) -> A -> B.
intros A B h h2.
apply (h h2).
Qed.
Related
That's pretty clear what destruct H does if H contains conjunction or disjunction. But I can't figure out what it does in general case. It does something bizarre, especially if H: a -> b.
Some examples:
Lemma demo : forall (x y: nat), x=4 -> x=4.
Proof.
intros. destruct H.
The hypothesis is just destroyed:
1 subgoal
x, y : nat
______________________________________(1/1)
x = x
Another one:
Lemma demo : forall (x y: nat), (x = 4 -> x=4) -> True.
Proof.
intros. destruct H.
Now I have two branches:
1 subgoal
x, y : nat
______________________________________(1/1)
x = 4
1 subgoal
x, y : nat
______________________________________(1/1)
True
Third example. It's not provable but it still doesn't make sense to me:
Lemma demo : forall (x y: nat), (x = 4 -> x = 4) -> x = 4.
Proof.
intros. destruct H.
Now I have to prove x = x in the second branch!
2 subgoals
x, y : nat
______________________________________(1/2)
x = 4
______________________________________(2/2)
x = x
So, I clearly don't understand what destruct H does.
The cases you are referring to fall in two categories. If H : A and A is inductively or coinductively defined (e.g., conjunction and disjunction), then destruct H generates one subgoal for each constructor in that type, with additional hypotheses determined by the arguments of that constructor. On the other hand, if H : A -> B, then destruct H generates one subgoal where you have to prove A, and then continues recursively as if H : B. This is roughly equivalent to the following calls:
assert (H' : A); [ |specialize (H H'); destruct H].
The missing piece of the puzzle is that equality itself is defined as an inductive type:
Inductive eq (A : Type) (a : A) : A -> Prop :=
| eq_refl : eq A a a
When you destruct something of type x = 4, Coq generates one case for each constructor of that type. But there is only one constructor in that type: eq_refl. When considering that case, Coq also automatically replaces occurrences of the RHS of destructed equality by the LHS (since both sides are equal for that constructor). In your first and third examples, this leads to replacing 4 in the goal with x.
Most of the time, you do not want to destruct an equality hypothesis, since this replacement behavior is not very useful. It is usually better to use the rewrite tactic, since it allows you to rewrite from rightto-left or left-to-right.
I'm wondering as destruct H as (H1 & H2). on hypothesis H : p /\ q creates two hypotheses H1 : p and H2 : q, if there is any tactic that does the other way around. That is, taking two hypotheses and creating one with conjunction of those.
Here are two possibilities, using the assert tactic:
Goal forall A B : Prop, A -> B -> A /\ B.
Proof.
intros A B HA HB.
assert (H1 : A /\ B). { now split. }
assert (H2 := conj HA HB).
Abort.
Trying to prove the following in coq:
Prove that the universal quantifier distributes over conjunction
∀x ∈ A, P x ∧ Qx ⇐⇒ (∀x ∈ A, P x) ∧ (∀x ∈ A, Qx)
My Proof so far-
Parameter (A : Type).
Parameter (P Q : A -> Prop).
Lemma II3: (forall x : A, P x /\ Q x) <->
(forall x : A, P x) /\ (forall x : A, Q x).
split.
intro H.
split.
apply H.
intros H1.
Proof.
I have tried to split, destruct, and introduce a new hypothesis, but I just can't seem to make it past this point. Any advice would be greatly appreciated.
this is a pretty easy proof, for example now intuition; apply H will solve your goal.
In your case, you should first figure out how the proof works using pen and paper, and once you've done that, the proof in Coq will be trivial.
Consider the following inductive definition:
Inductive T (n : nat) : nat -> Prop :=
| c1 : T n n.
This works:
Theorem a : T 1 1.
Proof.
apply c1.
Qed.
But this doesn't:
Theorem b : T 1 1 -> True.
Proof.
intros H.
apply c1 in H.
Both calls to apply seem equivalent to me, but the latter fails with Error: Statement without assumptions. Why? And how can I make it work?
This question arose from my poor understanding of the apply tactic. #gallais's comment made me realize why apply c1 in H doesn't really make sense. The tactic essentially works as a function application on H and c1 H doesn't really make sense. For future reference, this is an example in which apply in would make sense. If we had another constructor c2 like this:
Inductive T (n : nat) : nat -> Prop :=
| c1 : T n n
| c2 : forall x, T n x -> T n (S x).
Then apply c2 in H would transform something of type T n x into something of type T n (S x), for example:
Theorem b : T 1 1 -> True.
Proof.
intros H.
apply c2 in H.
transforms the hypothesis H : T 1 1 into H : T 1 2.
There is a difference between proving H or proving H -> True. The Coq standard library already defined a proof of True, called I.
Hence:
Theorem b : T 1 1 -> True.
Proof.
intros; apply I.
Qed.
But please also note that:
Theorem prove_I : forall p : Prop, p -> True.
Proof.
intros; apply I.
Qed.
And as a consequence H -> True does not prove H, there's no correlation between the inhabitants of the two type.
The apply tactic works differently when it is applied to a goal or a hypothesis. Applying H : A -> B has the following semantics:
if the goal was B, then it will be transformed to A after apply H.
if the hypothesis H1 : A, then it will be transformed to H1 : B after apply H in H1
This makes the reasoning correct; so it does not introduce inconsistencies.
Consider the following development:
Require Import Relation RelationClasses.
Set Implicit Arguments.
CoInductive stream (A : Type) : Type :=
| scons : A -> stream A -> stream A.
CoInductive stream_le (A : Type) {eqA R : relation A}
`{PO : PartialOrder A eqA R} :
stream A -> stream A -> Prop :=
| le_step : forall h1 h2 t1 t2, R h1 h2 ->
(eqA h1 h2 -> stream_le t1 t2) ->
stream_le (scons h1 t1) (scons h2 t2).
If I have a hypothesis stream_le (scons h1 t1) (scons h2 t2), it would be reasonable for the destruct tactic to turn it into a pair of hypotheses R h1 h2 and eqA h1 h2 -> stream_le t1 t2. But that's not what happens, because destruct loses information whenever doing anything non-trivial. Instead, new terms h0, h3, t0, t3 are introduced into the context, with no recall that they are respectively equal to h1, h2, t1, t2.
I would like to know if there is a quick and easy way to do this kind of "smart destruct". Here is what i have right now:
Theorem stream_le_destruct : forall (A : Type) eqA R
`{PO : PartialOrder A eqA R} (h1 h2 : A) (t1 t2 : stream A),
stream_le (scons h1 t1) (scons h2 t2) ->
R h1 h2 /\ (eqA h1 h2 -> stream_le t1 t2).
Proof.
intros.
destruct H eqn:Heq.
remember (scons h1 t1) as s1 eqn:Heqs1;
remember (scons h2 t2) as s2 eqn:Heqs2;
destruct H;
inversion Heqs1; subst; clear Heqs1;
inversion Heqs2; subst; clear Heqs2.
split; assumption.
Qed.
Indeed, inversion basically does what you want, however as Arthur pointed out it is a bit unstable, mainly due to the different congruence steps.
Under the hood, inversion just calls a version of destruct, but remembering some equalities first. As you have well discovered, pattern matching in Coq will "forget" arguments of constructors, except if these are variables, then, all the variables under the scope of the destruct will be instantiated.
What does that mean? It means that in order to properly destruct an inductive I : Idx -> Prop, you want to get your goal of the form: I x -> Q x, so that destructing the I x will also refine the x in Q. Thus, a standard transformation for an inductive I term and goal Q (f term) is to rewrite it to I x -> x = term -> Q (f x). Then, destructing I x will get you x instantiated to the proper index.
With that in mind, it may be a good exercise to implement inversion manually using the case: tactic of Coq 8.7;
From Coq Require Import ssreflect.
Theorem stream_le_destruct A eqA R `{PO : PartialOrder A eqA R} (h1 h2 : A) (t1 t2 : stream A) :
stream_le (scons h1 t1) (scons h2 t2) ->
R h1 h2 /\ (eqA h1 h2 -> stream_le t1 t2).
Proof.
move E1: (scons h1 t1) => sc1; move E2: (scons h2 t2) => sc2 H.
by case: sc1 sc2 / H E1 E2 => h1' h2' t1' t2' hr ih [? ?] [? ?]; subst.
Qed.
You can read the manual for more details, but basically with the first line, we create the equalities we need; then, in the second we can destruct the term and get the proper instantiations solving the goal. A good effect of the case: tactic is that, contrary to destruct, it will try to prevent us from destructing a term without first bringing its dependencies into scope.
Calling destruct will not directly give you what you want. You need to use inversion instead.
Theorem stream_le_destruct : forall h1 h2 t1 t2,
stream_le (scons h1 t1) (scons h2 t2) ->
h1 <= h2 /\ (h1 = h2 -> stream_le t1 t2).
Proof.
intros.
inversion H; subst; clear H.
split; assumption.
Qed.
Unfortunately, the inversion tactic is quite ill behaved, as it tends to generate a lot of spurious equality hypotheses, making it hard to name them consistently. One (somewhat heavyweight, admittedly) alternative is to use inversion only to prove a lemma like the one you did, and apply this lemma in proofs instead of calling inversion.