Import <Module> vs. Include <Module> in Coq Module system - coq

What is the exact semantics of Include M1 inside another module, say M ? How is it different from doing Import M1 inside the module M ? More precisely what is the semantics of the following command:
Module Type M := M1 <+ M2 <+ M3.

To summarize the semantics of both vernacular commands:
The command Include M1 (which can be used in the definition of a module or a module type) asks Coq to make a copy of all the fields of M1. Thus, it acts just like a "copy-and-paste" of the contents of M1 inside the ambient module (resp. module type).
The command Import M1 (which can also be used in the definition of a module or a module type, but additionally requires that M1 is a module) allows one to refer to the fields of M1 with their short identifier (i.e., without needing to use qualified identifiers M1.field_name)
Next, the syntax Module Type M := M1 <+ M2 <+ M3 is a shortcut for:
Module Type M.
Include M1.
Include M2.
Include M3.
End M.
See the corresponding sections of Coq's reference manual on the Include and Import commands, and you may also want to take a look at the Export command (a variant of Import).
If at some point you hesitate between Include and Import, you should probably try to use Import in the first place, because it will have a lighter effect (it won't clone the contents of the specified module but just define shorter names).
Finally, below are two comprehensive examples that illustrate the use of modules, module types, and functors in Coq as well as the commands Include and Import:
(********************************************)
(* Example involving a parameterized module *)
(********************************************)
(* A signature *)
Module Type MT.
Parameter t : Type.
End MT.
(* A bigger signature *)
Module Type MT1.
Include MT.
Parameter u : t.
Parameter f : t -> t.
End MT1.
(* A parameterized module *)
Module F1 (M1 : MT1).
Import M1. (* => we can now write f rather than M1.f *)
Definition fu := f u.
End F1.
(* A module implementing MT1 *)
Module M1 <: MT1. (* => check the signature but don't make the module opaque *)
Definition t := nat.
Definition u := O.
Definition f := S.
End M1.
(* Instantiation *)
Module FM1 := F1 M1.
Compute FM1.fu.
and I recall that Compute is a shortcut for Eval vm_compute in
(********************************************)
(* Extra example: a parameterized signature *)
(* *)
(* It can be noted that this feature of Coq *)
(* module types has no equivalent in OCaml… *)
(********************************************)
Module Type MT2 (M : MT).
Parameter u : M.t.
Import M. (* => we can now write t rather than M.t *)
Parameter f : t -> t.
End MT2.
(* Another parameterized module *)
Module F2 (M : MT) (M2 : MT2 M).
Import M2.
Definition fu := f u.
End F2.
(* Modules implementing MT and MT2 *)
Module M <: MT.
Definition t := bool.
End M.
Module M2 <: MT2 M.
Definition u := false.
Definition f := negb.
End M2.
(* Instantiation *)
Module FM2 := F2 M M2.
Compute FM2.fu.

Related

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! :-)

Coq Import problems

I'm trying to import Library Coq.Structures.OrdersFacts as usual with:
Require Import Coq.Structures.OrdersFacts
Then I try to use of the lemmas there with either:
apply CompareFacts.compare_nlt_iff. or apply compare_nlt_iff.
But none work ... what am I missing?
CompareFacts is a Module Type, not a Module. You can see that if you do
Require Import Coq.Structures.OrdersFacts.
Print OrdersFacts.CompareFacts.
Find a Module of this type and apply its Lemmas instead.
EDIT:
I meant that to use the lemmas on i.e. nat, you need a module that shows that nat is a DecStrOrder' (and Nat from PeanoNat is such a module), and also one that specializes CompareFacts for nat .
Perhaps an example is more useful.
Require Import Coq.Structures.OrdersFacts.
Module mymodule (O:DecStrOrder') (T: CompareFacts O).
Import T.
Import O.
Check compare_eq_iff. (* from CompareFacts *)
(* a theorem about terms of type O.t *)
Lemma lem1 a b c: (a ?= b) = Eq -> b == c -> c == a.
intros.
rewrite compare_eq_iff in H. (* here we use the lemma *)
rewrite H.
rewrite H0.
apply eq_equiv.
Qed.
End mymodule.
(* the above module functor can be specialised for i.e. nat *)
Require Import PeanoNat.
Print CompareFacts.
Module M : CompareFacts Nat.
Definition compare_eq_iff := Nat.compare_eq_iff.
Definition compare_eq := Nat.compare_eq.
Definition compare_lt_iff := Nat.compare_lt_iff.
Definition compare_gt_iff := Nat.compare_gt_iff.
Definition compare_nlt_iff := Nat.compare_nlt_iff.
Definition compare_ngt_iff := Nat.compare_ngt_iff.
Definition compare_refl := Nat.compare_refl.
Definition compare_compat: Proper (eq==>eq==>eq) Nat.compare.
intros x y Hxy a b Hab; now subst. Defined.
Definition compare_antisym := Nat.compare_antisym.
End M.
Module natmodule := mymodule Nat M.
Check natmodule.lem1.

Require, Import, Require Import

In Coq, what's the difference between ... ?
Require X.
Import X.
Require Import X.
I have basically memorized some common patterns. I usually see code using Require Import X. Then there's Import ListNotation. And I just noticed it's also possible to write just Require X. What's the difference? Some practical examples would be appreciated.
Require loads a library whereas Import brings its definitions into scope. Require Import does both. If you only have the library loaded, you'll need to refer to names fully qualified. Coq allows top-level modules corresponding to files to define modules; these have to be imported separately to bring all of their definitions into scope, and they can't be Required - that's what's going on with ListNotations:
(* List is not loaded by default *)
Fail Check List.map.
(* the full name is technically Coq.Lists.List *)
Require List.
(* note that lists are actually defined in Coq.Init.Datatypes which is
imported by default, so [list] is unqualified and the [x::xs] notation is
already defined *)
Print List.map.
(*
List.map =
fun (A B : Type) (f : A -> B) =>
fix map (l : list A) : list B :=
match l with
| nil => nil
| (a :: t)%list => (f a :: map t)%list
end
: forall A B : Type, (A -> B) -> list A -> list B
*)
(* bring everything in List into scope *)
Import List.
(* this includes the ListNotations submodule *)
Import ListNotations.
(* note that now list notations are available, and the list notation scope is
open (from importing List) *)
Print List.map.
(*
map =
fun (A B : Type) (f : A -> B) =>
fix map (l : list A) : list B :=
match l with
| [] => []
| a :: t => f a :: map t
end
: forall A B : Type, (A -> B) -> list A -> list B
*)
Note there are some quirks with how Coq handles modules, especially compared to other languages:
Coq does not require a full path to a module, only an unambiguous suffix. Indeed I rarely see full import paths, even to standard library modules.
Notations cannot be used except by importing the module, and unlike most objects there's no way to refer to a notation, fully qualified or otherwise.
Importing a module can have side effects, for example changing notation interpretation scopes or setting options if you use Global Set in the module being imported.
Importing is fairly limited (especially compared to Haskell) - there's no way to rename a module at import time, or selectively import some definitions.

Working with semirings in Coq

This is a simple Coq syntax newbie question.:)
I am trying to define simple polynomial function on semi_rings:
Require Import Vector.
Import VectorNotations.
Require Import Ring_theory.
Section Polynomial_def.
Variable Asring : Type.
Variable (asr_0 asr_1 : Asring) (asr_add asr_mul: Asring->Asring->Asring).
Variable SRth : semi_ring_theory asr_0 asr_1 asr_add asr_mul eq.
Fixpoint evalPolynomial {n} (a: t Asring n) (x:Asring) : Asring :=
match a with
nil => asr_0
| cons a0 p a' => asr_add a0 (asr_mul x (evalPolynomial a' x))
end.
End Polynomial_def.
When I use it on Reals, for example, I have to do something like this:
Require Import Reals.Rdefinitions.
evalPolynomial R R0 Rplus Rmult a v
I suspect there should be a simpler syntax, where I can just pass single data structure (like comm_ring_1 in Isabelle) which will encapsulate all fields like R,R0,Rplus,Rmult for given type.
Yes, you can package all of your parameters in a structure and then pass that as an argument, something like
Structure semiring := Semiring {
Asring : Type;
asr_0 : Asring;
asr_1 : Asring;
asr_add : Asring -> Asring -> Asring
(* Other fields... *)
}.
Then, you can rephrase your development in terms of this structure:
Section Polynomial_def.
Variable sr := semiring.
Fixpoint evalPolynomial {n} (a: t (Asring sr) n) (x:Asring sr) : Asring sr :=
(* ... *)
Later, when trying to use that, you just have to build such a structure and pass it as a normal argument. You can also use Coq type classes or canonical structures to tell Coq how to pass such arguments automatically.

Design functor to be able to use different modules

I have two different module signatures into two different files. They have the same field name but different behaviour.
And functor inside define another functor.
PI.v
Module Type TPI.
Parameter sig : Signature.
Parameter trsInt: forall f, pi f.
End TPI.
Module P (Export T: TPI).
Lemma A...
Module Export Mono <: MonoType.
End P.
and
MI.v
Module Type TMI.
Parameter sig : Signature.
Parameter trsInt : forall f, mi f.
End TMI.
Module M (Export TM: TMI).
Lemma B ...
Module Export Mono <: MonoType.
End M.
Where MonoType inside another file for example Mono.v
Here is my situation.
I have another file called B.v inside that file I need to use definitions and lemmas in both files PI.v and MI.v.
And one definition I need to use both of them for example.
Definition redPair R is :=
match is with
| Type_PI => pi_int R is
| Type_MI => mi_int R is
end.
I have a problem at R because pi_int R and mi_int R has different sig (Signature), where pi_int used trsInt inside the module signature TPI and mint_int used trsInt inside the module signature TMI.
Here is the way I defined it:
Module PI (Import P : TPI).
Definition pi_int R is := P.trsInt ...
(* inside PI I define another functor for MI *)
Module MI (Import M : TMI).
Definition mi_int R is := M.trsInt ...
Definition redPair R is :=
match is with
| Type_PI => pi_int R is
| Type_MI => mi_int R is (* error here saying that it used the sig of
P.sig but in this case mi_int used the sig of M.sig *)
end.
End MI.
End PI.
My question is that is there a way that I can have a good structure of module that I can have the same signature at the definition redPair? Thank you for your help.
In practice, in the definition of redPair, you have no guarantee that P.sig and M.sig have the same type, which is why you get this error message.
What one can do to solve this kind of problem is to enforce the type equality via a "sharing constraint". Here is a code similar to yours demonstrating how I force P.sig and M.sig to be equal to nat:
Module Type TPI.
Parameter sig : Type.
Parameter x : sig.
End TPI.
Module Type TMI.
Parameter sig : Type.
Parameter x : sig.
End TMI.
Module PI (Import P : TPI with Definition sig := nat).
Definition pi_int := x.
Module MI (Import M : TMI with Definition sig := nat).
Definition mi_int := x.
Definition f (x : bool) :=
if x
then pi_int
else mi_int.
End MI.
End PI.
You could also choose to leave P.sig unconstrained, but then enforce M.sig to be the same:
Module PI (Import P : TPI).
Definition pi_int := x.
Module MI (Import M : TMI with Definition sig := P.sig).
Definition mi_int := x.
Definition f (x : bool) :=
if x
then pi_int
else mi_int.
End MI.
End PI.
Now that a solution to your problem is mentioned, I would advise to be wary of using modules and functors in Coq. Most often than not, you actually only need dependent records. Modules and functors are complicated for everyone, you have to care about abstraction, sharing constraints, etc.
The status quo seems to be that you should avoid using them unless you actually need them for what they offer over dependent records: abstraction and/or subtyping.
As a matter of fact, I am at a bit of unease with your definitions right now. For instance, does it make sense for MI to be defined inside of PI? That seems arbitrary without more context. Maybe it does, I'm just stating that you should be careful when using modules, and make sure you have a good grasp of what you're doing, or it might backfire on you! :)
But if you're just experimenting, please do experiment with them. It's good to know the range of possibilities and the pros and cons of each.