In my list of hypothesis, I have:
X : Type
l' : list X
n' : nat
H : S (length l') = S n'
My goal is length l' = n'.
So I tried f_equal in H. But I get the following error:
Syntax error: [tactic:ltac_use_default] expected after [tactic:tactic] (in [vernac:tactic_command]).
Am I wrong in thinking I should be able to apply f_equal to H in order to remove the S on both sides?
f_equal is about congruence of equality. It can be used to prove f x = f y from x = y. However, it cannot be used to deduce x = y from f x = f y because that is not true in general, only when f is injective.
Here it is a particular case as S is a constructor of an inductive type, and constructors are indeed injective. You could for instance use tactics like inversion H to obtain the desired equality.
Another solution involving f_equal would be to apply a function that removes the S like
Definition removeS n :=
match n with
| S m => m
| 0 => 0
end.
and then use
apply (f_equal removeS) in H.
f_equal tells you that if x = y, then f x = f y. In other words, when you have x = y and need f x = f y, you can use f_equal.
Your situation is the reverse. You have f x = f y and you need x = y, so you can't use f_equal.
If you think about your conclusion, it is only true when S is an injection. You need a different tactic.
Related
Sometimes when I'm proving something, I have a hypothesis P x y, and I know that I have a definition like R x := exists y, P x y. I would like to add the hypothesis R x, but I don't know how to do it. I tried to use pose proof (R x), but I got something of type Prop. Is there a way to do it?
If you have a hypothesis Hxy: P x y, you can write
assert (Rx: R x) by (exists y; assumption).
On the other direction, if you have a hypothesis Hx: R x, the tactic destruct Hx as [y Pxy] adds the witness yand the corresponding hypothesis to your context.
You can add a new argument to your lemma, and inside the proof, you can then extract a witness y' for your y. In ssreflect, you could write:
From mathcomp Require Import all_ssreflect.
Set Implicit Arguments.
Unset Strict Implicit.
Unset Printing Implicit Defensive.
Variable T : Type.
Variable P : T -> T -> Prop.
Definition R x := exists y, P x y.
Lemma foo x y (p : P x y) (r : R x) : false.
Proof.
move: r => [y' pxy'].
EDIT: You can also derive a proof of R x directly in the proof of foo, as follows:
Lemma foo x y (p : P x y) : false.
Proof.
have r : R x by exists y.
move: r => [y' pxy'].
or, more succinctly:
Lemma foo x y (p : P x y) : false.
Proof.
have [y' pxy'] : R x by exists y.
``
I am interested in how does dependent-typed theorem provers do substitution on the context. I find a thing called "intro ->" in Coq, as described in:
https://coq.inria.fr/refman/proof-engine/tactics.html#intropattern-rarrow-ex
In the example, it says the goal:
x, y, z : nat
H : x = y
y = z -> x = z
will become
x, z : nat
H : x = z
x = z
after an application of "intros ->".
I am not sure how is the step of substituting H:x = y into H:x = z be done, what is the rule of the logic of Coq is this step according to? It seems like a step of rewriting, and according to my current knowledge most of these rewriting are according to equalities, so the replacement from H:x = y into H:x = z should come from an equality like (H:x = y) = (H:x= z) ($\diamond$), but such an equality is ill-formed because, in principle, we require the LHS and RHS of an equality to have the same type, so the well-formedness of such equality ($\diamond$) depends on the assumption that y = z.
Could someone please help explaining how does "intro ->" work here? Do we need to get "equalities" like ($\diamond$) involved?
In Coq, rewriting on the context is a derived notion. The tactic intros -> in this case is roughly equivalent to the following tactics:
intros H'. rewrite H' in H. clear y H'.
The tactic rewrite H' in H., in turn, is roughly equivalent to
revert H. rewrite H'. intros H.
In words, to rewrite on the context, Coq first transfers all the relevant hypotheses to the goal, rewrites the goal and then brings the hypotheses back to the context.
Rewriting the goal uses the following elimination principle for the equality type:
forall [A : Type] [a : A] (P : A -> Prop), P a -> forall b : A, b = a -> P b
For rewriting H' above, we would have:
A := T
a := z
P := fun c => x = c -> x = z
b := y
so,
P b == x = y -> x = z
P a == x = z -> x = z
Indeed, ignoring the move steps to and from the context, Coq went from P b to P a when you performed the rewrite.
I'm new to Coq and am doing some exercises to get more familiar with it.
My understanding is that proving a proposition in Coq "really" is writing down a type in Gallina and then showing that it's inhabited using tactics to combine terms together in deterministic ways.
I'm wondering if there's a way to get a pretty-printed representation of the actual term, with all the tactics removed.
In the example below, an anonymous term of type plus_comm (x y : N) : plus x y = plus y x is ultimately produced... I think. What should I do if I want to look at it? In a certain sense, I'm curious what the tactics "desugar" to.
Here's the code in question, lifted essentially verbatim from a tutorial on YouTube https://www.youtube.com/watch?v=OaIn7g8BAIc.
Inductive N : Type :=
| O : N
| S : N -> N
.
Fixpoint plus (x y : N) : N :=
match x with
| O => y
| S x' => S (plus x' y)
end.
Lemma plus_0 (x : N) : plus x O = x.
Proof.
induction x.
- simpl. reflexivity.
- simpl. rewrite IHx. reflexivity.
Qed.
Lemma plus_S (x y : N) : plus x (S y) = S(plus x y).
Proof.
induction x.
- simpl. reflexivity.
- simpl. rewrite IHx. reflexivity.
Qed.
Lemma plus_comm (x y : N) : plus x y = plus y x.
Proof.
induction x.
- simpl. rewrite plus_0. reflexivity.
- simpl. rewrite IHx. rewrite plus_S. reflexivity.
Qed.
First of all, plus_comm is not a part of the type. You get a term named plus_comm of type forall x y : N, plus x y = plus y x. You can check it using the following command
Check plus_comm.
So, an alternative way of defining the plus_comm lemma is
Lemma plus_comm : forall x y : N, plus x y = plus y x.
As a side note: in this case you'll need to add intros x y. (or just intros.) after the Proof. part.
Tactics (and the means to glue them together) are a metalanguage called Ltac, because they are used to produce terms of another language, called Gallina, which is the specification language of Coq.
For example, forall x y : N, plus x y = plus y x is an instance of Gallina sentence as well as the body of the plus function. To obtain the term attached to plus_comm use the Print command:
Print plus_comm.
plus_comm =
fun x y : N =>
N_ind (fun x0 : N => plus x0 y = plus y x0)
(eq_ind_r (fun n : N => y = n) eq_refl (plus_0 y))
(fun (x0 : N) (IHx : plus x0 y = plus y x0) =>
eq_ind_r (fun n : N => S n = plus y (S x0))
(eq_ind_r (fun n : N => S (plus y x0) = n) eq_refl (plus_S y x0))
IHx) x
: forall x y : N, plus x y = plus y x
It is not an easy read, but with some experience you'll be able to understand it.
Incidentally, here is how we could have proved the lemma not using tactics:
Definition plus_comm : forall x y : N, plus x y = plus y x :=
fix IH (x y : N) :=
match x return plus x y = plus y x with
| O => eq_sym (plus_0 y)
| S x => eq_ind _ (fun p => S p = plus y (S x)) (eq_sym (plus_S y x)) _ (eq_sym (IH x y))
end.
To explain a few things: fix is the means of defining recursive functions, eq_sym is used to change x = y into y = x, and eq_ind corresponds to the rewrite tactic.
I am trying to prove that every group has an inverse function.
I have defined a group as follows:
Record Group:Type := {
G:Set;
mult:G->G->G;
e:G;
assoc:forall x y z:G, mult x (mult y z)=mult (mult x y) z;
neut:forall x:G, mult e x=x /\ mult x e=x;
inverse:forall x:G,exists y:G, mult x y = e
}.
I am aware that it is better to just replace the inverse axiom by inverse:forall x:G, {y: mult x y = e}., or even inverse:G->G. is_inverse:forall x:G, mult x (inverse x)=e., but I prefer my definition, mainly because I want the definition to be identical to the one given in a classroom.
So I have included a suitable version of the axiom of choice:
Axiom indefinite_description : forall (A : Type) (P: A->Prop), ex P -> sig P.
Axiom functional_choice : forall A B (R:A->B->Prop), (forall x, exists y, R x y) -> (exists f, forall x, R x (f x)).
Now I can prove my claim:
Lemma inv_func_exists(H:Group):exists inv_func:G H->G H, (forall x:G H, mult H x (inv_func(x))=e H).
generalize (inverse H).
apply functional_choice.
Qed.
Now that I have proved the existence, I would like to define an actual function. Here I feel that things start to go messy. The following definition creates an actual function, but seems to ugly and complicated:
Definition inv_func(H:Group):G H->G H.
pose (inv_func_exists H).
pose indefinite_description.
generalize e0 s.
trivial.
Qed.
Lastly, I would like to prove that inv_func is actually an inverse function:
Lemma inv_func_is_inverse:forall (H:Group), forall x:(G H), mult H x (inv_func H x)=e H.
I can see that Coq knows how inv_func was defined (e.g. Print inv_func), but I have no idea how to formally prove the lemma.
To conclude, I would appreciate suggestions as to how to prove the last lemma, and of better ways to define inv_func (but under my definition of group, without including the existence of such a function in the group definition. I believe the question could be relevant in many other situations when one can prove some correspondence for each element and needs to build this correspondence as a function).
There are quite a few questions inside your question. I'll try to address all of them:
First, there is no reason to prefer exists x, P + description over {x | P}, indeed, it seems weird you do so. {x | P} is perfectly valid as "there exists a x that can be computed" and I would rather use that definition with your groups.
Secondly, when creating definitions using tactics, you should end the proof with the command Defined. Using Qed will declare the definition "Opaque", which means it cannot be expanded, then preventing you proof.
The way to extract the witness from your definition is by using a projection. In this case, proj1_sig.
Using all the above we arrive at:
Definition inv_func' (H:Group) (x : G H) : G H.
Proof.
destruct (inverse H x) as [y _].
exact y.
Defined.
Definition inv_func (H:Group) (x : G H) : G H := proj1_sig (inverse H x).
Lemma inv_func_is_inverse (H:Group) (x: G H) : mult H x (inv_func H x) = e H.
Proof. now unfold inv_func; destruct (inverse H x). Qed.
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)