How to set implicit parameters for constructor - coq

Playing with nostutter excersizes I found another odd behaviour. Here is the code:
Inductive nostutter {X:Type} : list X -> Prop :=
| ns_nil : nostutter []
| ns_one : forall (x : X), nostutter [x]
| ns_cons: forall (x : X) (h : X) (t : list X), nostutter (h::t) -> x <> h -> nostutter (x::h::t).
Example test_nostutter_manual: not (nostutter [3;1;1;4]).
Proof.
intro.
inversion_clear H.
inversion_clear H0.
unfold not in H2.
(* We are here *)
specialize (H2 eq_refl).
apply H2.
Qed.
Status after unfold is this:
1 subgoal (ID 229)
H1 : 3 <> 1
H : nostutter [1; 4]
H2 : 1 = 1 -> False
============================
False
When I run specialize (H2 eq_refl). inside IndProp.v that loads other Logical foundations files, it works. Somehow it understands that it needs to put "1" as a parameter. Header of IndProp.v is this:
Set Warnings "-notation-overridden,-parsing".
From LF Require Export Logic.
Require Import String.
Require Coq.omega.Omega.
When I move the code into another file "nostutter.v", this same code gives an expected error:
The term "eq_refl" has type "RelationClasses.Reflexive Logic.eq" while
it is expected to have type "1 = 1".
Header of nostutter.v:
Set Warnings "-notation-overridden,-parsing".
Require Import List.
Import ListNotations.
Require Import PeanoNat.
Import Nat.
Local Open Scope nat_scope.
I have to explicitly add a parameter to eq_refl: specialize (H2 (eq_refl 1)).
I think it's not related specifically to specialize. What is it? How to fix?

The problem is importing PeanoNat.Nat.
When you import PeanoNat, the module type Nat comes into scope, so importing Nat brings in PeanoNat.Nat. If you meant to import Coq.Init.Nat, you'll either have to import it before importing PeanoNat, or import it with Import Init.Nat..
Why does importing PeanoNat.Nat cause trouble in this case?
Arith/PeanoNat.v (static link) contains the module1 Nat. Inside that module, we find2 the unusual looking line
Include NBasicProp <+ UsualMinMaxLogicalProperties <+ UsualMinMaxDecProperties.
All this means is that each of NBasicProp, UsualMinMaxLogicalProperties and UsualMinMaxDecProperties are included, which in turn means that everything defined in those modules is included in the current module. Separating this line out into three Include commands, we can figure out which one is redefining eq_refl. It turns out to be NBasicProp, which is found in this file (static link). We're not quite there yet: the redefinition of eq_refl isn't here. However, we see the definition of NBasicProp in terms of NMaxMinProp.
This leads us to NMaxMin.v, which in turn leads us to NSub.v, which leads us to NMulOrder.v, which leads us to NAddOrder.v, which leads us to NOrder.v, which leads us to NAdd.v, which leads us to NBase.v, ...
I'll cut to the chase here. Eventually we end up in Structures/Equality.v (static link) with the module BackportEq which finally gives us our redefinition of eq_refl.
Module BackportEq (E:Eq)(F:IsEq E) <: IsEqOrig E.
Definition eq_refl := #Equivalence_Reflexive _ _ F.eq_equiv.
Definition eq_sym := #Equivalence_Symmetric _ _ F.eq_equiv.
Definition eq_trans := #Equivalence_Transitive _ _ F.eq_equiv.
End BackportEq.
The way this is defined, eq_refl (without any arguments) has type Reflexive eq, where Reflexive is the class
Class Reflexive (R : relation A) :=
reflexivity : forall x : A, R x x.
(found in Classes/RelationClasses.v)
So that means that we'll always need to supply an extra argument to get something of type x = x. There are no implicit arguments defined here.
Why is importing modules like PeanoNat.Nat generally a bad idea?
If the wild goose chase above wasn't convincing enough, let me just say that modules like this one, which extend and import other modules and module types, are often not meant to be imported. They often have short names (like N, Z or Nat) so any theorem you want to use from them is easily accessible without having to type out a long name. They usually have a long chain of imports and thus contain a vast number of items. If you import them, now that vast number of items is polluting your global namespace. As you saw with eq_refl, that can cause unexpected behavior with what you thought was a familiar constant.
Most of the modules encountered in this adventure are of the "module type/functor" variety. Suffice to say, they're difficult to understand fully, but a short guide can be found here.
My sleuthing was done by opening files in CoqIDE and running the command Locate eq_refl. (or better yet, ctrl+shift+L) after anything that might import from elsewhere. Locate can also tell you where a constant was imported from. I wish there were an easier way to see the path of imports in module types, but I don't think so. You could guess that we'd end up in Coq.Classes.RelationClasses based on the type of the overwritten eq_refl, but that isn't as precise.

Related

Understanding \is a unit in ssreflect

I'm really annoyed by the following goal:
a%:R \is a unit
where a is a nat. The only lemma that seems to help is unitrE, but then it seems impossible to simplify further. This goal should be solvable. Can someone explain how to coerce this to a field type so I can use unitfE which I can easily work with.
you can only use unitfE if the structure you work with is a field. Otherwise you need to deal with the characteristic ([char R]) of your ring.
What is your structure?
If you assume that a is non-zero (which makes sense, to have an inverse), then you can do this:
From mathcomp Require Import all_ssreflect all_algebra.
Set Implicit Arguments.
Unset Strict Implicit.
Unset Printing Implicit Defensive.
Open Scope ring_scope.
Import GRing.Theory.
Variable (R : numFieldType).
Variable (a : nat).
Definition a' : R := a%:R.
Hypothesis nea'0 : a' != 0.
Lemma a'unit : a' \is a GRing.unit.
Proof. by rewrite unitfE nea'0. Qed.

Introducing a new assumption/hypothesis by adding it as subgoal

Let's suppose that I have the following proof state:
1 subgoal
P, Q : Prop
H : P -> Q
-------------------(1/1)
Q
and I know a way to prove P, how may I add an "inline proof" of it so that I can have it in my list of assumptions?
Another thing you can use is the pose proof tactic. This lets you actually supply the proof term and name it (pose proof (foo bar baz) as qux basically translates into let qux := foo bar baz in ... in the generated proof).
This can be neat for things like specialized versions of a lemma that you're going to use in multiple branches.
The tactic assert does exactly that.
Using assert (<proposition>) breaks your objective into two subgoals, in the first you have to prove "<proposition>" with your current assumptions, and the second has your original goal as the objective, but with "<proposition>" added to the list of assumptions.
You may also specify its name with assert (<proposition>) as <name> or assert (<name>: <proposition>).
Another option is to use cut (<proposition>).
It also creates two objectives, one of the form <proposition> -> <your objective> (then you can get your hypothesis by using intros, or intros <name> if you want to specify its name), and another one in which you have to prove "<prososition>" with your current assumptions.
If you use the SSRreflect proof language, you can use the have proof_of_P: P. <write your proof here> construct.

Coq for HoTT: proving || P-> X || -> (P-> ||X||)

I need to prove in Coq that for any type X and any proposition P (though I think it should work even if P is a type) there exists
trunc_impl: || P-> X || -> (P-> ||X||)
where ||_|| is the symbol used in HoTT book to indicate propositional truncation.
I demonstrated the statement in type theory: one gets the thesis by using the induction principle of propositional truncation, assuming from an H : || P-> X || and a p: P that H=|H'|, with H': P->X , and then defines trunc_impl(p):= |H'(p)|.
(|-| indicates the constructor for the trucation, i.e. |_| : A -> ||A||).
By the way, I cannot write it in Coq!
Any help would be very appreciated.
I am using the HoTT library available on GitHub.
You need to Require Import Basics. since coq doesn't know Trunc.TruncType can be coerced to Type otherwise. The tactics that you want to be aware of are apply Trunc_ind which will act on a goal like forall (x : Tr _ _), _.
intros x y and revert x will come in handy to get the goal into a form you want to apply trunc_ind to .
You also have the (custom) tactic strip_truncations which will search the context for any terms that are wrapped up with a truncation and try to do induction on them to remove them. This requires the goal to be as truncated but that shouldn't be a problem here.
Finally, the constructor for truncations is tr, so you can use apply there.

Coq power operator "^" unfound

I'm trying to define a power function in Coq, and I can't seem to find the relevant module to import:
Require Import Coq.Numbers.NatInt.NZPow.
Definition func (a b : nat) : nat := a+b*2^a.
Gives me the following error:
Unknown interpretation for notation "_ ^ _".
I'm a bit confused, because inside Coq.Numbers.NatInt.NZPow, I see the following description:
Interface of a power function, then its specification on naturals
And also this:
Module Type PowNotation (A : Typ)(Import B : Pow A).
Infix "^" := pow.
End PowNotation.
So what am I missing?
(TLDR; You can to just Require Import Nat. to get the pow definition and notation for nat.
Require Import Nat.
Definition func (a b : nat) : nat := a+b*2^a.
)
The problem is that you are trying to use a module type instead of a module.
The abstract interfaces of NZPow need to be instantiated for the specific types. In the case of nat it is already done in the library in NPeano. It is just taking the already defined stuff in the "old" PeanoNat.Nat, so its very short. Btw, note the deprecation warning...
(** This file is DEPRECATED ! Use [PeanoNat] (or [Arith]) instead. *)
(** [PeanoNat.Nat] already implements [NAxiomSig] *)
Module Nat <: NAxiomsSig := Nat.
Anyway, if you insist on using this, you should import NPeano which is a module that concretely implements the NAxsiomsSig module type for nat. It will just give you the same functions you get when you do Require Import Nat. You can see they are really definitionally the same function with
Require Import Init.Nat.
Require Import NPeano.
Check eq_refl: Init.Nat.add = NPeano.Nat.add.
(The Numbers seem to not have gotten much attention since 2011, so perhaps you should use something more maintained for your work. OTOH, natural numbers have also been around unchanged for the last 13 billion plus years, so...)
All the NZ modules contain axiomatizations. They specify the properties of functions like pow without actually defining them. They do this by using Modules. A Module is a collection of definitions, notations, etc., and the names and types of those definitions etc. form a Module Type. You can "open" a Module and use whatever's inside by Importing it, but to do that you need to have a module of the correct type in the first place.
Pow A is the type of implementations of pow : A -> A -> A, and PowNotation is the type of modules that contain the notation Infix "^" := pow. If you have a Module that has type (or supertype!) PowNotation, you can Import that module to get at that notation. But, again, since the NZ modules are just axiomatizations, they don't give you such a module and so you haven't imported anything that gives you that notation. You can directly import an actual implementation:
Require Import PeanoNat.
(* The module Nat has type Pow nat, witnessed by Nat.pow : nat -> nat -> nat
however, it does not have type Pow' nat, so it doesn't actually contain
Infix "^" := pow.
The "^" notation is just coming from PeanoNat itself. *)
Definition func (a b : nat) : nat := a+b*2^a.
Or you can abstract over the number system in use (so it could be unary nats, or the binary naturals, or the integers, or the integers mod some number, etc.), in the same way that all the NZ modules abstract over the number system:
Require Import NZAxioms.
Require Import NZPow.
Module Type NZFunc (Import A : Typ) (Import OT : OneTwo' A) (Import ASM : AddSubMul' A) (Import P : Pow' A).
Definition func (a b : t) : t := a+b*2^a.
(* t means A.t, and can be many things depending on the final implementation of this module type *)
(* 2 comes from OT, + from ASM, and ^ from P *)
End NZFunc.

Specialization of module argument in Coq

I have a module and I need to specialize one of its argument. I want to use natural numbers instead of arbitrary UsualDecidableTypeFull. How can I obtain such behaviour in Coq?
I defined some module:
Module PRO2PRE_mod
(SetVars FuncSymb PredSymb PropSymb: UsualDecidableTypeFull).
(* ... *)
End PRO2PRE_mod.
Then I specialized the last of the arguments PropSymb.
Require Import Arith.PeanoNat.
Module m2 : UsualDecidableTypeFull.
Definition t:=nat.
Definition eq := #eq nat.
Definition eq_refl:=#eq_refl nat.
Definition eq_sym:=#eq_sym nat.
Definition eq_trans:=#eq_trans nat.
Definition eq_equiv:Equivalence eq := Nat.eq_equiv.
Definition eq_dec := Nat.eq_dec.
Definition eqb:=Nat.eqb.
Definition eqb_eq:=Nat.eqb_eq.
End m2.
This module needs specialization of PropVars:
Module SWAP_mod
(SetVars FuncSymb PredSymb : UsualDecidableTypeFull).
Module PRE := PRO2PRE_mod SetVars FuncSymb PredSymb m2.
Import PRE.
Theorem test : m2.t.
try exact 0. (* ERROR HERE! *)
Abort.
End SWAP_mod.
How to use theorems about natural numbers inside the last module? (I think I don't understand something about using modules... Maybe we need somehow to coerce the type 'm2.t' to the type 'nat'?)
Indeed, the use of : UsualDecidableTypeFull in the definition of m2 hides completely the implementation details of m2. From the outside, m2.t is an unknown type.
Sometimes, this is exactly what you want. For example, you may want to abstract away a type defined in a module so that the users cannot manipulate values of this type without using the functions that you gave to them in the module. You can thus ensure that they will not break some invariants.
However, in your case, you need to remember that m2.t is actually nat, you have at least these two options:
Make the interface transparent with Module m2 <: UsualDecidableTypeFull. When using this, Coq just verifies that the definition of the module complies with the signature, but does not hide the content of the module.
If you still want to hide part of the module, you can also use
Module m2 : UsualDecidableTypeFull with Definition t := nat.
In this case, from the outside, m2.t is known to be nat, but the other fields of m are masked. For instance, the body of m2.eqb is hidden.