apply tactic cannot find an instance for a variable - coq

I have been trying out apply tactic in various scenarios and it seems to stuck in the following case when premises are like this:
H1 : a
H2 : a -> forall e : nat, b -> g e
============================
...
When I try apply H2 in H1., it gives me the error:
Error: Unable to find an instance for the variable e.
Any way for me to bring forall e : nat, b -> g e as part of premises. This is the full working code with the above scenario:
Lemma test : forall {a b c : Prop} {g : nat} (f : nat -> Prop),
a /\ (a -> forall {e : nat}, b -> f e) -> c.
Proof.
intros a b c f g.
intros [H1 H2].
(* apply H2 in H1. *)
Abort.

The Coq Reference manual, ยง8.2.5:
The tactic apply term in ident tries to match the conclusion of the type of ident against a non-dependent premise of the type of term, trying them from right to left. If it succeeds, the statement of hypothesis ident is replaced by the conclusion of the type of term.
Now, applying the above description to your case, we get the following, Coq tries to replace H1 : a with the conclusion of H2, i.e. g e. To do that it needs to instantiate the universally quantified variable e with some value, which Coq cannot obviously infer -- hence the error message you've seen.
Another way to see that is to try a different variant of apply ... in ...:
eapply H2 in H1.
which will give you two subgoals:
...
H2 : a -> forall e : nat, b -> g e
H1 : g ?e
============================
c
and
...
H1 : a
H2 : a -> forall e : nat, b -> g e
============================
b
The H1 hypothesis of the first subgoal shows what Coq was going for with the ordinary apply in tactic, but in the eapply in case the variable e got replaced with an existential variable (?e). If you are not familiar with existential variables yet, then they are sort of promise you make to Coq that you'll build terms for them later. You are supposed to build the terms implicitly, via unification.
Anyways, specialize (H2 H1). might be what you want to do, or something like this
pose proof (H2 H1) as H; clear H1; rename H into H1.

Related

The missing De Morgan's law

Coq uses constructive logic, which means that if you try to fill out
De Morgan's laws, you'll end up missing 2.
Namely, you can't prove:
Theorem deMorgan_nand P Q (andPQ : ~(P /\ Q)) : P \/ Q.
Abort.
Theorem deMorgan_nall {A} (P : A -> Prop) (allPa : ~forall a, P a) : exists a, ~P a.
Abort.
This makes sense, because you've have to compute whether it was
the left or right item of the or, which you can't do in general.
Looking at
"Classical Mathematics for a Constructive World"
(https://arxiv.org/pdf/1008.1213.pdf)
has the definitions
Definition orW P Q := ~(~P /\ ~Q).
Definition exW {A} (P : A -> Prop) := ~forall a, ~P a.
similar to De Morgan's law. This suggests an alternative formulation.
Theorem deMorgan_nand P Q (andPQ : ~(P /\ Q)) : orW (~P) (~Q).
hnf; intros nnPQ; destruct nnPQ as [ nnP nnQ ].
apply nnP; clear nnP; hnf; intros p.
apply nnQ; clear nnQ; hnf; intros q.
apply (andPQ (conj p q)).
Qed.
Theorem deMorgan_nall {A} (P : A -> Prop) (allPa : ~forall a, P a) : exW (fun a => ~P a).
Abort.
But, it doesn't work with negating forall. In particular, it gets stuck on
trying to convert ~~P a into P a. So, despite in the nand case
converting ~~P into P, it doesn't seem to work with forall.
You can also show that there is some element of a that has
P a.
Similarly, you could try to show
Theorem deMorgan_nexn {A} (P : A -> Prop) (exPa : ~exists a, ~P a) : ~~forall a, P a.
Abort.
but that gets stuck in that once you have the argument a,
the conclusion is no longer False, so you can't use ~~P -> P.
So, if you can't prove deMorgan_nall, is there any theorem like it?
Or is ~forall a, P a already as simplified as it can get?
More generally, when the conclusion is False, that allows for using
the law of excluded middle (P \/ ~P). Is there any counterpart
to that that works when the proposition takes an argument, that is
P : A -> Prop instead of P : Prop ?
The principle you are looking for is known as double negation shift. It is not valid in intuitionistic logic in general. Despite looking fairly innocuous at first, as its conclusion is a doubly-negated formula, it is actually quite potent. Indeed, DNS is essentially what is needed in order to interpret the axiom of choice through the double-negation translation.
Edit by scubed:
So, that means I have to add an axiom to handle this case. Using the axiom,
Axiom deMorgan_allnn : forall {A} (P : A -> Prop) (allPa : forall a, ~~P a), ~~forall a, P a.
Theorem deMorgan_nall {A} (P : A -> Prop) (allPa : ~forall a, P a) : exW (fun a => ~P a).
hnf; intros ex1; apply deMorgan_allnn in ex1.
apply ex1; clear ex1; hnf; intros all2.
apply (allPa all2).
Qed.

Does Gallina have holes like in Agda?

When proving in Coq, it's nice to be able to prove one little piece at a time, and have Coq help keep track of the obligations.
Theorem ModusPonens: forall (A B : Prop), ((A -> B) /\ A) -> B.
Proof.
intros A B [H1 H2].
apply H1.
At this point I can see the proof state to know what is required to finish the proof:
context
H2: B
------
goal: B
But when writing Gallina, do we have to solve the whole thing in one bang, or make lots of little helper functions? I'd love to be able to put use a question mark to ask Coq what it's looking for:
Definition ModusPonens' := fun (A B : Prop) (H : (A -> B) /\ A) =>
match H with
| conj H1 H2 => H1 {?} (* hole of type B *)
end.
It really seems like Coq should be able to do this, because I can even put ltac in there and Coq will find what it needs:
Definition ModusPonens' := fun (A B : Prop) (H : (A -> B) /\ A) =>
match H with
| conj H1 H2 => H1 ltac:(assumption)
end.
If Coq is smart enough to finish writing the definition for me, it's probably smart enough to tell me what I need to write in order to finish the function myself, at least in simple cases like this.
So how do I do this? Does Coq have this kind of feature?
You can use refine for this. You can write underscores which will turn into obligations for you to solve later.
Definition ModusPonens: forall (A B : Prop), ((A -> B) /\ A) -> B.
refine (fun A B H =>
match H with
| conj H1 H2 => H1 _ (* hole of type A *)
end).
Now your goal is to provide an A. This can be discharged with exact H2. Defined.
Use an underscore
Definition ModusPonens' := fun (A B : Prop) (H : (A -> B) /\ A) =>
match H with
| conj H1 H2 => H1 _ (* hole of type A *)
end.
(*
Error: Cannot infer this placeholder of type
"A" in environment:
A, B : Prop
H : (A -> B) /\ A
H1 : A -> B
H2 : A
*)
or use Program
Require Import Program.
Obligation Tactic := idtac. (* By default Program tries to be smart and solve simple obligations automatically. This commands disables it. *)
Program Definition ModusPonens' := fun (A B : Prop) (H : (A -> B) /\ A) =>
match H with
| conj H1 H2 => H1 _ (* hole of type A *)
end.
Next Obligation. intros. (* See the type of the hole *)

Understanding specialize tactic

Trying to comprehend the answer of #keep_learning I walked through this code step by step:
Inductive nostutter {X:Type} : list X -> Prop :=
| ns_nil : nostutter []
| ns_one : forall (x : X), nostutter [x]
| ns_cons: forall (x : X) (h : X) (t : list X), nostutter (h::t) -> x <> h -> nostutter (x::h::t).
Example test_nostutter_4: not (nostutter [3;1;1;4]).
Proof.
intro.
inversion_clear H.
inversion_clear H0.
unfold not in H2.
(* We are here *)
specialize (H2 eq_refl).
apply H2.
Qed.
Here is what we have before excuting specialize
H1 : 3 <> 1
H : nostutter [1; 4]
H2 : 1 = 1 -> False
============================
False
Here is eq Prop whose constructor eq_refl is used in specialize:
Inductive eq (A:Type) (x:A) : A -> Prop :=
eq_refl : x = x :>A
where "x = y :> A" := (#eq A x y) : type_scope.
I can't explain, how this command works:
specialize (H2 eq_refl).
I read about specialize in reference manual, but the explanation there is too broad. As far as I understand it sees that "1 = 1" expression in H2 satisfies eq_refl constructor and therefore eq proposition is True. Then it simplifies the expression:
True -> False => False
And we get
H1 : 3 <> 1
H : nostutter [1; 4]
H2 : False
============================
False
Can somebody provide me a minimal example with explanation of what is specialize doing, so I could freely use it?
Update
Trying to imitate how specialize works using apply I did the following:
Example specialize {A B: Type} (H: A -> B) (a: A): B.
Proof.
apply H in a.
This gives:
A : Type
B : Type
H : A -> B
a : B
============================
B
Almost the same as specialize, only different hypothesis name.
In test_nostutter_4 theorem I tried this and it worked:
remember (#eq_refl nat 1) as Heq.
apply H2 in Heq as H3.
It gives us:
H1 : 3 <> 1
H : nostutter [1; 4]
H2 : 1 = 1 -> False
Heq : 1 = 1
H3 : False
HeqHeq : Heq = eq_refl
============================
False
This one was more complex, we had to introduce a new hypothesis Heq. But we got what we need - H3 at the end.
Does specialize internally use something like remember? Or is it possible to solve it with apply but without remember?
specialize, in its simplest form, simply replaces a given hypothesis with that hypothesis applied to some other term.
In this proof,
Example specialize {A B: Type} (H: A -> B) (a: A): B.
Proof.
specialize (H a).
exact H.
Qed.
we initially have the hypothesis H: A -> B. When we call specialize (H a), we apply H to a (apply as in function application). This gives us something of type B. specialize then gets rid of the old H for us and replaces it with the result of the application. It gives the new hypothesis the same name: H.
In your case, we have H2: 1 = 1 -> False, which is a function from the type 1 = 1 to the type False. That means that H2 applied to eq_refl is of type False, i.e. H2 eq_refl: False. When we use the tactic specialize (H2 eq_refl)., the old H2 is cleared and replaced by a new term (H2 eq_refl) whose type is False. It keeps the old name H2, though.
specialize is useful when you're sure that you're only going to use a hypothesis once, since it automatically gets rid of the old hypothesis. One disadvantage is that the old name may not fit the meaning of the new hypothesis. However, in your case and in my example, H is a generic enough name that it works either way.
To your update...
specialize is a core tactic defined directly in the ltac plugin. It doesn't use any other tactic internally, since it is its internals.
If you want to keep a hypothesis, you can use the as modifier, which works for both specialize and apply. In the proof
Example specialize {A B: Type} (H: A -> B) (a: A): B.
Proof.
if you do specialize (H a) as H0., instead of clearing H, it'll introduce a new hypothesis H0: B. apply H in a as H0. has the same effect.

Applying apply tactic to premises instead of the goal

If the goal state is like this:
a : Prop
b : Prop
H1 : a
H2 : b -> c
============================
c
Then I can convert it to the following state using apply H2 tactic:
a : Prop
b : Prop
H1 : a
H2 : b -> c
============================
b
Now, I want to do the same but for hypothesis:
a : Prop
b : Prop
H1 : a
H2 : b -> a
============================
b
I want to introduce a new hypothesis(or simplify the existing hypothesis) such that I have a new H3 : b in premises. Is that possible ?
I tried various variations of apply but everything is leading to some kind of error. Code for bringing up to the above state:
Lemma test : forall {a b : Prop},
a /\ (b -> a) -> b.
Proof.
intros a b.
intros [H1 H2].
Abort.
This is not possible, because your test lemma does not hold. For instance, take a to be True and b to be False. Both premises (a and b -> a) hold, yet b does not hold.
This would work, however, if you changed the statement of your result a little:
Lemma test : forall a b : Prop, a /\ (a -> b) -> b.
Proof. intros [H1 H2]. apply H2 in H1. exact H1. Qed.

Using remember in induction over proposition gives 'ill-typed' error in Coq

Here are the inductive & computational definitions of evenness of natural numbers.
Inductive ev : nat -> Prop :=
| ev_0 : ev O
| ev_SS : forall n:nat, ev n -> ev (S (S n)).
Definition even (n:nat) : Prop :=
evenb n = true.
And the proof that one implies the other.
Theorem ev__even : forall n,
ev n -> even n.
intros n E.
induction E as [ | n' E' ].
reflexivity. apply IHE'. Qed.
I didn't think much of this proof at first, but on a closer look I find something troubling. The problem is that after the reflexivity step, I expect to see the context
1 subgoal
n' : nat
E : ev (S (S n'))
E' : ev n'
IHE' : ev n' -> even n'
====================================================================== (1/1)
even (S (S n'))
But what I actually get instead is
1 subgoal
n' : nat
E' : ev n'
IHE' : even n'
====================================================================== (1/1)
even (S (S n'))
Although the theorem is still provable as is, it is disturbing to see hypotheses mysteriously disappear. I'd like to know how to get the context I initially expected. From web searches I understand that this is a general problem with induction over constructed terms in Coq. One proposed solution on SO suggests using the remember tactic on hypotheses to be kept. But when I try that in this proof,
Theorem ev__even : forall n,
ev n -> even n.
intros n E.
remember E.
induction E as [ | n' E' ].
I get the following error message at the induction step.
Error: Abstracting over the term "n" leads to a term
"fun n : nat => forall e : ev n, e = E -> even n" which is ill-typed.
Which I do not really understand. I think the problem is that E has a free variable, but in that case I would be stuck, since there is no way to introduce E without also introducing n. (generalize dependent n would generalize E with it)
Is there any way to obtain the initially expected context?
To be useful, the induction tactic tries to generalize over all variables that depend on the thing you are doing induction on, and things that depend on the indices of its type. In your case, this implies generalizing over n, the newly generated proof e : ev n, and the equality e = E. However, it does not generalize over E itself, because the induction principles that are automatically generated for propositions ignore the proof argument. Unfortunately, this means that that generalization will be ill-typed, and your intuition is correct: because E was not generalized with n, its type will mention a different number, which will make the equality e = E ill-typed.
I don't understand what the induction tactic is doing here.
Whenever I don't understand what a tactic is doing, I try to just write the proof term myself.
If you invoke the induction principle by hand, you can keep the original hypothesis:
Theorem ev__even : forall n, ev n -> even n.
intros n E.
refine (ev_ind even _ _ n E).
- reflexivity.
- intros n' E' IH.
apply IH.
Qed.
This is what the context looks like in the second case of the induction:
n : nat
E : ev n
n' : nat
E' : ev n'
IH : even n'
============================
even (S (S n'))
Assuming
Fixpoint evenb (n:nat) : bool :=
match n with
| O => true
| S O => false
| S (S n') => evenb n'
end.