Software Foundations Volume 1: Tactics: injection_ex3 - coq

Could some explain how to complete this proof? (please don't give the actual answer, just some guidance :)
The exercise is from SF volume1, as stated in the title and it goes like this:
(** **** Exercise: 3 stars, standard (injection_ex3) *)
Example injection_ex3 : forall (X : Type) (x y z : X) (l j : list X),
x :: y :: l = z :: j ->
j = z :: l ->
x = y.
Now, I'm trying to tackle this by injection on H0 after introducing all terms. After injection and rewriting by H2, I end up with the following goal and I have no idea how to move forward.
1 subgoal (ID 174)
X : Type
x, y, z : X
l, j : list X
H2 : x = z
H3 : y :: l = j
H1 : j = z :: l
============================
z = y
It's clear that if I manage to add :: l to both sides of the equation, then I can complete with reflexivity, but what tactic would allow me to add :: l to both sides?
Best regards

From H3 and H1, you should be able to get a hypothesis on which you can use injection again to conclude.

Related

Agda: Failed to solve the following constraints: P x <= _X_53 (blocked on _X_53)

I'm writing Agda code as I read the HoTT book. I'm stuck on Lemma 2.3.9:
data _≡_ {X : Set} : X -> X -> Set where
refl : {x : X} -> x ≡ x
infix 4 _≡_
-- Lemma 2.1.2
_·_ : {A : Set} {x y z : A} -> x ≡ y -> y ≡ z -> x ≡ z
refl · refl = refl
-- Lemma 2.3.1
transp : {A : Set} {P : A -> Set} {x y : A} -> x ≡ y -> P x -> P y
transp refl f = f
lemma2'3'9 : {A : Set}{P : A -> Set}{x y z : A}{p : x ≡ y}{q : y ≡ z}{u : P x} ->
(transp q (transp p u)) ≡ (transp (p · q) u)
lemma2'3'9 {p = refl} {q = refl} = ?
Type-checking with Adga Emacs Mode gives me the following error:
?0 : transp refl (transp refl u) ≡ transp (refl · refl) u
_X_53 : Set [ at /home/user/prog/agda/sample.agda:12,38-39 ]
———— Errors ————————————————————————————————————————————————
Failed to solve the following constraints:
P x =< _X_53 (blocked on _X_53)
Questions
What is '_X_53', and why is it greater than or equal to (P x)?
How can I get rid of this error?
Note
I wrote a working example of Lemma 2.3.9 in Coq, so I'm assuming it's possible in Agda.
Inductive eq {X:Type} (x: X) : X -> Type :=
| refl : eq x x.
Notation "x = y" := (eq x y)
(at level 70, no associativity)
: type_scope.
Definition eqInd{A} (C: forall x y: A, x = y -> Type) (c: forall x: A, C x x (refl x)) (x y: A): forall p: x = y, C x y p :=
fun xy: x = y => match xy with
| refl _ => c x
end.
Definition dot'{A}{x y: A}: x = y -> forall z: A, y = z -> x = z :=
let D := fun x y: A => fun p: x = y => forall z: A, forall q: y = z, x = z in
let d: forall x, D x x (refl x) := let E: forall x z: A, forall q: x = z, Type := fun x z: A => fun q: x = z => x = z in
let e := fun x => refl x
in fun x z => fun q => eqInd E e x z q
in fun p: x = y => eqInd D d x y p.
(* Lemma 2.1.2 *)
Definition dot{A}{x y z: A}: x = y -> y = z -> x = z :=
fun p: x = y => dot' p z.
Definition id {A} := fun a: A => a.
(* Lemma 2.3.1 *)
Definition transp{A} {P: A -> Type} {x y: A}: x = y -> P x -> P y :=
fun p =>
let D := fun x y: A => fun p: x = y => P x -> P y in
let d: forall x, D x x (refl x) := fun x => id
in eqInd D d x y p.
Lemma L_2_3_9{A}{P: A -> Type}{x y z: A}{p: x = y}{q: y = z}{u: P x}:
transp q (transp p u) = transp (dot p q) u.
Proof.
unfold transp, dot, dot'.
rewrite <- q.
rewrite <- p.
reflexivity.
Qed.
_X_53 is a meta variable, i.e., an unknown part of a term. In order to figure out this unknown part of the term, Agda tries to resolve the meta variable. She does so by looking at the context the meta variable appears in, deriving constraints from this context, and determining possible candidate solutions for the meta variable that meet the constraints.
Among other things, Agda uses meta variables to implement implicit arguments. Each implicit argument is replaced with a meta variable, which Agda then tries to resolve within a context that includes the remaining arguments. This is how values for implicit arguments can be derived from the remaining arguments, for example.
Sometimes Agda is unable to figure out an implicit argument, even though one would think that she should be able to. I.e., Agda is unable to resolve the implicit argument's meta variable. This is when she needs a little assistance, i.e., we have to explicitly specify one or more of the implicit arguments. Which is what #gallais suggests in the comment.
=< compares two types. A =< B means that something of type A can be put where something of type B is required. So, if you have a function that takes a B, you can give it an A and it'll type check. I think that this is mostly used for Agda's sized types. In your case, I think, this can be read as type equality instead.
But back to the error message. Agda fails to find a solution for _X_53. The constraint that needs to be met is P x =< _X_53. If, in your case, =< is type equality, then why doesn't Agda simply set _X_53 to P x?
According to my very limited understanding, the reason is higher-order unification, which is a bit of a - to use a very technical term - capricious and finicky beast. _X_53 isn't the complete truth here. Meta variables can be functions and thus have arguments. According to the Agda debug log, the actual unification problem at hand is to unify _X_53 A P x x and P x. If I remember things correctly, then the two xs in the former are a problem. Take this with a grain of salt, though. I'm not a type theorist.
Long story short, sometimes Agda fails to figure out an implicit argument because unification fails and it's a bit hard to understand why exactly.
Finally, something related: The following article talks a bit about best practices for using implicit arguments: Inference in Agda
Update
I guess the two xs are a problem, because they keep Agda from finding a unique solution to the unification problem. Note that both, λ a b c d. P c and λ a b c d. P d would work for _X_53 in that both would make _X_53 A P x x reduce to P x.

Tactics: filter_exercise

(** **** Exercise: 3 stars, advanced (filter_exercise)
This one is a bit challenging. Pay attention to the form of your
induction hypothesis. *)
Theorem filter_exercise : forall (X : Type) (test : X -> bool)
(x : X) (l lf : list X),
filter test l = x :: lf ->
test x = true.
Proof.
intros X test x l lf. induction l as [| h t].
- simpl. intros H. discriminate H.
- simpl. destruct (test h) eqn:E.
+
Here is what I got so far:
X : Type
test : X -> bool
x, h : X
t, lf : list X
IHt : filter test t = x :: lf -> test x = true
E : test h = true
============================
h :: filter test t = x :: lf -> test x = true
And here I am stuck. What is so special in induction hypothesis that I must pay attention to?
Given the goal with an arrow in it,
h :: filter test t = x :: lf -> test x = true
^^
the natural next step is to intros the premise. The new premise
h :: filter test t = x :: lf
implies that the components of :: are respectively equal i.e. h = x and filter test t = lf, which can be extracted using inversion. The rest is trivial.

Coq - Proving condition about elements of sequence in Ssreflect

I have a goal that looks like this:
x \in [seq (f v j) | j <- enum 'I_m & P v j] -> 0 < x
In the above, f is a definition generating a solution of an inequality depending on v, j and P v j is a predicate restricting j to indices which satisfy another inequality.
I have already proven that Goal : P v j -> (f v j > 0), but how can I use this to prove that it holds for any x in the sequence? I have found just a few relevant lemmas like nthP which introduce sequence manipulation, which I'm very unfamiliar with.
Thanks in advance!
You need to use the mapP lemma (that characterizes membership wrt map):
Lemma U m (P : rel 'I_m) f v x (hp : forall j, P v j -> f v j > 0) :
x \in [seq f v j | j <- enum 'I_m & P v j] -> 0 < x.
Proof. by case/mapP=> [y]; rewrite mem_filter; case/andP=> /hp ? _ ->. Qed.

How to add to both sides of an equality in Coq

This seems like a really simple question, but I wasn't able to find anything useful.
I have the statement
n - x = n
and would like to prove
(n - x) + x = n + x
I haven't been able to find what theorem allows for this.
You should have a look at the rewrite tactic (and then maybe reflexivity).
EDIT: more info about rewrite:
You can rewrite H rewrite -> H to rewrite from left to right
You can rewrite <- H to rewrite from right to left
You can use the pattern tactic to only select specific instances of the goal to rewrite. For example, to only rewrite the second n, you can perform the following steps
pattern n at 2.
rewrite <- H.
In your case, the solution is much simpler.
Building on #gallais' suggestion on using f_equal. We start in the following state:
n : nat
x : nat
H : n - x = n
============================
n - x + x = n + x
(1) First variant via "forward" reasoning (where one applies theorems to hypotheses) using the f_equal lemma.
Check f_equal.
f_equal
: forall (A B : Type) (f : A -> B) (x y : A), x = y -> f x = f y
It needs the function f, so
apply f_equal with (f := fun t => t + x) in H.
This will give you:
H : n - x + x = n + x
This can be solved via apply H. or exact H. or assumption. or auto. ... or some other way which suits you the most.
(2) Or you can use "backward" reasoning (where one applies theorems to the goal).
There is also the f_equal2 lemma:
Check f_equal2.
f_equal2
: forall (A1 A2 B : Type) (f : A1 -> A2 -> B)
(x1 y1 : A1) (x2 y2 : A2),
x1 = y1 -> x2 = y2 -> f x1 x2 = f y1 y2
We just apply it to the goal, which results in two trivial subgoals.
apply f_equal2. assumption. reflexivity.
or just
apply f_equal2; trivial.
(3) There is also the more specialized lemma f_equal2_plus:
Check f_equal2_plus.
(*
f_equal2_plus
: forall x1 y1 x2 y2 : nat,
x1 = y1 -> x2 = y2 -> x1 + x2 = y1 + y2
*)
Using this lemma we are able to solve the goal with the following one-liner:
apply (f_equal2_plus _ _ _ _ H eq_refl).
There is a powerful search engine in Coq using patterns. You can try for example:
Search (_=_ -> _+_=_+_).

How to "flip" an equality proposition in Coq?

If I'm in Coq and I find myself in a situation with a goal like so:
==================
x = y -> y = x
Is there a tactic that can can take care of this in one swoop? As it is, I'm writing
intros H. rewrite -> H. reflexivity.
But it's a bit clunky.
To "flip" an equality H: x = y you can use symmetry in H. If you want to flip the goal, simply use symmetry.
If you're looking for a single tactic, then the easy tactic handles this one immediately:
Coq < Parameter x y : nat.
x is assumed
y is assumed
Coq < Lemma sym : x = y -> y = x.
1 subgoal
============================
x = y -> y = x
sym < easy.
No more subgoals.
If you take a look at the proof that the easy tactic found, the key part is an application of eq_sym:
sym < Show Proof.
(fun H : x = y => eq_sym H)
The heavier-weight auto tactic will also handle this goal in a single step. For a slightly lower-level proof that produces exactly the same proof term, you can use the symmetry tactic (which also automatically does the necessary intro for you):
sym < Restart.
1 subgoal
============================
x = y -> y = x
sym < symmetry.
1 subgoal
H : x = y
============================
x = y
sym < assumption.
No more subgoals.
sym < Show Proof.
(fun H : x = y => eq_sym H)