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! :-)
Related
I was able to create a ComRingMixin, but when I try to declare this type as a canonical ring, Coq complains:
x : phantom (GRing.Zmodule.class_of ?bT) (GRing.Zmodule.class ?bT)
The term "x" has type "phantom (GRing.Zmodule.class_of ?bT) (GRing.Zmodule.class ?bT)"
while it is expected to have type "phantom (GRing.Zmodule.class_of 'I_n) ?b".
This is what I have so far, I was able to define the operations and instantiate the abelian group mixin as well as the canonical declaration, but for the ring, my code fails.
From mathcomp Require Import all_ssreflect all_algebra.
Set Implicit Arguments.
Unset Strict Implicit.
Unset Printing Implicit Defensive.
Import GRing.Theory.
Open Scope ring_scope.
Section Zn.
Variables n :nat.
Axiom one_lt_n : (1 < n)%N.
Axiom z_lt_n : (0 < n)%N.
Lemma mod_lt_n : forall (x : nat), ((x %% n)%N < n)%N.
Proof.
move=> x0; rewrite ltn_mod; by exact: z_lt_n.
Qed.
Definition mulmod (a b : 'I_n) : 'I_n := Ordinal (mod_lt_n (((a*b)%N %% n)%N)).
Definition addmod (a b : 'I_n) : 'I_n := Ordinal (mod_lt_n (((a+b)%N %% n)%N)).
Definition oppmod (x : 'I_n) : 'I_n := Ordinal (mod_lt_n (n - x)%N).
Lemma addmodC : commutative addmod. Admitted.
Lemma addmod0 : left_id (Ordinal z_lt_n) addmod. Admitted.
Lemma oppmodK : involutive oppmod. Admitted.
Lemma addmodA : associative addmod. Admitted.
Lemma addmodN : left_inverse (Ordinal z_lt_n) oppmod addmod. Admitted.
Definition Mixin := ZmodMixin addmodA addmodC addmod0 addmodN.
Canonical ordn_ZmodType := ZmodType 'I_n Mixin.
Lemma mulmodA : associative mulmod. Admitted.
Lemma mulmodC : commutative mulmod. Admitted.
Lemma mulmod1 : left_id (Ordinal one_lt_n) mulmod. Admitted.
Lemma mulmod_addl : left_distributive mulmod addmod. Admitted.
Lemma one_neq_0_ord : (Ordinal one_lt_n) != Ordinal z_lt_n. Proof. by []. Qed.
Definition mcommixin := #ComRingMixin ordn_ZmodType (Ordinal one_lt_n) mulmod mulmodA mulmodC mulmod1 mulmod_addl one_neq_0_ord.
Canonical ordnRing := RingType 'I_n mcommixin.
Canonical ordncomRing := ComRingType int intRing.mulzC.
What am i doing wrong? I'm basing myself on http://www-sop.inria.fr/teams/marelle/advanced-coq-17/lesson5.html.
The problem is that ssralg already declares ordinal as a zmodType instance. There can only be one canonical instance of a structure per head symbol, so your declaration of ordn_ZmodType is effectively ignored.
One solution around it is to introduce a local synonym in this section and use it to define the canonical structures:
(* ... *)
Definition foo := 'I_n.
(* ... *)
Definition ordn_ZmodType := ZmodType foo Mixin.
(* ... *)
Canonical ordnRing := RingType foo mcommixin. (* This now works *)
The other solution is to use the ringType instance defined in MathComp for ordinal. The catch is that it is only defined for types of the form 'I_n.+2.
In principle, one could also have declared these instances assuming the same axioms on n as you did, but this would make the inference of canonical structures more difficult.
Check fun n => [ringType of 'I_n.+2].
(* ... : nat -> ringType *)
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.
When attempting to formalize the class which corresponds to an algebraic structure (for example the class of all monoids), a natural design is to create a type monoid (a:Type) as a product type which models all the required fields (an element e:a, an operator app : a -> a -> a, proofs that the monoid laws are satisfied etc.). In doing so, we are creating a map monoid: Type -> Type. A possible drawback of this approach is that given a monoid m:monoid a (a monoid with support type a) and m':monoid b (a monoid wih support type b), we cannot even write the equality m = m' (let alone prove it) because it is ill-typed. An alternative design would be to create a type monoid where the support type is just another field a:Type, so that given m m':monoid, it is always meaningful to ask whether m = m'. Somehow, one would like to argue that if m and m' have the same supports (a m = a m) and the operators are equals (app m = app m', which may be achieved thanks to some extensional equality axiom), and that the proof fields do not matter (because we have some proof irrelevance axiom) etc. , then m = m'. Unfortunately, we can't event express the equality app m = app m' because it is ill-typed...
To simplify the problem, suppose we have:
Inductive myType : Type :=
| make : forall (a:Type), a -> myType.
.
I would like to have results of the form:
forall (a b:Type) (x:a) (y:b), a = b -> x = y -> make a x = make b y.
This statement is ill-typed so we can't have it.
I may have axioms allowing me to prove that two types a and b are same, and I may be able to show that x and y are indeed the same too, but I want to have a tool allowing me to conclude that make a x = make b y. Any suggestion is welcome.
A low-tech way to prove this is to insert a manual type-cast, using the provided equality. That is, instead of having an assumption x = y, you have an assumption (CAST q x) = y. Below I explicitly write the cast as a match, but you could also make it look nicer by defining a function to do it.
Inductive myType : Type :=
| make : forall (a:Type), a -> myType.
Lemma ex : forall (a b:Type) (x:a) (y:b) (q: a = b), (match q in _ = T return T with eq_refl => x end) = y -> make a x = make b y.
Proof.
destruct q.
intros q.
congruence.
Qed.
There is a nicer way to hide most of this machinery by using "heterogenous equality", also known as JMeq. I recommend the Equality chapter of CPDT for a detailed introduction. Your example becomes
Require Import Coq.Logic.JMeq.
Infix "==" := JMeq (at level 70, no associativity).
Inductive myType : Type :=
| make : forall (a:Type), a -> myType.
Lemma ex : forall (a b:Type) (x:a) (y:b), a = b -> x == y -> make a x = make b y.
Proof.
intros.
rewrite H0.
reflexivity.
Qed.
In general, although this particular theorem can be proved without axioms, if you do the formalization in this style you are likely to encounter goals that can not be proven in Coq without axioms about equality. In particular, injectivity for this kind of dependent records is not provable. The JMEq library will automatically use an axiom JMeq_eq about heterogeneous equality, which makes it quite convenient.
I'm currently trying to write a tactic that instantiates an existential quantifier using a term that can be generated easily (in this specific example, from tauto). My first attempt:
Ltac mytac :=
match goal with
| |- (exists (_ : ?X), _) => cut X;
[ let t := fresh "t" in intro t ; exists t; firstorder
| tauto ]
end.
This tactic will work on a simple problem like
Lemma obv1(X : Set) : exists f : X -> X, f = f.
mytac.
Qed.
However it won't work on a goal like
Lemma obv2(X : Set) : exists f : X -> X, forall x, f x = x.
mytac. (* goal becomes t x = x for arbitrary t,x *)
Here I would like to use this tactic, trusting that the f which tauto finds will be just fun x => x, thus subbing in the specific proof (which should be the identity function) and not just the generic t from my current script. How might I go about writing such a tactic?
It's much more common to create an existential variable and let some tactic (eauto or tauto for example) instantiate the variable by unification.
On the other hand, you can also literally use a tactic to provide the witness using tactics in terms:
Ltac mytac :=
match goal with
| [ |- exists (_:?T), _ ] =>
exists (ltac:(tauto) : T)
end.
Lemma obv1(X : Set) : exists f : X -> X, f = f.
Proof.
mytac.
auto.
Qed.
You need the type ascription : T so that the tactic-in-term ltac:(tauto) has the right goal (the type the exists expects).
I'm not sure this is all that useful (usually the type of the witness isn't very informative and you want to use the rest of the goal to choose it), but it's cool that you can do this nonetheless.
You can use eexists to introduce an existential variable, and let tauto instantiates it.
This give the following simple code.
Lemma obv2(X : Set) : exists f : X -> X, forall x, f x = x.
eexists; tauto.
Qed.
I'm trying to deal with canonical structures in ssreflect. There are 2 pieces of code that I took from here.
I will bring pieces for the bool and the option types.
Section BoolFinType.
Lemma bool_enumP : Finite.axiom [:: true; false]. Proof. by case. Qed.
Definition bool_finMixin := Eval hnf in FinMixin bool_enumP.
Canonical bool_finType := Eval hnf in FinType bool bool_finMixin.
Lemma card_bool : #|{: bool}| = 2. Proof. by rewrite cardT enumT unlock. Qed.
End BoolFinType.
Section OptionFinType.
Variable T : finType.
Notation some := (#Some _) (only parsing).
Local Notation enumF T := (Finite.enum T).
Definition option_enum := None :: map some (enumF T).
Lemma option_enumP : Finite.axiom option_enum.
Proof. by case => [x|]; rewrite /= count_map (count_pred0, enumP). Qed.
Definition option_finMixin := Eval hnf in FinMixin option_enumP.
Canonical option_finType := Eval hnf in FinType (option T) option_finMixin.
Lemma card_option : #|{: option T}| = #|T|.+1.
Proof. by rewrite !cardT !enumT {1}unlock /= !size_map. Qed.
End OptionFinType.
Now, suppose I have a function f from finType to Prop.
Variable T: finType.
Variable f: finType -> Prop.
Goal f T. (* Ok *)
Goal f bool. (* Not ok *)
Goal f (option T). (* Not ok *)
In the last two cases I get the following error:
The term "bool/option T" has type "Set/Type" while it is expected to have type "finType".
What am I doing wrong?
The instance search for canonical structures is a bit counter intuitive in these cases. Suppose that you have the following things:
a structure type S, and a type T;
a field proj : S -> T of S;
an element x : T; and
an element st : S that has been declared as canonical, such that proj st is defined as x.
In your example, we would have:
S = finType
T = Type
proj = Finite.sort
x = bool
st = bool_finType.
Canonical structure search is triggered only in the following case: when the type-checking algorithm is trying to find a value to validly fill in the hole in the equation proj _ = x. Then, it will use st : S to fill in this hole. In your example, you expected the algorithm to understand that bool can be used as finType, by transforming it into bool_finType, which is not quite what is described above.
To make Coq infer what you want, you need to use a unification problem of that form. For instance,
Variable P : finType -> Prop.
Check ((fun (T : finType) (x : T) => P T) _ true).
What is going on here? Remember that Finite.sort is declared as a coercion from finType to Type, so x : T really means x : Finite.sort T. When you apply the fun expression to true : bool, Coq has to find a solution for Finite.sort _ = bool. It then finds bool_finType, because it was declared as canonical. So the element of bool is what triggers the search, but not quite bool itself.
As ejgallego pointed out, this pattern is so common that ssreflect provides the special [finType of ...] syntax. But it might still be useful to understand what is going on under the hood.