Setoids
(* DEFINITION OF SETOID, i. e. a set with an equivalence relation. *)
(* Venanzio Capretta, January 1999. *)
(* Coq version 6.2.3 *)
Require Export Relations.
Require Export Eqdep.
Syntactic Definition
Reflexive := (reflexive ?).
Syntactic Definition
Symmetric := (symmetric ?).
Syntactic Definition
Transitive := (transitive ?).
Syntactic Definition
Equiv := (equiv ?).
Implicit Arguments On.
Record
Setoid : Type := setoid
{ s_el :> Set;
s_eq : (relation s_el);
s_proof : (Equiv s_eq)
}.
(* We define an infix notation for equality of setoid elements. *)
Infix 5 "[=]" s_eq.
(* We want functions that extract the proofs from a setoid. *)
Lemma
s_reflexivity : (S:Setoid)(x:S)x[=]x.
Lemma
s_symmetry : (S:Setoid)(x,y:S)x[=]y -> y[=]x.
Lemma
s_transitivity : (S:Setoid)(x,y,z:S)x[=]y -> y[=]z -> x[=]z.
Hints Resolve s_reflexivity s_symmetry s_transitivity : setoids.
(* The hint s_transitivity is only used by EAuto with sets setoids, not by Auto with sets setoids. *)
(* SETS AS SETOIDS *)
(* A type with Leibniz equality is trivially a setoid. *)
Section Set_setoids.
Variable A : Set.
Remark eq_equiv : (Equiv (eq A)).
Definition
S_set : Setoid := (!setoid A (eq A) eq_equiv).
End Set_setoids.
(* UNIT SETOID *)
Definition
S_unit := (S_set unit).
(* PREDICATES OVER A SETOID. *)
(* They must be invariant by the setoid equality. *)
Definition
Predicate_well_defined : (S : Setoid)(S -> Prop) -> Prop :=
[S : Setoid][pred : S -> Prop]
(x, y : S)(x [=] y) -> (pred x) -> (pred y).
(* The type of predicates over a setoid S. *)
Record
Setoid_predicate [S : Setoid] : Type := setoid_predicate
{ sp_pred :> S -> Prop;
sp_proof : (Predicate_well_defined sp_pred)
}.
(* RELATIONS OVER A SETOID. *)
Definition
Relation_well_defined : (S : Setoid)(relation S) -> Prop :=
[S, rel](x1,x2,y1,y2:S)(x1 [=] x2) -> (y1 [=] y2) ->
(rel x1 y1) -> (rel x2 y2).
(* The type of relations over a setoid S. *)
Record
Setoid_relation [S : Setoid] : Type := setoid_relation
{ sr_rel :> S -> S -> Prop;
sr_proof : (Relation_well_defined sr_rel)
}.
(* The type of equivalence relations over a setoid. *)
Record
Setoid_equivalence [S:Setoid] : Type := setoid_equivalence
{ se_rel :> (Setoid_relation S);
se_proof : (Equiv se_rel)
}.
(* For a setoid with Leibniz equality, every predicate or relation *)
(* is well-defined. *)
Section Leibniz_Equality_Predicates_Relations.
Variable A : Set.
Variable P : A -> Prop.
Local S := (S_set A).
Remark leibniz_pred_well_defined : (Predicate_well_defined 1!S P).
(* So every predicate is a setoid predicate. *)
Definition
leibniz_eq_predicate : (Setoid_predicate S) :=
(setoid_predicate leibniz_pred_well_defined).
Variable R : (relation A).
Remark leibniz_rel_well_defined : (Relation_well_defined 1!S R).
Definition
leibniz_eq_relation : (Setoid_relation S) :=
(setoid_relation leibniz_rel_well_defined).
End Leibniz_Equality_Predicates_Relations.
(* SUBSETOIDS. *)
(* If P is a predicate over the setoid S, then we want to define *)
(* the setoid whose elements are the elements of S that satisfy P. *)
(* This is done with a sigma type. *)
Section Subsetoids.
Variable S : Setoid.
Variable P : (Setoid_predicate S).
Definition
subsetoid_carrier : Set := (sig S P).
Definition
sub_s_elem : (x:S)(P x) -> subsetoid_carrier :=
(exist S P).
(* The definition of the equality for the subsetoid is inherited from *)
(* the setoid S. The equality does not depend on the proof of (P x). *)
Definition
subsetoid_eq : (relation subsetoid_carrier) :=
[a, b : subsetoid_carrier]
(proj1_sig ? ? a) [=] (proj1_sig ? ? b).
Lemma
subsetoid_eq_equiv : (Equiv subsetoid_eq).
Definition
subsetoid : Setoid :=
(setoid subsetoid_eq_equiv).
Definition
s_inj : subsetoid -> S :=
[a : subsetoid](proj1_sig ? ? a).
Definition
subsetoid_el := (s_el subsetoid).
(* It would be nice to be able to declare s_inj as a coercion : *)
(* Coercion s_inj : subsetoid_carrier >-> s_el. *)
(* But this would cause some side effects: the coercion from *)
(* S_Fun to Setoid_function (defined below) would not work. *)
(* This is due to the fact that s_el would be at the same time a *)
(* coercion and a class. *)
(* This extracts the proof that the given element satisfies *)
(* the defining predicate. *)
Definition
ss_proof : (a : subsetoid)(P (s_inj a)) :=
[a : subsetoid](proj2_sig ? ? a).
End Subsetoids.
(* PRODUCTS OF SETOIDS *)
Section Setoid_Product.
Variables S1, S2 : Setoid.
Local C := S1*S2.
Local C_eq : (relation C) :=
[z1, z2 : C](Fst z1) [=] (Fst z2) /\
(Snd z1) [=] (Snd z2).
Remark C_equivalence : (Equiv C_eq).
Definition
S_prod : Setoid := (setoid C_equivalence).
End Setoid_Product.
Infix 7 "[*]" S_prod.
(* FUNCTIONS FROM A SETOID TO ANOTHER SETOID. *)
(* Such functions must preserve the setoid equality. *)
Section Setoid_functions.
Variables S1, S2 : Setoid.
Definition
fun_well_defined : (S1 -> S2) -> Prop :=
[f : S1 -> S2]
(x1, x2 : S1)x1[=]x2 -> (f x1)[=](f x2).
Record
Setoid_function : Set := setoid_function
{ s_function :> S1 -> S2;
s_fun_proof : (fun_well_defined s_function)
}.
(* Extensional equality of functions. *)
Definition
extensional_eq : (relation Setoid_function) :=
[f, g : Setoid_function]
(x : S1)(f x)[=](g x).
(* Extensional equality is an equivalence relation. *)
Lemma
extensional_eq_reflexive : (Reflexive extensional_eq).
Lemma
extensional_eq_symmetric : (Symmetric extensional_eq).
Lemma
extensional_eq_transitive : (Transitive extensional_eq).
Lemma
extensional_eq_equivalence : (Equiv extensional_eq).
(* So the functions between two setoid form a setoid. *)
Definition
S_Fun : Setoid :=
(setoid extensional_eq_equivalence).
(* Applying equal functions to equal object yields equal results. *)
Lemma
eq_fun_args
: (f1, f2 : S_Fun)f1[=]f2 ->
(x1, x2 : S1) x1[=]x2 ->
(f1 x1)[=](f2 x2).
Hints Resolve eq_fun_args : setoids.
(* Definition of injection, surjection and bijection *)
(* between setoids. *)
Definition
injective : S_Fun -> Prop :=
[f : S_Fun]
(x, y : S1)(f x) [=] (f y) -> x [=] y.
Definition
weak_surjective : S_Fun -> Prop :=
[f : S_Fun]
(y : S2)(EX x:S1 | (f x) [=] y).
Definition
weak_bijective : S_Fun -> Prop :=
[f : S_Fun]
(injective f) /\ (weak_surjective f).
(* In Coq it is not possible to define an element of a Set by *)
(* elimination over a Prop, and therefore with the previous *)
(* it is not possible to build an inverse of f. *)
(* We then need the following stronger definition. *)
Definition
surjective : S_Fun -> Set :=
[f : S_Fun]
(y : S2)(sig S1 [x:S1](f x) [=] y).
(* Note that we cannot define (bijective f) as *)
(* (injective f) /\ (surjective f) because (surjective f) is a Set *)
(* not a Prop. Also (bijective f) must be a Set if we want to be *)
(* able to define an inverse. *)
Inductive
bijective : S_Fun -> Set :=
is_bijective : (f : S_Fun)
(injective f) -> (surjective f) ->
(bijective f).
(* Being and injection or a surjection is an invariant property *)
(* with respect to the extensional equality. *)
Lemma
injective_well_defined :
(Predicate_well_defined injective).
Lemma
surjective_well_defined :
(f, g : S_Fun)f [=] g -> (surjective f) -> (surjective g).
Record
Bijection : Set := bijection
{ b_function : S_Fun;
b_proof : (bijective b_function)
}.
(* Bijection cannot be defined as a subsetoid of S_Fun because *)
(* the predicate bijective needs to be a Set predicate in order *)
(* to be able to extract an inverse function. *)
Lemma
bijection_is_injective :
(f : Bijection)(injective (b_function f)).
Lemma
bijection_is_surjective :
(f : Bijection)(surjective (b_function f)).
End Setoid_functions.
Infix RIGHTA 7 "[->]" S_Fun.
(* The identity is always a setoid bijection. *)
Section Setoid_Identity.
Variable S : Setoid.
Local id_funct : S -> S := [x:S]x.
Lemma
id_well_defined : (fun_well_defined id_funct).
Definition
s_id : S [->] S :=
(setoid_function id_well_defined).
Lemma
id_inj : (injective s_id).
Lemma
id_surj : (surjective s_id).
Lemma
id_bij : (bijective s_id).
Definition
s_id_bij : (Bijection S S) := (bijection id_bij).
End Setoid_Identity.
(* Composition of setoid fuctions. *)
Section Setoid_Functions_Composition.
Variables S1, S2, S3 : Setoid.
Variable g : S2 [->] S3.
Variable f : S1 [->] S2.
Local fun_comp : S1 -> S3 :=
[x : S1](g (f x)).
Lemma
fun_comp_well_defined : (fun_well_defined fun_comp).
Definition
s_fun_comp : S1 [->] S3 :=
(setoid_function fun_comp_well_defined).
End Setoid_Functions_Composition.
Infix 7 "[o]" s_fun_comp.
(* Inverse of a bijection. *)
Section Inverse.
Variables S1, S2 : Setoid.
Variable f : (Bijection S1 S2).
Local f_is_bij := (b_proof f).
Local f_is_inj := (bijection_is_injective 3!f).
Local f_is_surj := (bijection_is_surjective f).
(* Notice the difference in the two definitions above: *)
(* the function is an implicit argument for injective. *)
Definition
bijection_inverse_fun : S2 -> S1 :=
[y : S2](proj1_sig ? ? (f_is_surj y)).
Lemma
inverse_fun_is_left_inverse :
(y : S2)
((b_function f) (bijection_inverse_fun y)) [=] y.
Lemma
inverse_well_defined : (fun_well_defined bijection_inverse_fun).
Definition
bijection_inverse : S2 [->] S1 :=
(setoid_function inverse_well_defined).
(* One could now also proof that the inverse is an element of *)
(* (Bijection S2 S1). This is best done by first proving that *)
(* a function that has and inverse is a bijection. *)
(* All this is left as an exercise. *)
End Inverse.
(* The type of unary operations on a setoid. *)
Definition
Un_operaton : Setoid -> Type := [S:Setoid]S [->] S.
(* The type of binary operations on a setoid. *)
Definition
Bin_operation : Setoid -> Type := [S:Setoid]S [->] S [->] S.
(* Properties of binary operations *)
Definition
commutativity : (S : Setoid)(Bin_operation S) -> Prop :=
[ S : Setoid ]
[ op : (Bin_operation S) ]
(x, y : S)((op x) y) [=] ((op y) x).
Definition
associativity : (S : Setoid)(Bin_operation S) -> Prop :=
[ S : Setoid ]
[ op : (Bin_operation S) ]
(x,y,z : S)((op x) ((op y) z)) [=] ((op ((op x) y)) z).
Implicit Arguments Off.
(* We now prove that eq_rec preserves setoid equality.
The proof require the use of the axiom eq_rec_eq contained
in the library module Eqdep.
*)
Theorem
eq_rec_setoid :
(A : Set)(x : A)(P : A -> Setoid)
(p1, p2 : (P x))p1 [=] p2 ->
(y : A)(p : x=y)
(eq_rec A x P p1 y p) [=] (eq_rec A x P p2 y p).
25/02/99, 14:36