Coq - how to name an assumption inline - coq

I would like to have some name for P in P->Q. The rational is to state a theorem of type P->Q in which Q depends on P.
In the following example I need to replace the '???'.
I know I could open a Section and have (x<>0) as a Parameter with a name. Then after I close the section I get something to my thm2, but I would like to just state thm2 in one line.
(Ofcourse, the following example is somewhat silly. That's just an example to demonstrate my problem.)
Require Import QArith.
Definition my_inv(x:Q)(x<>0):Q.
intros.
exact (1/x).
Defined.
Thm thm1: forall x:Q, x>0 -> x<>0.
Proof.
...
Qed.
Theorem thm2: forall x:Q, x>0-> (my_inv x (thm1 x ???)) > 0.
Now, the ??? should refer Coq to the assumption that x>0. I couldn't find a way to refer to that assumption in the same line in which it is stated.

You can use forall to introduce named binders: forall (x:Q) (p : x>0), (...). Which gives us:
Require Import QArith.
Definition my_inv(x:Q) (p : x <> 0):Q.
intros.
exact (1/x).
Defined.
Theorem thm1 : forall x:Q, x>0 -> x<>0.
Proof.
Admitted.
Theorem thm2: forall (x:Q) (p : x>0), (my_inv x (thm1 x p)) > 0.

Related

Controlling unification order in Coq

I have a function whose second argument depends on its first argument, like this:
Definition is_nice (f : Formula) (pf : FProof f) : bool := true.
And I have a unification goal, like this
is_nice (some_formula ?u) (some_proof ?u) =^= is_nice f pf
.
which fails to unify when the unification starts from left to right,
but it would be unifiable when we first unify (some_proof ?u =^= pf),
infer the value for u during this unification, and then proceed to unify
some_formula ?u =^= f with the knowledge of u.
How do I make Coq solve such unification problem? I have the following ideas:
Change is_nice so that the order of parameters is different. However, I do not know how to achieve this because of the dependency between the parameters. We would need to somehow break this dependency...
Change is_nice so that it uses some canonical structure trickery to reorder the unification problems. There is some trick like that described in the extended version of Gonthier's 'How to make ad hoc proof automation less ad hoc' paper, but it does not seem to be directly applicable.
Somehow infer ?u even before the unification of that goal starts. But again, I am not sure how.
I may use UniCoq, but it is not a requirement.
As an example, consider the following piece of code:
Inductive Formula : Set :=
| f_atomic : nat -> Formula
| f_imp : Formula -> Formula -> Formula.
Inductive FProof : Formula -> Set :=
| P1 : forall (f1 f2 : Formula), FProof (f_imp f1 (f_imp f2 f1))
| MP : forall (f1 f2 : Formula), FProof f1 -> FProof (f_imp f1 f2) -> FProof f2
.
Definition is_nice (f : Formula) (pf : FProof f) : bool := true.
Lemma impl_5_is_nice': forall (n1 : nat), is_nice _ (P1 (f_atomic (n1 + 0)) (f_atomic 5)) = true.
Proof. intros. unfold is_nice. reflexivity. Qed.
Lemma impl_3_5_is_nice: is_nice _ (P1 (f_atomic 3) (f_atomic 5) ) = true.
Proof. intros.
Fail apply impl_5_is_nice'.
apply (impl_5_is_nice' 3).
Qed.
The types Formula and FProof represent formulas and proofs in a deeply-embedded logic. The proof script of Lemma impl_3_5_is_nice demostrates the problem: the first apply does not go through, because the unification of f_atomic (?n1 + 0) with f_atomic 3 fails. However, when we manually compare the goal and Lemma impl_5_is_nice', we can realize that n1 has to be 3, and so we can specialize the lemma.
Another solution would be to inspect the goal using match goal, but then the problem is that I have quite a lot of lemmas similar impl_5_is_nice', and the tactic that would do the inspection would need to understand each one of these lemmas. Ideally, this would be unified using type classes or canonical structures, but this is really a 'backup plan'.

Using a module's definition in Coq

The following code states that it defines finite sets in Coq with the axiom of extensionality:
(** A library for finite sets with extensional equality.
Author: Brian Aydemir. *)
Require Import FSets.
Require Import ListFacts.
Require Import Coq.Logic.ProofIrrelevance.
(* *********************************************************************** *)
(** * Interface *)
(** The following interface wraps the standard library's finite set
interface with an additional property: extensional equality. *)
Module Type S.
Declare Module E : UsualOrderedType.
Declare Module F : FSetInterface.S with Module E := E.
Parameter eq_if_Equal :
forall s s' : F.t, F.Equal s s' -> s = s'.
End S.
(* *********************************************************************** *)
(** * Implementation *)
(** For documentation purposes, we hide the implementation of a
functor implementing the above interface. We note only that the
implementation here assumes (as an axiom) that proof irrelevance
holds. *)
Module Make (X : UsualOrderedType) <: S with Module E := X.
(* begin hide *)
Module E := X.
Module F := FSetList.Make E.
Module OFacts := OrderedType.OrderedTypeFacts E.
Lemma eq_if_Equal :
forall s s' : F.t, F.Equal s s' -> s = s'.
Proof.
intros [s1 pf1] [s2 pf2] Eq.
assert (s1 = s2).
unfold F.MSet.Raw.t in *.
eapply Sort_InA_eq_ext; eauto.
intros; eapply E.lt_trans; eauto.
1 : {
apply F.MSet.Raw.isok_iff.
auto.
}
1 : {
apply F.MSet.Raw.isok_iff.
auto.
}
subst s1.
assert (pf1 = pf2).
apply proof_irrelevance.
subst pf2.
reflexivity.
Qed.
(* end hide *)
End Make.
How can I define a function with signature from finite sets to finite sets using this module?
You need to define a Module (call it M) that implements the UsualOrderedType module type for the type you want to make finite sets out of, and then build another Module with Make M which contains an implementation of finite sets for your type.
Module M <: UsualOrderedType.
...
End M.
Module foo := Make M.
Check foo.F.singleton.
Note that you need to declare the module type with <: instead of just :, otherwise you are hiding the fact that the module is defined for (in the example below) nat behind an opaque type t.
Say you want to make finite sets of nats:
(* Print the module type to see all the things you need to define. *)
Print Module Type UsualOrderedType.
Require Import PeanonNat.
Module NatOrdered <: UsualOrderedType . (* note the `<:` *)
Definition t:=nat.
Definition eq:=#eq nat.
Definition lt:=lt.
Definition eq_refl:=#eq_refl nat.
Definition eq_sym:=#eq_sym nat.
Definition eq_trans:=#eq_trans nat.
Definition lt_trans:=Nat.lt_trans.
(* I wrote Admitted where I didn't provide an implementation *)
Definition lt_not_eq : forall x y : t, lt x y -> ~ eq x y. Admitted.
Definition compare : forall x y : t, Compare lt eq x y. Admitted.
Definition eq_dec : forall x y : t, {eq x y} + {~ eq x y}. Admitted.
End NatOrdered.
Now you can create a module that uses this ordered type.
Module foo := Make NatOrdered.
Print foo.F. (* to see everything that is defined for the FSetList *)
Import foo. (* get F in our namespace so we can say F.t instead of foo.F.t, etc. *)
Now we can use our F module. The finite sets have type F.t and the elements have type F.elt which is coercible to nat since we know they come from NatOrdered.
Lets build a function that uses stuff from F.
Definition f: F.elt -> F.t.
intros x. apply (F.singleton x).
Defined.
Print F.
Goal F.cardinal (F.union (f 1) (f 2)) = 2.
compute.
Ok. That gets stuck halfway through the computation because I didn't implement compare above. I was lazy and just wrote Admitted. But you can do it! :-)

how to reflect with ssreflect: unable to unify ?x == ?y with "n = n0"

EDIT: I found it! I had forgotten about a coercion. Please ignore this :)
I am learning ssreflect and am stuck on how to proceed here. My proof state is the following:
n, n0 : nat
============================
n = n0 -> n == n0
At first, I tried move/eqP, because I thought that would "apply" eqP to n=n0, where "apply" means "get n==n0 out of the reflection given by eqP".
However, this attempt produced:
Illegal application (Non-functional construction):
The expression "eqP ?i" of type "?x = ?y"
cannot be applied to the term
"?y0" : "?T0"
I'm confused on what y0 and T0 are supposed to be.
I also tried
intros H. eapply (introT eqP) in H.
which produced the error
Unable to apply lemma of type "?x = ?y -> ?x == ?y"
on hypothesis of type "n = n0".
I tried to pass in explicit arguments n0 and n to eqP, just to see if it would work, with
pose proof (eqP n n0).
but this gave an error of
In environment
n, n0 : nat
H : n = n0
The term "n" has type "nat"
while it is expected to have type
"is_true (?x == ?y)".
So, it seems like eqP both wants and doesn't want explicit instantiations for ?x and ?y. I would really appreciate some conceptual explanation as to why move/eqP isn't behaving how I think it should, and what is actually going on with the types of eqP and (introT eqP).
If it is relevant, I am importing
From mathcomp Require Import ssrnat ssreflect ssrfun ssrbool eqtype.
from ssreflect.
Thank you.
Silly mistake! I had a coercion that I forgot about; my actual proof state was Nat n = Nat n0 -> n ==n0.

What is the idiomatic way to get `auto` to perform case analysis?

Inductive Foo : nat -> Type :=
| a : Foo 1.
(* ... *)
Goal forall m, Foo m -> m = 1.
Proof.
auto.
Fail Qed.
Is there a straightforward approach to do this?
You can use Hint Extern together with a tactic script that executes the case analysis. For example, this one will use destruct if the argument is a variable, and use inversion_clear otherwise:
Inductive Foo : nat -> Type :=
| a : Foo 1.
Hint Extern 1 => match goal with
| [ H : Foo ?m |- _ ]
=> first [ is_var m; destruct H | inversion_clear H ]
end.
Goal forall m, Foo m -> m = 1.
Proof.
auto.
Qed.
Via Programming Language Foundations, chapter Theory and Practice of Automation in Coq Proofs:
Note that proof search tactics never perform any rewriting step (tactics rewrite, subst), nor any case analysis on an arbitrary data structure or property (tactics destruct and inversion), nor any proof by induction (tactic induction). So, proof search is really intended to automate the final steps from the various branches of a proof. It is not able to discover the overall structure of a proof.
So there is really no way to do this; this goal should be solved manually, and then added to the hint database (Hint blah.).

Using `apply with` without giving names of parameters in Coq?

In using the Coq apply ... with tactic, the examples I have seen all involve explicitly giving the names of variables to instantiate. For example, given a theorem about the transitivity of equality.
Theorem trans_eq : forall (X:Type) (n m o : X),
n = m -> m = o -> n = o.
To apply it:
Example test: forall n m: nat,
n = 1 -> 1 = m -> n = m.
Proof.
intros n m.
apply trans_eq with (m := 1). Qed.
Note that in the last line apply trans_eq with (m := 1)., I have to remember that the name of the variable to instantiate is m, rather than o or n or some other names y.
To me, whether m n o or x y z are used in the original statement of the theorem shouldn't matter, because they are like dummy variables or formal parameters of a function. And sometimes I can't remember the specific names I used or somebody else put down in a different file when defining the theorem.
Is there a way by which I can refer to the variables e.g. by their position and use something like:
apply trans_eq with (#1 := 1)
in the above example?
By the way, I tried: apply trans_eq with (1 := 1). and got Error: No such binder.
Thanks.
You can specialize the lemma with the right arguments. The _ is used for all arguments that we don't want to specialize (because they can be inferred). The # is required to specialize implicit arguments.
Example test: forall n m: nat,
n = 1 -> 1 = m -> n = m.
Proof.
intros n m.
apply (#trans_eq _ _ 1).
Qed.
You can omit the binder names after with, so in your case do apply trans_eq with 1.
Example test: forall n m: nat,
n = 1 -> 1 = m -> n = m.
Proof.
intros n m.
apply trans_eq with 1; auto.
Qed.
I've changed your original example a little to conclude the proof.
Why this works
To understand why this works, check the manual under Bindings:
Tactics that take a term as an argument may also accept bindings to
instantiate some parameters of the term by name or position. The
general form of a term with bindings is termtac with bindings where
bindings can take two different forms:
bindings::= (ident | ​natural := term)+
| one_term+
What is shown in this example is the form one_term, which is described as follows:
in the case of apply, or of constructor and its variants, only instances for the dependent products that are not bound in the conclusion of termtac are required.
Which is why only one term needs to be supplied.