Definition EqPredType_trans r2 r1 r3 := @EqPredType_trans' r1 r2 r3.Definition SubPredType_trans r2 r1 r3 := @SubPredType_trans' r1 r2 r3.(* Declaration of relations *)

(* Unfortunately, Coq setoids don't seem to understand implicit coercions *)
(* and canonical structures so we have to repeat relation declarations    *)
(* for all instances. This is really annoying, but at least I don't have  *)
(* to reprove the lemmas on refl, sym and trans                           *)
(*                                                                        *)
(* Add Parametric Relation T (pT : PredType T) : pT (@EqPredType _ pT)    *)
(*   reflexivity proved by (@EqPredType_refl _ _)                         *)
(*  symmetry proved by (@EqPredType_sym _ _)                              *)
(*  transitivity proved by (@EqPredType_trans' _ _) as EqPredType_rel.    *)
(*                                                                        *)
(* Add Parametric Relation T (pT : PredType T) : pT (@SubPredType _ pT)   *)
(*  reflexivity proved by (@SubPredType_refl _ _)                         *)
(*  transitivity proved by (@SubPredType_trans' _ _) as SubPredType_rel.  *)

Add Parametric Relation T : (Pred T) (@EqPred _)
  reflexivity proved by (@EqPredType_refl _ _)
  symmetry proved by (@EqPredType_sym _ _)
  transitivity proved by (@EqPredType_trans' _ _) as EqPred_rel.Add Parametric Relation T : (Pred T) (@SubPred _)
  reflexivity proved by (@SubPredType_refl _ _)
  transitivity proved by (@SubPredType_trans' _ _) as SubPred_rel.Add Parametric Relation T : (Simpl_Pred T) (@EqSimplPred _)
  reflexivity proved by (@EqPredType_refl _ _)
  symmetry proved by (@EqPredType_sym _ _)
  transitivity proved by (@EqPredType_trans' _ _) as EqSimplPred_rel.Add Parametric Relation T : (Simpl_Pred T) (@SubSimplPred _)
  reflexivity proved by (@SubPredType_refl _ _)
  transitivity proved by (@SubPredType_trans' _ _) as SubSimplPred_rel.Add Parametric Relation T : (Mem_Pred T) (@EqMem T)
  reflexivity proved by (@EqPredType_refl _ _)
  symmetry proved by (@EqPredType_sym _ _)
  transitivity proved by (@EqPredType_trans' _ _) as EqMem_rel.Add Parametric Relation T : (Mem_Pred T) (@SubMem _)
  reflexivity proved by (@SubPredType_refl _ _)
  transitivity proved by (@SubPredType_trans' _ _) as SubMem_rel.(* Declaring morphisms. *)
(* Annoyingly, even the coercions must be declared *)

Add Parametric Morphism T : (@Pred_of_Simpl T) with signature
      @EqSimplPred _ ==> @EqPred T as Pred_of_Simpl_morph.(* Do we need other coercions? We'll discover as we go *)

(* Now the other morphisms. Again, not clear which ones are needed.   *)
(* However, for all this to work, it seems that morphisms must be     *)
(* declared with most specific signatures, or else the system         *)
(* complains. For example, we use EqPred _ instead of EqPredType _ _, *)
(* even though the former is an instance of the later.                *)

Add Parametric Morphism T : (@EqPred T) with signature
    @EqPred _ ==> @EqPred _ ==> iff as EqPred_morph.Add Parametric Morphism T : (@SubPred T) with signature
    @EqPred _ ==> @EqPred _ ==> iff as SubPred_morph.Add Parametric Morphism T : (@InMem T) with signature
    @eq _ ==> @EqMem _ ==> iff as InMem_morph.Add Parametric Morphism T (pT : PredType T) : (@Mem T pT) with signature
  @EqPredType _ _ ==> @EqMem _ as Mem_morhp.Add Parametric Morphism T : (@PredU T) with signature
    @EqPred _ ==> @EqPred _ ==> @EqSimplPred _ as predU_morph.Add Parametric Morphism T : (@PredI T) with signature
    @EqPred _ ==> @EqPred _ ==> @EqPred _ as predI_morph.Add Parametric Morphism T : (@PredC T) with signature
    @EqPred _ ==> @EqPred _ as predC_morph.

(* Specifications: *)
Lemma subp_refl (p : Pred T) : p <=p p.
Lemma subp_asym (p1 p2 : Pred T) : p1 <=p p2 -> p2 <=p p1 -> p1 =p p2.
Lemma subp_trans (p2 p1 p3 : Pred T) : p1 <=p p2 -> p2 <=p p3 -> p1 <=p p3.
Lemma subp_or (p1 p2 q : Pred T) : p1 <=p q /\ p2 <=p q <-> p1 +p p2 <=p q.
Lemma subp_and (p1 p2 q : Pred T) : q <=p p1 /\ q <=p p2 <-> q <=p p1 *p p2.
Lemma subp_orl (p1 p2 q : Pred T) : p1 <=p p2 -> p1 +p q <=p p2 +p q.
Lemma subp_orr (p1 p2 q : Pred T) : p1 <=p p2 -> q +p p1 <=p q +p p2.
Lemma subp_andl (p1 p2 q : Pred T) : p1 <=p p2 -> p1 *p q <=p p2 *p q.
Lemma subp_andr (p1 p2 q : Pred T) : p1 <=p p2 -> q *p p1 <=p q *p p2.