How to match a "match" expression? - coq

I am trying to write a rule for hypotheses, formulated with a help of match construction:
Goal forall x:nat, (match x with | 1 => 5 | _ => 10 end = 5 -> x = 1)%nat.
intros.
x : nat
H : match x with
| 0%nat => 10%nat
| 1%nat => 5%nat
| S (S _) => 10%nat
end = 5%nat
============================
x = 1%nat
How can I match such hypotheses ? The following straight forward method fails:
match goal with
|[H:match ?e with | ?a => ?x | ?b => ?y | ?c => ?z end = ?b] => idtac
end.
> Syntax error: 'end' expected after [branches] (in [match_constr]).

Pattern-matching on match statements is somewhat weird.
The first thing you should know is that, inside Coq, there's no such thing as a match on several variables or with deep matching: everything is translated in terms of simpler match statements. Thus, the term you wrote is actually syntax sugar for the following term:
match x with
| 0 => 10
| S x' =>
match x' with
| 0 => 5
| S x'' => 10
end
end
which is what Coq is hinting at when it prints your proof state. The problem is that this syntax sugar doesn't work on Ltac patterns: thus, when writing an Ltac pattern that mentions a match, you should always try to match it as if it were a one-level match.
The second problem is that you can't bind the pattern part of a match: something like
match goal with
| H : match ?x => _ | ?y => _ end = 5 |- _ => (* ... *)
end
doesn't really make sense in Ltac.
You have two choices for solving your problem, then:
Write down the match you expect with the exact list of constructors of your type on the pattern part, e.g.
match goal with
| H : match x with 0 => _ | S _ => _ end = 5 |- _ => (* ... *)
end
Use the special match (* ... *) with _ => _ end syntax, which matches any match whatsoever:
match goal with
| H : match x with _ => _ end = 5 |- _ => (* ... *)
end
Often, as in your case, one still wants to consider all branches of match, including deep ones. This idiom often comes in handy in that case:
repeat match goal with
| H : match ?x with _ => _ end = _ |- _ =>
destruct x; try solve [inversion H]
end.

Related

Coq - Assign expression to variable

First and foremost, I'm not yet very familiar with Coq lingo, so I will use terms like e.g. 'expression' and 'variable' loosely, but they are probably not the correct Coq terms.
I'm trying to prove the following subgoal of a Theorem.
1 goal
b : bag
v, b' : nat
b'' : natlist
B : b = b' :: b''
IHb'' : b = b'' -> count v (add v b'') = count v b'' + 1
______________________________________(1/1)
S match v =? b' with
| true => S (count v b'')
| false => count v b''
end = match v =? b' with
| true => S (count v b'')
| false => count v b''
end + 1
You can ignore S and + 1, I'm basically looking for a way to assign
match v =? b' with
| true => S (count v b'')
| false => count v b''
end
to a variable of type nat because it occurs on both sides of the equation.
How can I do this? Or do I need to go through destroying v and b' and proving all cases separately?
Here are two possibilities. There may well be better ones.
You can use set to give a name to a term. All the occurrences of that term are replaced by the variable.
set (x := match v =? b' with
| true => S (count v b'')
| false => count v b''
end).
Sometimes you need to hide the definition of the variable, and only remember it as an equality that you invoke on demand. For that, use remember.
You can match the goal against a pattern using the context form of match goal and give a name to whatever's inside that pattern.
match goal with |- context [S ?_x = ?_x + 1] => set (x := _x) end.
If this is your real goal and not a simplified example, it's a simple arithmetic statement and you can just call lia and let Coq figure it out.
Require Import Lia.
…
lia.
Besides Gilles's suggestions you can use the ssreflect set to achieve this, in at least two ways illustrated here:
Require Import Arith ssreflect.
Variables v b' b'' : nat.
Variable count : nat -> nat -> nat.
Goal
S match v =? b' with
| true => S (count v b'')
| false => count v b''
end
= match v =? b' with
| true => S (count v b'')
| false => count v b''
end + 1.
Proof.
set t := (X in S X = X + _).
Undo.
set t := match _ with true => _ | false => _ end.
Abort.
The latter one also works with the regular set but it needs brackets:
set (t := match _ with true => _ | false => _ end).

How do I check for convertibility in a tactic producing terms?

Suppose I have the following tactic to check if a term is the literal zero:
Ltac isZero x :=
match x with
| O => constr:true
| _ => constr:false
end.
Goal Set.
let isz := isZero O in pose isz.
(* adds true to the context *)
Now imagine that I want the tactic to accept a bit more; maybe any term that is convertible with zero. If this was a tactic acting on the goal, I would do
Ltac isZero x :=
match x with
| ?v => unify v 0; constr:true
| _ => constr:false
end.
but this fails for a tactic producing terms:
Error: Value is a term. Expected a tactic.
How can I check for convertibility in a tactic producing terms? In this specific example reducing x or computing it (let xx := eval compute in x) may work, but in more complex example the cost of computing could be prohibitive, especially as I would need to reduce the two terms of the comparison.
PS: For reference, the unsimplified issue is that I'm trying to efficiently lookup a key probably matching a value in an FMap built by sequences of calls to add, and the tactic looks like
Ltac find_key value :=
match fmap with
| add ?k value _ => constr:(Some k)
| add _ _ ?m => find_key value m
| _ => constr:None
end
With this implementation, if instead of value the map contains a term convertible to value but not syntactically equal to it, the tactic will incorrectly return None.
You can try to construct a term that triggers the conversion check; for instance:
Goal 2 + 2 = 4.
match goal with
| |- ?a = ?b =>
let e := constr:(eq_refl a : a = b) in
idtac "equal"
| |- _ => idtac "not equal"
end.
Normally, this prints "equal". However, if you replace 4 by, say, 3 in the goal above, the inner branch fails, printing "not equal".

Best way to instantiate nested existential statement in Coq

Suppose I have a nested existential statement H : exists ( a : A ) ( b : B ) ( c : C ) ... ( z : Z ), P a b c ... z in the context. What is the best way instantiate H and obtain a new hypothesis H' : P a b c ... z? Doing so by repeated inversion takes a long time and leaves all the unwanted intermediate steps like H0 : exists ( b : B ) ( c : C ) ... ( z : Z ), P a b c ... z.
My previous question is very similar to this one. Maybe there's some way to use pose proof or generalize to make this one work as well.
What you want to do is not called "instantiation." You can instantiate a universally quantified hypothesis and you can instantiate an existentially quantified conclusion, but not vice versa. I'm thinking the proper name is "introduction". You can introduce existential quantification in a hypothesis and you can introduce universal quantification in the conclusion. If it seems like you're "eliminating" instead, that's because, when proving something, you start at the bottom of a sequent calculus deriviation, and work your way backwards to the top.
Anyway, use the tactic firstorder. Also, use the command Set Firstorder Depth 0 to turn off proof search if you only want to simplify your goal.
If your goal has higher order elements though, you'll probably get an error message. In that case, you can use something like simplify.
Ltac simplify := repeat
match goal with
| h1 : False |- _ => destruct h1
| |- True => constructor
| h1 : True |- _ => clear h1
| |- ~ _ => intro
| h1 : ~ ?p1, h2 : ?p1 |- _ => destruct (h1 h2)
| h1 : _ \/ _ |- _ => destruct h1
| |- _ /\ _ => constructor
| h1 : _ /\ _ |- _ => destruct h1
| h1 : exists _, _ |- _ => destruct h1
| |- forall _, _ => intro
| _ : ?x1 = ?x2 |- _ => subst x2 || subst x1
end.

Proofs about constructors matched with _

Assume I have the following Set:
Inductive Many : Set :=
| aa: Many
| bb: Many
| cc: Many
(* | ... many more constructors *)
.
How can I proof in the _ match, that y<>aa?
match x with
| aa => true
| _ as y => (* how can i proof that y <> aa ? *)
Unfortunately, it does not seem possible to get such a proof without some more work in pure Gallina. What you would like to write is:
match x with
| aa => true
| y =>
let yNOTaa : y <> aa := fun yaa =>
eq_ind y (fun e => match e with aa => False | _ => True end) I aa yaa
in false
end
But that does not work quite well in Gallina, as it does not expand the wildcard into all possible cases, leaving y abstract in the eq_ind invocation. It does however work in tactic mode:
refine (
match x with
| aa => true
| y =>
let yNOTaa : y <> aa := fun yaa =>
eq_ind y (fun e => match e with aa => False | _ => True end) I aa yaa
in false
end
).
But it actually builds the expanded term with all the branches.
I just found out that there is a way to have the Vernacular build the same term that the refine tactic would build. To do so, you have to force a return annotation mentioning the discriminee, like so:
Definition foo (x : many) : bool :=
match x return (fun _ => bool) x with
| aa => true
| y =>
let yNOTaa : y <> aa := fun yaa : y = aa =>
#eq_ind many y (fun e => match e with aa => False | _ => True end) I aa yaa
in false
end
.
My guess is that the term elaboration differs whether the match is dependent or not...

Morphism - Setoid on non-convertible terms in Coq

I have the following function in Coq. Now I want to define an instance as below. In my case, equivalence [==] on type [nat] is defined but not on [StringMap.t String.t]. Please if you solve the Instace SC_Proper. Thanks.
Definition SC (u: nat) (zm: StringMap.t String.t):
StringMap.t String.t :=
match u with
| S p => match p with
| 2 => zm
| _ =>
match StringMap.find "S" zm with
| Some k => StringMap.empty
| _ => zm
end
end
| O => zm
end.
Instance SC_Proper
: Proper (equiv ==> equiv ==> equiv) SC.
Proof with o.
repeat red. intros u u' Hu zm1 zm2 Hzm.
Admitted.