How to do "negative" match in Ltac? - coq

I want to apply a rule in a case when some hypothesis present, and another is not. How can I check for this condition?
For example:
Variable X Y : Prop.
Axiom A: X -> Y.
Axiom B: X -> Z.
Ltac more_detail :=
match goal with
|[H1:X,<not H2:Y>|-_] =>
let H' := fresh "DET" in assert Y as H'
by (apply A;assumption)
|[H1:X,<not H2:Z>|-_] =>
let H' := fresh "DET" in assert Z as H'
by (apply B;assumption)
end.
Such that, for this goal:
> Goal X->True. intros.
H:X
=====
True
more_detail. would introduce a second hypothesis DET:
H:X
DET:Y
DET0:Z
=====
True
And a successive invocation more_detail. would fail.
However more_detail. should always ensure, that both Y and Z are there, i.e. if only one of them present, it should run a rule for another:
Goal X->Y->True. intros.
H:X
H1:Y
=====
True
> more_detail.
H:X
H1:Y
DET:Z
=====
True
And:
> Goal X->Z->True. intros.
H:X
H0:Z
=====
True
> more_detail.
H:X
H0:Z
DET:Y
=====
True

This is a common Ltac pattern. You can use the fail tactic to avoid executing a branch when some condition matches:
Variable X Y Z : Prop.
Hypothesis A : X -> Y.
Hypothesis B : X -> Z.
Ltac does_not_have Z :=
match goal with
| _ : Z |- _ => fail 1
| |- _ => idtac
end.
Ltac more_detail :=
match goal with
| H : X |- _ =>
first [ does_not_have Y;
let DET := fresh "DET" in
assert (DET := A H)
| does_not_have Z;
let DET := fresh "DET" in
assert (DET := B H) ]
end.
Goal X -> True.
intros X. more_detail. more_detail.
(* This fails *)
more_detail.
Abort.
The does_not_have tactic acts as a negative match: it only succeeds if its argument is not present in the context. Here's how it works: if H : Z is present in the context, the first branch will match. Calling simply fail or fail 0 would cause that branch to fail, but would allow Ltac to try other branches of the same match. Using fail 1 causes the current branch and the entire match to fail. If H : Z is not present in the context, the first branch will never match, and Coq will skip it and try the second branch. Since this branch doesn't do anything, execution will proceed with whichever tactics come after the match.
In more_detail, the first tactical can be used to combine several invocations of does_not_have; since each branch of first will fail if the context contains the corresponding hypothesis, the construction as a whole will have the effect of your match with negative patterns.

Related

Beta expansion in coq: can I make a term into a function, abstracting over another given term?

I want to rewrite a term, as a function in a sort of beta expansion (inverse of beta reduction).
So, for example in the term a + 1 = RHS I would like to replace it as (fun x => x + 1) a = RHS. Obviously, the two terms are equal by betta reduction, but I can't figure out how to automate it.
The tactic pattern comes very close to what I want, except it only applies to a full goal, and I can't see how I would use it in a term inside an equality.
Similarly, I thought I could use the context holes. Here is my best attempt
Ltac betaExpansion term a:=
let T:= type of a in
match term with
context hole [a] =>
idtac hole;
let f:= fun x => context hole [x] in
remember ( fun x:T => f x ) as f'
end.
Goal forall a: nat, a + 1 = 0.
intros a.
match goal with
|- ?LHS = _ =>
betaExpansion LHS a (*Error: Variable f should be bound to a term but is bound to a tacvalue.*)
end.
This obviously fails, because f is a tacvalue when I really need a normal value. Can I somehow evaluate the expression to make it a value?
You should have a look at the pattern tactic. pattern t replaced all occurrences of t in the goal by a beta expanded variable.
You may also use the change ... with ... at tactic.
Goal forall (a:nat) , a+1 = 2* (a+1) - (a+1).
intro x; change (x+1) with ((fun z => z) (x+1)) at 1 3.
(*
x : nat
============================
(fun z : nat => z) (x + 1) = 2 * (x + 1) - (fun z : nat => z) (x + 1)
*)
Or, more automatically
Ltac betaexp term i :=
let x := fresh "x" in
let T := type of term in
change term with ((fun x : T => x) term) at i.
Goal forall (a:nat) , a+1 = a+1 .
intro x; betaexp (x+1) ltac:(1).

Why unable to perform case analysis in rather simple case

Well, the code
From mathcomp Require Import ssreflect ssrnat ssrbool eqtype.
Unset Strict Implicit.
Unset Printing Implicit Defensive.
Inductive nat_rels m n : bool -> bool -> bool -> Set :=
| CompareNatLt of m < n : nat_rels m n true false false
| CompareNatGt of m > n : nat_rels m n false true false
| CompareNatEq of m == n : nat_rels m n false false true.
Lemma natrelP m n : nat_rels m n (m < n) (m > n) (m == n).
Proof.
case (leqP m n); case (leqP n m).
move => H1 H2; move: (conj H1 H2) => {H1} {H2} /andP.
rewrite -eqn_leq => /eqP /ssrfun.esym /eqP H.
by rewrite H; constructor.
move => H. rewrite leq_eqVlt => /orP.
case.
Error is Error: Case analysis on sort Set is not allowed for inductive definition or.
The last goal before the case is
m, n : nat
H : m < n
============================
m == n \/ m < n -> nat_rels m n true false (m == n)
I've already used this construction (rewrite leq_eqVlt => /orP; case) in very similar situation and it just worked:
Lemma succ_max_distr n m : (maxn n m).+1 = maxn (n.+1) (m.+1).
Proof.
wlog : m n / m < n => H; last first.
rewrite max_l /maxn; last by exact: ltnW.
rewrite leqNgt.
have: m.+1 < n.+2 by apply: ltnW.
by move => ->.
case: (leqP n m); last by apply: H.
rewrite leq_eqVlt => /orP. case.
What is the difference between two cases?
and Why "Case analysis on sort Set is not allowed for inductive definition or"?
The difference between the two cases is the sort of the goal (Set vs Prop) when you execute the case command. In the first situation your goal is nat_rels ... and you declared that inductive in Set; in the second situation your goal is an equality that lands in Prop.
The reason why you can't do a case analysis on \/ when the goal is in Set (the first situation) is because \/ has been declared as Prop-valued. The main restriction associated to such a declaration is that you cannot use informative content from a Prop to build something in Set (or more generally Type), so that Prop is compatible with an erasure-semantic at extraction time.
In particular, doing a case analysis on \/ gives away the side of the \/ that is valid, and you can't be allowed to use that information for building some data in Set.
You have at least two solutions at your disposal:
You could move your family nat_rels from Set to Prop if that's compatible with what you want to do later on.
Or you could use the fact that the hypothesis that you want to branch on is decidable and find a way to produce some {m == n} + { m <n } out of m <= n; here the notation { _ } + { _ } is the Set-valued disjunction of proposition.

Match context pattern inside a tactic/tactic notation

I find a pattern inside my goal through a tactic.
Why does this fail:
Tactic Notation "my_context_match" uconstr(g) :=
match goal with
| |- context[g] => idtac
end.
my_context_match _.
While this succeeds?
match goal with
| |- context[_] => idtac
end.
Is there any way to write a my_context_match, such that I can pass incomplete patterns (with _ on them) and see if anything inside my goal matches the patter?
Support for uconstr is very patchy. I've just reported #9321. Note that even this fails:
Goal True.
let v := uconstr:(True) in
lazymatch constr:(v) with
| v => idtac
end. (* Error: No matching clauses for match. *)
As suggested by #eponier in a comment, you can use open_constr instead of uconstr. However, this will leave unresolved evars. Here is a tactic that will work, and will not leave unresolved evars:
Tactic Notation "my_context_match" uconstr(g) :=
(* [match] does not support [uconstr], cf COQBUG(https://github.com/coq/coq/issues/9321),
so we use [open_constr] *)
let g := open_constr:(g) in
(* turning [g] into an [open_constr] creates new evars, so we must
eventually unify them with the goal *)
let G := match goal with |- ?G => G end in
(* We now search for [g] in the goal, and then replace the matching
subterm with the [open_constr] [g], so that we can unify the
result with the goal [G] to resolve the new evars we created *)
match G with
| context cG[g]
=> let G' := context cG[g] in
unify G G'
end.
Goal True /\ True.
my_context_match _.
my_context_match (_ /\ _).
Fail my_context_match (_ \/ _).
my_context_match True.
exact (conj I I).
Qed.

Pattern-matching a hypothesis obtained from a pattern-match on goal

Consider the following development:
Definition done {T : Type} (x : T) := True.
Goal Test.
pose 1 as n.
assert (done n) by constructor.
Fail ltac:(
match goal with
| [ H : done _ |- _ ] => fail
| [ H : _ |- _ ] =>
match goal with
| [ _: done H |- _ ] => idtac "H == n"
| [ _: done n |- _ ] => idtac "H != n"; fail 2
end
end
).
Abort.
This prints H != n. I'm finding this very surprising, since the only hypothesis in scope are n and done n - and done n was already dispatched by the first branch of the top-level match.
How can I match done n without explicitly referring to n, as in the first branch of the second match?
I think you are confused by the way match works. The first branch of the matching is matched against every hypothesis, and if it always fails, the second branch is tested, and so on. In your example, the first branch matches hypothesis H, but the execution of the corresponding tactic (fail) fails, thus the second branch is tried that also matches hypothesis H.
Actually, the first branch of the outer match seems to do what you want (i.e. matches on a hypothesis of the form done _) so I don't really get the point of your inner match.
For instance,
match goal with
| [ H' : done _ |- _ ] => idtac H'
end.
prints H, showing that the right hypothesis is matched.
Note that you don't need the ltac:() expression to use Fail on a tactic. For example, Fail fail. works.

Computing with a finite subset of an infinite representation in Coq

I have a function Z -> Z -> whatever which I treat as a sort of a map from (Z, Z) to whatever, let's type it as FF.
With whatever being a simple sum constructible from nix or inj_whatever.
This map I initialize with some data, in the fashion of:
Definition i (x y : Z) (f : FF) : FF :=
fun x' y' =>
if andb (x =? x') (y =? y')
then inj_whatever
else f x y.
The =? represents boolean decidable equality on Z, from Coq's ZArith.
Now I would like to have equality on two of such FFs, I don't mind invoking functional_extensionality. What I would like to do now is to have Coq computationally decide equality of two FFs.
For example, suppose we do something along the lines of:
Definition empty : FF := fun x y => nix.
Now we add some arbitrary values to make foo and foo', those are equivalent under functional extensionality:
Definition foo := i 0 0 (i 0 (-42) (i 56 1 empty)).
Definition foo' := i 0 (-42) (i 56 1 (i 0 0 empty)).
What is a good way to automatically have Coq determine foo = foo'. Ltac level stuff? Actual terminating computation? Do I need domain restriction to a finite one?
The domain restriction is a bit of an intricate one. I manipulate the maps in a way f : FF -> FF, where f can extend the subset of Z x Z that the computation is defined on. As such, come to think of it, it can't be f : FF -> FF, but more like f : FF -> FF_1 where FF_1 is a subset of Z x Z that is extended by a small constant. As such, when one applies f n times, one ends up with FF_n which is equivalent to domain restriction of FF plus n * constant to the domain. So the function f slowly (by a constant factor) expands the domain FF is defined on.
As I said in the comment more specifics are needed in order to elaborate a satisfactory answer. See the below example --- intended for a step by step description --- on how to play with equality on restricted function ranges using mathcomp:
From mathcomp Require Import all_ssreflect all_algebra.
Set Implicit Arguments.
Unset Strict Implicit.
Unset Printing Implicit Defensive.
(* We need this in order for the computation to work. *)
Section AllU.
Variable n : nat.
(* Bounded and unbounded fun *)
Definition FFb := {ffun 'I_n -> nat}.
Implicit Type (f : FFb).
Lemma FFP1 f1 f2 : reflect (f1 = f2) [forall x : 'I_n, f1 x == f2 x].
Proof. exact/(equivP eqfunP)/ffunP. Qed.
Lemma FFP2 f1 f2 :
[forall x : 'I_n, f1 x == f2 x] = all [fun x => f1 x == f2 x] (enum 'I_n).
Proof.
by apply/eqfunP/allP=> [eqf x he|eqf x]; apply/eqP/eqf; rewrite ?enumT.
Qed.
Definition f_inj (f : nat -> nat) : FFb := [ffun x => f (val x)].
Lemma FFP3 (f1 f2 : nat -> nat) :
all [fun x => f1 x == f2 x] (iota 0 n) -> f_inj f1 = f_inj f2.
Proof.
move/allP=> /= hb; apply/FFP1; rewrite FFP2; apply/allP=> x hx /=.
by rewrite !ffunE; apply/hb; rewrite mem_iota ?ltn_ord.
Qed.
(* Exercise, derive bounded eq from f_inj f1 = f_inj f2 *)
End AllU.
The final lemma should indeed allow you reduce equality of functions to a computational, fully runnable Gallina function.
A simpler version of the above, and likely more useful to you is:
Lemma FFP n (f1 f2 : nat -> nat) :
[forall x : 'I_n, f1 x == f2 x] = all [pred x | f1 x == f2 x] (iota 0 n).
Proof.
apply/eqfunP/allP=> eqf x; last by apply/eqP/eqf; rewrite mem_iota /=.
by rewrite mem_iota; case/andP=> ? hx; have /= -> := eqf (Ordinal hx).
Qed.
But it depends on how you (absent) condition on range restriction is specified.
After your edit, I think I should add a note on the more general topic of map equality, indeed you can define a more specific type of maps other than A -> B and then build a decision procedure.
Most typical map types [including the ones in the stdlib] will work, as long as they support the operation of "binding retrieval", so you can reduce equality to the check of finitely-many bound values.
In fact, the maps in Coq's standard library do already provide you such computational equality function.
Ok, this is a rather brutal solution which does not attempt to avoid doing the same case distinctions multiple times but it's fully automated.
We start with a tactic which inspects whether two integers are equal (using Z.eqb) and translates the results to a proposition which omega can deal with.
Ltac inspect_eq y x :=
let p := fresh "p" in
let q := fresh "q" in
let H := fresh "H" in
assert (p := proj1 (Z.eqb_eq x y));
assert (q := proj1 (Z.eqb_neq x y));
destruct (Z.eqb x y) eqn: H;
[apply (fun p => p eq_refl) in p; clear q|
apply (fun p => p eq_refl) in q; clear p].
We can then write a function which fires the first occurence of i it can find. This may introduce contradictory assumptions in the context e.g. if a previous match has revealed x = 0 but we now call inspect x 0, the second branch will have both x = 0 and x <> 0 in the context. It will be automatically dismissed by omega.
Ltac fire_i x y := match goal with
| [ |- context[i ?x' ?y' _ _] ] =>
unfold i at 1; inspect_eq x x'; inspect_eq y y'; (omega || simpl)
end.
We can then put everything together: call functional extensionality twice, repeat fire_i until there's nothing else to inspect and conclude by reflexivity (indeed all the branches with contradictions have been dismissed automatically!).
Ltac eqFF :=
let x := fresh "x" in
let y := fresh "y" in
intros;
apply functional_extensionality; intro x;
apply functional_extensionality; intro y;
repeat fire_i x y; reflexivity.
We can see that it discharges your lemma without any issue:
Lemma foo_eq : foo = foo'.
Proof.
unfold foo, foo'; eqFF.
Qed.
Here is a self-contained gist with all the imports and definitions.