If I have the following:
H : some complicated expression = some other complicated expression
and I want to grab
u := some other complicated expression
without hardcoding it into my proof (i.e., using pose)
Is there a clean way to do this in LTac?
I am sure there are other ltac ways to do it, in my case I prefer to use SSReflect's contextual pattern language to do it. (You'll need to install the plugin or use Coq >= 8.7 which includes SSReflect):
(* ce_i = complicated expression i *)
Lemma example T (ce_1 ce_2 : T) (H : ce_1 = ce_2) : False.
set u := (X in _ = X) in H.
resulting goal:
T : Type
ce_1, ce_2 : T
u := ce_2 : T
H : ce_1 = u
============================
False
Usually you can refine the pattern more and more until you get a pretty stable match.
Note that this happens to be the first example of the section 8.3 "Contextual patterns" in the SSReflect manual.
Here is another version, which uses Ltac and its ability to pattern-match on types of terms:
Tactic Notation "assign" "rhs" "of" ident(H) "to" ident(u) "in" ident(H') :=
match type of H with _ = ?rhs => set (u := rhs) in H' end.
Tactic Notation "assign" "rhs" "of" ident(H) "to" ident(u) "in" "*" :=
match type of H with _ = ?rhs => set (u := rhs) in * end.
We can create more variants of the above (see e.g. here). Here is how to use it:
Lemma example {T} (ce1 ce2 ce3 : T) (H1 : ce1 = ce2) (H2 : ce2 = ce3) : ce1 = ce3.
Proof.
assign rhs of H1 to u in *.
Proof state:
u := ce2 : T
H1 : ce1 = u
H2 : u = ce3
============================
ce1 = ce3
One more time:
Undo.
assign rhs of H1 to u in H1.
Proof state:
u := ce2 : T
H1 : ce1 = u
H2 : ce2 = ce3
============================
ce1 = ce3
Related
Suppose I have such record type:
Record myRec : Type := {
myNat : nat;
myProof : myNat > 0
}.
How can I tell Coq to parse but not pretty-print (i.e., hide) the field myProof of a value of type myRec?
Can it be set while declaring the record type?
Or should it be done using the Notation command and the only printing syntax modifier?
The way I would do it is indeed with notations.
Record myRec : Type := myRecBuild {
myNat : nat ;
myProof : myNat > 0
}.
Notation "⟪ x ⟫" := (myRecBuild x _).
Now if you have a value of myRec it will only print the relevant part.
Lemma foo :
forall (x y : myRec),
x.(myNat) = y.(myNat) ->
x = x.
Proof.
intros [x hx] [y hy] e.
simpl in e. (* replaces myNat ⟪ x ⟫ with x *)
(* Goal is now ⟪ x ⟫ = ⟪ x ⟫, hiding hx and hy *)
Abort.
I would argue that you don't need the only printing option. In fact, this can be handy if you want to easily provide the relevant part and leave the rest to automation / tactics.
Lemma bar :
exists (x : myRec), x.(myNat) = 1.
Proof.
unshelve eexists ⟪ 1 ⟫.
- auto.
- reflexivity.
Qed.
This can become particularly handy when using Program or Equations.
Is there an easy way to rename an existential variable in a hypothesis?
Sometimes the variable names are confusing, because the same names are reused in unrelated hypotheses.
For example, I want to change H1 : exists p : nat, n0 = p * 2 to H1 : exists pminus1 : nat, n0 = pminus1 * 2.
Here is a piece of code that does it:
match goal with
an_h : #ex _ (?f) |- _ =>
let new_f := eval lazy beta in (fun pminus_one => f pminus_one) in
assert (my_h : #ex _ new_f) by exact an_h; clear an_h
end.
I'm currently trying to write a tactic that instantiates an existential quantifier using a term that can be generated easily (in this specific example, from tauto). My first attempt:
Ltac mytac :=
match goal with
| |- (exists (_ : ?X), _) => cut X;
[ let t := fresh "t" in intro t ; exists t; firstorder
| tauto ]
end.
This tactic will work on a simple problem like
Lemma obv1(X : Set) : exists f : X -> X, f = f.
mytac.
Qed.
However it won't work on a goal like
Lemma obv2(X : Set) : exists f : X -> X, forall x, f x = x.
mytac. (* goal becomes t x = x for arbitrary t,x *)
Here I would like to use this tactic, trusting that the f which tauto finds will be just fun x => x, thus subbing in the specific proof (which should be the identity function) and not just the generic t from my current script. How might I go about writing such a tactic?
It's much more common to create an existential variable and let some tactic (eauto or tauto for example) instantiate the variable by unification.
On the other hand, you can also literally use a tactic to provide the witness using tactics in terms:
Ltac mytac :=
match goal with
| [ |- exists (_:?T), _ ] =>
exists (ltac:(tauto) : T)
end.
Lemma obv1(X : Set) : exists f : X -> X, f = f.
Proof.
mytac.
auto.
Qed.
You need the type ascription : T so that the tactic-in-term ltac:(tauto) has the right goal (the type the exists expects).
I'm not sure this is all that useful (usually the type of the witness isn't very informative and you want to use the rest of the goal to choose it), but it's cool that you can do this nonetheless.
You can use eexists to introduce an existential variable, and let tauto instantiates it.
This give the following simple code.
Lemma obv2(X : Set) : exists f : X -> X, forall x, f x = x.
eexists; tauto.
Qed.
I'm trying to deal with canonical structures in ssreflect. There are 2 pieces of code that I took from here.
I will bring pieces for the bool and the option types.
Section BoolFinType.
Lemma bool_enumP : Finite.axiom [:: true; false]. Proof. by case. Qed.
Definition bool_finMixin := Eval hnf in FinMixin bool_enumP.
Canonical bool_finType := Eval hnf in FinType bool bool_finMixin.
Lemma card_bool : #|{: bool}| = 2. Proof. by rewrite cardT enumT unlock. Qed.
End BoolFinType.
Section OptionFinType.
Variable T : finType.
Notation some := (#Some _) (only parsing).
Local Notation enumF T := (Finite.enum T).
Definition option_enum := None :: map some (enumF T).
Lemma option_enumP : Finite.axiom option_enum.
Proof. by case => [x|]; rewrite /= count_map (count_pred0, enumP). Qed.
Definition option_finMixin := Eval hnf in FinMixin option_enumP.
Canonical option_finType := Eval hnf in FinType (option T) option_finMixin.
Lemma card_option : #|{: option T}| = #|T|.+1.
Proof. by rewrite !cardT !enumT {1}unlock /= !size_map. Qed.
End OptionFinType.
Now, suppose I have a function f from finType to Prop.
Variable T: finType.
Variable f: finType -> Prop.
Goal f T. (* Ok *)
Goal f bool. (* Not ok *)
Goal f (option T). (* Not ok *)
In the last two cases I get the following error:
The term "bool/option T" has type "Set/Type" while it is expected to have type "finType".
What am I doing wrong?
The instance search for canonical structures is a bit counter intuitive in these cases. Suppose that you have the following things:
a structure type S, and a type T;
a field proj : S -> T of S;
an element x : T; and
an element st : S that has been declared as canonical, such that proj st is defined as x.
In your example, we would have:
S = finType
T = Type
proj = Finite.sort
x = bool
st = bool_finType.
Canonical structure search is triggered only in the following case: when the type-checking algorithm is trying to find a value to validly fill in the hole in the equation proj _ = x. Then, it will use st : S to fill in this hole. In your example, you expected the algorithm to understand that bool can be used as finType, by transforming it into bool_finType, which is not quite what is described above.
To make Coq infer what you want, you need to use a unification problem of that form. For instance,
Variable P : finType -> Prop.
Check ((fun (T : finType) (x : T) => P T) _ true).
What is going on here? Remember that Finite.sort is declared as a coercion from finType to Type, so x : T really means x : Finite.sort T. When you apply the fun expression to true : bool, Coq has to find a solution for Finite.sort _ = bool. It then finds bool_finType, because it was declared as canonical. So the element of bool is what triggers the search, but not quite bool itself.
As ejgallego pointed out, this pattern is so common that ssreflect provides the special [finType of ...] syntax. But it might still be useful to understand what is going on under the hood.
I am using the Mathematical Components library and I am trying to prove this:
Lemma card_sub_ord (k : nat) (P : nat -> bool) :
#|[set i : 'I_k | P i]| <= k.
Proof.
set S := [set i : 'I_k | P i].
have H1 : S \subset 'I_k.
by apply: subset_predT.
have H2 : #|S| <= #|'I_k|.
by apply: subset_leq_card.
have H3 : k = #|'I_k|.
by rewrite card_ord.
(* Only goal left: #|S| <= k *)
rewrite H3 (* <--- this fails *)
Admitted.
The last rewrite fails with an error message:
Error: dependent type error in rewrite of (fun _pattern_value_ : nat => is_true (#|S| <= _pattern_value_)
Any idea on why the rewrite fails or an explanation of this error message?
The reason your rewrite fails is that k appears as a hidden parameter in S, thus by rewriting all the occurrences you make the goal ill-typed. You can check this by using Set Printing All.
by rewrite {5}H3.
will close your goal. Note that naming goals in H1...Hn style is not encouraged in mathcomp. Your indentation also doesn't follow math-comp style, and you may want to use exact: in place of by apply:.
Your proof can also be made shorter by using max_card:
by rewrite -{8}(card_ord k) max_card.
or
by rewrite -[k in _ <= k]card_ord max_card.
thou you could also prefer to use a more generic from that won't require specifying the indexes:
suff: #|[set i : 'I_k | P i]| <= #|'I_k| by rewrite card_ord.
exact: max_card.
Another way to avoid index tinkering is to rely on transitivity:
by rewrite (leq_trans (max_card _)) ?card_ord.
YMMV.