Specialization of module argument in Coq - 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.

Related

Use of build-In function in Coq

I want to use lemma (count_occ_In)related to count_occ function from library.I have Imported library in the Coq Script. But still I am unable to use it. If I copy count_occ & eq_dec from library in the scipt,then it works. My question is why I should redefine function when I have included library module. Please guide me how to write lemma by adding the library module only(Not defining the functions again)?.
With the additional information this should work for you:
Require Import List Arith.
Import ListNotations.
Check count_occ.
Search nat ({?x = ?y} + {?x <> ?y}).
Definition count_occ_nat := count_occ Nat.eq_dec.
Definition count_occ_In_nat := count_occ_In Nat.eq_dec.
Check count_occ_nat.
Check count_occ_In_nat.
See how I used Check to find which arguments count_occ takes and how I used Search to find a suitable instance for the decidability of equality function.
count_occ is written like this because it should work for lists of any type with decidable equality, but then to use it, you need a proof that for your type equality is decidable, and you have to give this explicitly.
In modern definitions one makes such arguments implicit and uses type classes to automatically fill in information like decidable equality, but count_occ has an explicit argument for that, so you have to supply it.

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.

How to set implicit parameters for constructor

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.

Best Practices for Dummy Values in Coq

I find that I'm frequently writing code like this:
Fixpoint get_fresh w (Γ : Ctx) : Pat w * Ctx:=
match w with
...
| w1 ⊗ w2 => let (p1, Γ1) := get_fresh w1 Γ in
match Γ ⋓ Γ1 with
| None => (dummy_pat _, dummy_ctx)
| Some Γ' => (p1,Γ')
end.
Where the None branch will never be entered. (Here, it's impossible to enter the branch, sometimes we will never enter the branch on an appropriate input.)
What's the best way to implement the dummy values that should never be returned?
An easy approach is to simply declare
Parameter dummy_pat : forall W, Pat W.
Parameter dummy_ctx : Ctx.
But that sounds seems like bad practice - for all the user knows Ctx and Pat W might have no inhabitants. (This is especially true for dependent types like Pat W.)
I could give simple definitions for dummy_pat and dummy_ctx but I don't want users reasoning about this branch. I could declare dummy_pat and dummy_ctx opaque, but opacity is disturbingly easy to reverse.
Finally, I guess I could declare these as the a projection from a sigma type, but it seems like that would be confusing, and I'm not sure it addresses the problem of reasoning about that case.
(Note that I don't want to intrinsically prove that these branches are inaccessible, using Program or otherwise. I find these functions very difficult to write and to use.)
Any suggestions?
The following way of declaring a module may have better opaqueness guarantees (but if I'm wrong I'd be very interested to know!):
Module Type DummySig.
Parameter dummy_pat : forall W, Pat W.
Parameter dummy_ctx : Ctx.
End DummySig.
Module Import Dummy : DummySig.
Definition dummy_pat := (* some simple definition *)
Definition dummy_ctx := (* some simple definition *)
End Dummy.
Explanation
Module Import Dummy : DummySig. is short for Module Dummy : DummySig followed by Import Dummy. after the closing End Dummy. command.
Module Dummy : DummySig. declares a module with module type (or signature) DummySig, and also seals the module so that only the information declared in DummySig is visible about this Dummy module.
This is a strong abstraction boundary that hides all of the implementation details. In particular, a Parameter in DummySig makes a definition opaque in Dummy, and identifiers defined in Dummy that do not appear in DummySig are not visible at all from outside the module.
As far as I can tell, this opaqueness is irreversible, which is the key point here.
For comparison, the two other ways of declaring modules are:
Module M. exposes everything in the module M, so it is mostly a kind of namespacing.
Module M <: MSig., also exposes everything in M, while checking that it implements the signature MSig (defined via Module Type MSig.), without the "sealing" aspect of Module M : Sig..
Other proposed solutions
You can also turn the dummies into actual parameters, either via a module functor...
Module MyProject (Dummy : DummySig).
Import Dummy.
...
or a section; to avoid having to pass dummies around, a type class may be useful.
Class Dummy (A : Type) := { dummy : A }.
Section Dummies.
Context `{forall W, Dummy (Pat W)}.
Context `{Dummy Ctx}.
...
At the end of the day I wonder whether it is really bad that users can reason about inaccessible branches.

How to use the Lemma inside a module in Coq?

I defined a module type in one file called A.v
Module Type WeakPair.
...
End WeakPair.
Module WeakPairProps (Import WP : WeakPair).
Lemma Weak_A ....
End WeakPairProps.
Then I want to define another file B.v that can use the Lemma in WeakPairProps for example : Weak_A.
Because WeakPairProps is not a module type so I do not know how to write a module that can reuse the lemma in WeakPairProps.
First you need to define a module that implements the module type WeakPair :
Module WeakPairImpl <: WeakPair.
(* stuff goes here *)
End WeakPairImpl.
Now you can instantiate the functor WeakPairProps:
Module WeakPairPropsInst := WeakPairProps(WeakPairImpl).
You are now able to refer to the lemma:
WeakPairPropsInst.lemma
You can import WeakPairPropsInst if you desire not to use qualified names.