End Lemmas.
End Exports.
End CancellativePCM.
Export CancellativePCM.Exports.
(***************)
(* Topped PCMs *)
(***************)
(* PCM with an explicit undef value *)
(* we will want these constants to be decidable *)
(* so we also add unitb, to test if an element is unit *)
(* for undefb, that should be valid, so we don't add anything special *)
(* OTOH, unit should not be decomposable *)
Module TPCM.
Record mixin_of (U : pcm) := Mixin {
undef_op : U;
unitb_op : U -> bool;
_ : forall x, reflect (x = Unit) (unitb_op x);
(* next one doesn't hold of max PCM, so remove eventually *)
_ : forall x y : U, x \+ y = Unit -> x = Unit /\ y = Unit;
(* _ : forall x y z : U, valid (x \+ y \+ z) = [&& valid (x \+ y), valid (y \+ z) & valid (x \+ z)]; *)
_ : ~~ valid undef_op;
_ : forall x, undef_op \+ x = undef_op}.
Section ClassDef.
Record class_of (U : Type) := Class {
base : PCM.mixin_of U;
mixin : mixin_of (PCM.Pack base)}.
Local Coercion base : class_of >-> PCM.mixin_of.
Structure type : Type := Pack {sort : Type; _ : class_of sort}.
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.
(* produce a topped pcm out of the mixin *)
(* equalize m0 and m by means of a phantom *)
Definition pack b0 (m0 : mixin_of (PCM.Pack b0)) :=
fun m & phant_id m0 m => Pack (@Class T b0 m).
Definition pcm := PCM.Pack class.
Definition unitb := unitb_op (mixin class).
Definition undef : pcm := undef_op (mixin class).
End ClassDef.
Module Exports.
Coercion base : class_of >-> PCM.mixin_of.
Coercion sort : type >-> Sortclass.
Coercion pcm : type >-> PCM.type.
Canonical Structure pcm.
Notation tpcm := type.
Notation TPCMMixin := Mixin.
Notation TPCM T m := (@pack T _ _ m id).
Notation "[ 'tpcm' 'of' T 'for' cT ]" := (@clone T cT _ id)
(at level 0, format "[ 'tpcm'  'of'  T  'for' cT ]") : pcm_scope.
Notation "[ 'tpcm' 'of' T ]" := (@clone T _ _ id)
(at level 0, format "[ 'tpcm'  'of'  T ]") : pcm_scope.
Notation undef := undef.
Notation unitb := unitb.
Arguments undef [cT].
Prenex Implicits undef.
Section Lemmas.
Variable U : tpcm.

(* Specifications: *)
Lemma unitbP (x : U) : reflect (x = Unit) (unitb x).
Lemma valid_undefN : ~~ valid (@undef U).
End BigPartialMorph.