Proper instance for "nested" matching - coq

I have a Lemma of the form FnEquivInner f g implies
outer t (bind t f) === outer t (bind t g) (full example posted below).
I wish to understand what kind of Proper instance I need to write for outer that lets me perform a rewrite in this case, to replace f with g in the call of outer.
In general, how does one write Proper instances where the patterns are non-trivial?
Require Import Setoid.
Require Import Morphisms.
Section PROPERINSTANCE.
Variable T: Type.
Variable inner: T -> (T -> T) -> T.
Variable outer : T -> (T -> T) -> T.
Variable bind: T -> (T -> T) -> (T -> T).
Variable equiv: T -> T -> Prop.
Infix "===" := equiv (at level 50).
Variable equivalence_equiv: Equivalence equiv.
(** Check that equivalence can be found by Coq *)
Lemma check_equiv_refl: forall (t: T), t === t.
reflexivity.
Qed.
Definition FnEquivInner (f g: T -> T): Prop := forall (t: T),
inner t f === inner t g.
(** This is a part of my theory *)
Variable FnEquivOuter:
forall (f g: T -> T)
(t t1: T)
(EQUIVINNER: FnEquivInner f g),
outer t1 (bind t f) === outer t1 (bind t g).
(** This is not a made up example to push coq, I have an actual theorem like this:
* https://github.com/bollu/vellvm/blob/master/src/coq/Memory.v#L923
inner = memEffect
outer = memD
bind = bindM
*)
Lemma useFnEquivOuter:
forall (f g: T -> T)
(t: T)
(EQUIVINNER: FnEquivInner f g),
outer t (bind t f) === outer t (bind t g).
Proof.
intros.
(** What should the Proper instance look like so that if I have a FnEquivInner witness,
I can `rewrite` using it? *)
setoid_rewrite EQUIVINNER.
Qed.
End PROPERINSTANCE.

If you Set Typeclasses Debug. and then try setoid_rewrite EQUIVINNER, and look for the lines that include looking for which come immediately before lines that mention proper_subrelation, you will see
Debug: 1.1-1: looking for (Proper (?R ==> FnEquivInner ==> ?r) bind) with backtracking
Debug: 1.1-1.2-2.1-1: looking for (Proper (?R --> FnEquivInner --> Basics.flip ?r) bind) with backtracking
Debug: 1.3-2.1-1: looking for (Proper (FnEquivInner --> Basics.flip ?r) (bind t)) with backtracking
This is basically a list of the Proper instances you can add to make typeclass resolution for setoid_rewrite go through.
For example, if I write
Global Instance: Proper (eq ==> FnEquivInner ==> eq) bind. Admitted.
then setoid_rewrite goes through.
I assume, though, that you will want something like
Global Instance bind_Proper : Proper (eq ==> FnEquivInner ==> FnEquivInner) bind. Admitted.
If I write this, then setoid_rewrite fails. Let's dig through the typeclass log again, this time looking for where resolution goes wrong after applying bind_Proper. Following the same rule as above, we see that the first line matching the above criterion is
Debug: 2.1-1: looking for (Proper (?R ==> FnEquivInner ==> ?r) outer) with backtracking
If I add
Global Instance outer_Proper: Proper (eq ==> FnEquivInner ==> equiv) outer. Admitted.
then setoid_rewrite again goes through.
Note that you get to fill in ?-prefixed relations (?R, ?r, etc) with any reflexive relation you'd like.
You may ask "why does this black magic work?" The answer is that proper_subrelation is where Coq generally goes wrong. It means, roughly, "I have nothing in my database matching what you're looking for; let me blindly try everything in my database and see if any of them are maybe close enough to work."* (Where "close enough" means "is a subrelation of".) So we look for the places where Coq goes wrong in its search, and we look immediately before that to see what it was looking at. (There are often many steps of partial_application_tactic, which strips arguments off of functions; this is why you only need one Proper instance for bind, rather than one for bind t and another for fun t => bind t f.)
*This is actually useful, sometimes, because eq is a subrelation of every reflexive relation, and so you can get away with not entering relations when you can just use eq. But most of the time, proper_subrelation is not what you want.

Related

Rewrite with variable from inner scope?

Is it possible to rewrite something that uses variables from another scope,
such as a function call that uses a variable from a match, fun, or fix ?
For example,
Theorem foo (f : nat -> nat) (rw : forall x, f x = 5) x : match x with
| 0 => 5
| S a => f a
end = 5.
rewrite rw.
(* Error: Found no subterm matching "f ?M160" in the current goal. *)
destruct x; try rewrite rw; apply eq_refl.
Qed.
So, the theorem is provable, but trying to rewrite rw initially fails,
seemingly because a is in another scope. But, the rewrite applies
unconditionally, so it seems like it should apply there too.
Of course, this is a toy example. Assume that, in a real-world scenario,
getting into the scope is a bit more complicated than just a destruct.
From Rewrite tactic fails to find term occurrence within pattern matching it looks like this isn't possible in Coq. So, is it just that it isn't implemented, or does it cause contradictions or allow for bad behavior like smuggling variables out of their scope?
What about harder cases like fix ?
You have likely heard that the Logic of Coq is not powerful enough to derive functional exensionality.
Now what you prove above is a point wise equality, that is you prove that an applied function has a certain value.
A rewrite in the match would correspond to a proof that two unapplied functions are equal: The original match statement (which is a function of x) and the rewritten match statement (also a function of x). This means you would prove a more general result as intermediate step - and Coq's logic is not able to prove this more general result.
Functional extensionality is compatible with Coq's logic, though. So one can add it as axiom and then one can add some setoid instances which allow to setoid_rewrite under binders. But afaik this does not work for rewrites under matches either.
It would also be possible to detect that in the end you prove a point wise equality, do the destruct behind the scenes, do the point wise rewrite and put things together again, but this would work only in rather trivial cases, which I guess are not sufficiently interesting to implement this.
To close here is an example of proving functional extensionality (suggested by the edit by #scubed) with a rewrite under binders - which is enabled by a global type class instance which is itself based on the functional extensionality axiom. So this proves an axiom with itself and it doesn't help for your match case, but it shows that rewriting under binders is equivalent to functional extensionality.
Require Import PeanoNat.
Require Import Setoid.
Require Import Morphisms.
Definition fun1 (x : nat) := x + 1.
Definition fun2 (x : nat) := 1 + x.
Example Fun1EqFun2: fun1 = fun2.
Proof.
unfold fun1, fun2.
Fail setoid_rewrite Nat.add_comm.
Abort.
Require Import FunctionalExtensionality.
(* This is derived from the error message of setoid_rewrite above *)
Global Instance:
forall (A B : Type),
Proper
(#pointwise_relation A B eq ==>
#pointwise_relation A B eq ==> Basics.flip Basics.impl) eq.
Proof.
(* See what all this Setoid stuff actually means ... *)
unfold Proper, pointwise_relation, respectful, Basics.flip, Basics.impl.
intros A B f g fgeq f' g' fg'eq gg'eq.
apply functional_extensionality.
intros x.
rewrite fgeq, fg'eq, gg'eq.
reflexivity.
Qed.
Theorem eq_arg (A B : Type) (f : A -> B) : f = (fun x => f x). reflexivity. Qed.
Lemma functional_extensionality' :
forall (A B : Type), forall (f g : A -> B),
(forall a : A, (f a) = (g a)) -> f = g.
Proof.
intros.
setoid_rewrite eq_arg at 2.
setoid_rewrite H.
reflexivity.
Qed.

What causes `fix` to appear after unfolding?

After unfolding everything I can in an attempt to get rid of symbols I don't want in my induction hypothesis, I am left with:
X: Type
test: X -> bool
x: X
l: list X
IHl: (fix existsb
(X : Type) (test : X -> bool)
(l : list X) {struct l} : bool :=
fold orb (map test l) false) X test l =
negb
((fix forallb
(X : Type) (test : X -> bool)
(l : list X) {struct l} : bool :=
fold andb (map test l) true) X
(fun x : X => negb (test x)) l)
The two fixpoints which wind up embedded should be evaluated as far as I can see since I have already intros'ed their parameters; and if they simply were evaluated with their parameters, my IHl would be perfect.
I am not clear on why these won't evaluate in this case. As the example is from logical foundations, I haven't provided more of my solution hoping that it's enough to ask what tactic can I apply to IHl to cause coq to actually do the rewrite with the arguments that I am looking for.
I guess I don't really understand but it seems my case is fundamentally similar to this question:
Why cannot evaluate a fix-defined expression with an abstract value in Coq?
It seems that the workaround is to destruct l in order to ensure that the cases all start with a constructor, which then eliminates the fixpoints in two redundant cases that make the proof more or less immediate from there.
A post to enlighten me better about why there is no way to get one level of substitution here would be great, as I can't see any reason not to have a tactic that will apply in this circumstance.

SsrReflect and setoid rewriting

I can't use Ssreflect's rewrite with setoids. Although I don't think this information is relevant to solve the problem, I'm using this formulation of category theory in coq: https://github.com/jwiegley/category-theory.
As far as I know, Ssreflect's rewriting can use user-defined equivalence relations if a suitable RewriteRelation Typeclass instance can be resolved.
Context { x y : obj[C]}.
About RewriteRelation.
(* ∀ A : Type, crelation A → Prop *)
Instance equivrw : (#RewriteRelation (x ~> y) (#equiv (x ~> y) (homset x y))) := {}. (* defined and correctly type-checked *)
About equivrw.
(* RewriteRelation equiv (coq omits implicit arguments) *)
Lemma test_rwrel (a b c : x ~> y) : (#equiv (x ~> y) (homset x y) a b) -> (#equiv (x ~> y) (homset x y) b c) -> (#equiv (x ~> y) (homset x y) a c).
Proof.
move => ->.
(* Fails: not a rewritable relation: (a ≈ b) in rule __top_assumption_ *)
Using the default rewrite tactic instead works (even without manually declaring the instance, because something similar is already declared in the library).
Something funny:
Instance equivrw : (#RewriteRelation False equiv) := {}.
Lemma test_rwrel (a b c : False) : (equiv a b) -> (equiv b c) -> (equiv a c).
Proof.
move => ->.
by [].
Qed.
This works fine.
Why doesn't SSReflect use the RewriteRelation instance I have manually declared to rewrite by user-defined equivalence?
Thanks in advance.
EDIT:
I have figured out why Ssreflect doesn't see my relation. Apparently, you can add relations to be used with Ssreflect's rewrite only with Add Parametric Relation which is documented in the manual, and RewriteRelation instances don't change anything. I have tried to create a fake relation using axioms and adding it with Add Parametric Relation and rewriting works correctly. But now I'm again in trouble. The relation that I want to be able to use has type crelation (x ~> y) (which is (x ~> y) -> (x ~> y) -> Type), but to use Add Parametric Relation I need a term with type relation (x ~> y) (which is (x ~> y) -> (x ~> y) -> Prop. Why two different kinds of relations (relation and crelation) have been defined in the standard library?
How can I convert a crelation to a relation without getting universe inconsistency errors?
And I still can't understand why the above example with False works.
It's not sufficient nor necessary to declare a relation as a RewriteRelation. You must prove properties that ensure that the rewriting is logically valid, the most common one being transitivity (but you often want also reflexivity, and even symmetry as well).
As you have noticed already, the setoid rewriting plugin is actually made of two twin systems, one for relations in Prop, and one for relations in Type (whose module names are prefixed with C). You generally use just one or the other, depending on the sort of your relations.
I'm not sure whether SSReflect changes things, but here is an example usage of setoid rewriting without it:
Require Setoid. to activate the plugin.
Require Import CEquivalence. if you use Type relations, or Require Import Equivalence. if you use Prop relations.
Implement instances for properties of equivalence relations (any of Reflexive, Symmetric, Transitive, or Equivalence for all 3).
You may also have to prove Proper lemmas if the terms you are rewriting are not at the toplevel of the goal.
Note that at step 3, if you do not/cannot prove all three properties, then you will not be allowed to rewrite in all directions.
To the best of my knowledge, commands such as Add Parametric Relation you may find in the documentation are just boilerplate that desugar to these instances. But in my opinion as a user, they add an unnecessary layer of indirection; declaring the instances directly makes things more understandable (especially if you're already familiar with type classes).
Require Setoid. (* 1 *)
Require Import CMorphisms. (* 2 *)
Axiom obj : Type.
Axiom equiv : obj -> obj -> Type.
Axiom cat : forall a b c, equiv a b -> equiv b c -> equiv a c.
(* 3 *)
Instance Transitive_equiv : Transitive equiv.
Proof.
exact cat.
Qed.
(* Example usage *)
Goal forall a b c,
equiv a b -> equiv b c -> equiv a c.
Proof.
intros a b c H1 H2.
rewrite H1.
(* or,
rewrite H2
*)

How to turn an single unification variable into a goal, during proof

I want to construct an existential variable interactively. I can't use Grab Existential Variables because I need to fill the existential before I complete the goal.
Minimal exmaple
Here is a minimal example (since it's simple, it has other solutions, but it illustrates my question)
Context (A:Type).
Parameter P Q: A -> Prop.
Definition filter: forall {a}, P a -> A:= fun a Pa=> a.
Lemma my_lemma:
forall a b, Q b -> (Q b -> P a) ->
exists a (H: P a), P (filter H).
Proof.
intros ?? H H0.
do 2 eexists.
At this point, there are two solutions that don't answer my questions: (1) I could run (eauto) and then do Grab Existential Variables, but suppose that eauto doesn't succeed until I instantiate the unification variable; (2) I could just pass the proof term explicitly with instantiate(1:= H0 H) (or even instantiate(1:= ltac:(eauto))), but assume that the proof of the xistential was tedious and we wished to do it interactively.
What else can we do? We can try to use cut or assert, like so:
match goal with
|[|- P (filter ?x)] =>
match type of x with
| ?T => assert (HH:T) by eauto
end
end.
But HH is not in the context of the unification variable, so it can't be instantiated.
instantiate(1:=HH). (* Instance is not well-typed in the environment of ?H. *)
As far as I can tell, the only way to solve this is to use Show Existentials, see the type of the variable copy it by hand, roll back the proof to before the unification was introduced and construct the variable there. In the example it looks like this:
Lemma my_lemma:
forall a b, Q b -> (Q b -> P a) ->
exists a (H: P a), P (filter H).
Proof.
intros ?? H H0.
do 2 eexists.
Show Existentials.
Restart. (* This command restores the proof editing process to the original goal. *)
intros ?? H H0.
assert (HH:P a) by eauto.
eexists; exists HH.
auto.
Qed.
Obviously, I would like to avoid this workflow. So, anyway to turn the existential variables into subgoals?
Your best bet is probably to avoid creating the existential variable as an evar in the first place. You don't have to construct the variable by hand to do this; if you can identify where it's created, you can wrap the offending tactic with unshelve t, which turns all evars created by t into goals. Where this might be difficult is if the relevant tactic is deep inside some automation and difficult to identify or change.

can I force Coq to print parentheses?

I'm new to Coq, working on set-theoretic proof writing.
I realized that parentheses are omitted, and it makes difficult for me to read the formula. For example,
1 subgoal
A, B : {set T}
H : B \subset A
______________________________________(1/1)
A :\: A :|: A :&: B = B
But I would like Coq to print (A :\: A) :|: (A :&: B) = B. This output above is gained by the foloowing code.
Require Import ssreflect ssrbool ssrnat fintype finset.
Theorem a_a_b__b' (A B : {set T}) : B \subset A -> (A :\: (A :\: B)) = B.
Proof.
move=> H.
rewrite setDDr.
To my surprise, if I see the original coding of setDDr in finset.v, it has parentheses as follows
Lemma setDDr A B C : A :\: (B :\: C) = (A :\: B) :|: (A :&: C).
Proof. by rewrite !setDE setCI setIUr setCK. Qed.
So I'm wondering why parentheses disappear and how to force Coq to print parentheses explicitly in CoqIde.
You can turn off all notations with this command:
Unset Printing Notations.
Printing Notations is a flag, Unset turns it off. You can find more information about notation from here: https://coq.inria.fr/refman/user-extensions/syntax-extensions.html#syntax-extensions-and-interpretation-scopes.
For example,
(n + m) * 0 = n * 0 + m * 0
would be printed as
eq (Nat.mul (Nat.add n m) O) (Nat.add (Nat.mul n O) (Nat.mul m O))
I know, it's not a really good solution.
In the latest versions of Coq Set Printing Parentheses should work.
I am not aware of a mechanism to do what you propose (but it could well exist, Coq notation support is rich and complex).
Coq is supposed to insert parenthesis based on the precedence of the operators, that means that you'll have to redefine the precedence of :|: to achieve what you want. This is not possible to do easily, and most people won't like it. The current precedence of :|: is what is expected by mathematicians.
A possible workaround is to define a different, local notation for you own use:
From mathcomp
Require Import ssreflect ssrbool eqtype ssrnat seq choice fintype finset.
Section U.
Variable (T: finType).
Local Notation "A :||: B" := (#setU T A B) (at level 48, left associativity).
Theorem a_a_b__b' (A B : {set T}) : B \subset A -> (A :\: (A :\: B)) = B.
Proof.
move=> H; rewrite setDDr.
But I'd suggest you use this only temporarily, try to get used to the current precedence rules, as you'll have to read other people proofs, and they'll have to read yours, so deviating from standard practice has a non trivial cost.