End NatChain.
(*********)
(* CPO's *)
(*********)
Module CPO.
Section RawMixin.
Record mixin_of (T : poset) := Mixin {
mx_lim : chain T -> T;
_ : forall (s : chain T) x, x \In s -> x <== mx_lim s;
_ : forall (s : chain T) x,
(forall y, y \In s -> y <== x) -> mx_lim s <== x}.
End RawMixin.
Section ClassDef.
Record class_of (T : Type) := Class {
base : Poset.class_of T;
mixin : mixin_of (Poset.Pack base T)}.
Local Coercion base : class_of >-> Poset.class_of.
Structure type : Type := Pack {sort; _ : class_of sort; _ : Type}.
Local Coercion sort : type >-> Sortclass.
Variables (T : Type) (cT : type).
Definition class := let: Pack _ c _ as cT' := cT return class_of cT' in c.
Definition clone c of phant_id class c := @Pack T c T.
Definition pack b0 (m0 : mixin_of (Poset.Pack b0 T)) :=
fun m & phant_id m0 m => Pack (@Class T b0 m) T.
Definition poset := Poset.Pack class cT.
Definition lim (s : chain poset) : cT := mx_lim (mixin class) s.
End ClassDef.
Module Import Exports.
Coercion base : class_of >-> Poset.class_of.
Coercion sort : type >-> Sortclass.
Coercion poset : type >-> Poset.type.
Canonical Structure poset.
Notation cpo := type.
Notation CPOMixin := Mixin.
Notation CPO T m := (@pack T _ _ m id).
Notation "[ 'cpo' 'of' T 'for' cT ]" := (@clone T cT _ idfun)
(at level 0, format "[ 'cpo'  'of'  T  'for'  cT ]") : form_scope.
Notation "[ 'cpo' 'of' T ]" := (@clone T _ _ id)
(at level 0, format "[ 'cpo'  'of'  T ]") : form_scope.
Arguments CPO.lim {cT}.
Notation lim := CPO.lim.
Section Laws.
Variable D : cpo.

(* Specifications: *)
Lemma limP (s : chain D) x : x \In s -> x <== lim s.
Lemma chain_clos_idemp (s : Pred T) :
chain_closed s -> chain_closure s =p s.
Lemma chain_clos_mono (s1 s2 : Pred T) :
s1 <=p s2 -> chain_closure s1 <=p chain_closure s2.
(* intersection of admissible sets is admissible *)
Lemma chain_closI (s1 s2 : Pred T) :
chain_closed s1 -> chain_closed s2 -> chain_closed (PredI s1 s2).