(*********************)
(* PCM constructions *)
(*********************)
(* nats with addition are a pcm *)
Definition natPCMMix :=
PCMMixin addnC addnA add0n (fun x y => @id true) (erefl _).
Canonical natPCM := Eval hnf in PCM nat natPCMMix.
(* also with multiplication, but we don't make that one canonical *)
Definition multPCMMix :=
PCMMixin mulnC mulnA mul1n (fun x y => @id true) (erefl _).
Definition multPCM := Eval hnf in PCM nat multPCMMix.
(* with max too *)
Definition maxPCMMix :=
PCMMixin maxnC maxnA max0n (fun x y => @id true) (erefl _).
Definition maxPCM := Eval hnf in PCM nat maxPCMMix.
(* bools with disjunction are a pcm *)
Definition bool_orPCMMix :=
PCMMixin orbC orbA orFb (fun x y => @id true) (erefl _).
Definition bool_orPCM := Eval hnf in PCM bool bool_orPCMMix.
(* cartesian product of pcms is a pcm *)
Module ProdPCM.
Section ProdPCM.
Variables (U V : pcm).
Local Notation tp := (U * V)%type.
Definition pvalid := [fun x : tp => valid x.1 && valid x.2].
Definition pjoin := [fun x1 x2 : tp => (x1.1 \+ x2.1, x1.2 \+ x2.2)].
Definition punit : tp := (Unit, Unit).

(* Specifications: *)
Lemma joinC x y : pjoin x y = pjoin y x.
Lemma joinA x y z : pjoin x (pjoin y z) = pjoin (pjoin x y) z.
Lemma validL x y : pvalid (pjoin x y) -> pvalid x.
Lemma unitL x : pjoin punit x = x.
Lemma prod_join0E (x y : prodPCM U V) : x \+ y = Unit -> x = Unit /\ y = Unit.
*)
Lemma prod_valid_undef : ~~ valid (@undef U, @undef V).