(* Definition castEqX T (t t' : eqTypeX) (r : t = t') (e : T t) := *)
(*   match r in (_ = t') return T t' with erefl => e end. *)
(* Definition eqcEqX X m' (r : m' = m') (e : X m') : castEqX r e = e. *)
(* Proof. by move: r; apply: Streicher_K. Qed. *)
Module Coherence.
Section CohDef.
(* Represent nodes as a decidable predicate, which depends on the state *)
Variable nodes: dstatelet -> pred nid.
Notation protocol_soup  := (soup (TaggedMessage)).
Structure mixin_of (coh : Pred dstatelet) := Mixin {
_   : forall d, coh d -> valid (dstate d);
_   : forall d, coh d -> valid (dsoup d);
_   : forall d, coh d -> dom (dstate d) =i nodes d;
}.
End CohDef.
Section ClassDef.
Variable nodes: dstatelet -> pred nid.
Notation class_of := mixin_of (only parsing).
Structure cohpred : Type := Pack {sort : dstatelet -> Prop;
_ : class_of nodes sort}.
Local Coercion sort : cohpred >-> Funclass.
Variables (T : dstatelet -> Prop) (cT : cohpred).
Definition class := let: Pack _ c as cT' := cT
return class_of nodes cT' in c.
Definition pack c := @Pack T c.
Definition clone := fun c & T = cT & phant_id (pack c) cT => pack c.
End ClassDef.
Module Exports.
Section Exports.
Variable Lstate : Type.
Variable nodes: dstatelet -> pred nid.
Coercion sort : cohpred >-> Funclass.
Definition cohpred := cohpred.
Definition CohPredMixin := Mixin.
Definition CohPred T m := (@pack T m).
Notation "[ 'cohPredMixin' 'of' T ]" := (class _ : mixin_of T)
(at level 0, format "[ 'cohPredMixin'  'of'  T ]") : form_scope.
Notation "[ 'cohpred' 'of' T 'for' C ]" := (@clone T C _ (erefl _) id)
(at level 0, format "[ 'cohpred'  'of'  T  'for'  C ]") : form_scope.
Notation "[ 'cohpred' 'of' T ]" := (@clone T _ _ (erefl _) id)
(at level 0, format "[ 'cohpred'  'of'  T ]") : form_scope.
Canonical cohpred_PredType := mkPredType (@sort nodes).
Variable coh : cohpred nodes.

(* Specifications: *)
Lemma cohVl d : d \In coh -> valid (dstate d).
Lemma pred0v2 d: cohMT d -> valid (dsoup d).
Lemma pred0v3 d: cohMT d -> dom (dstate d) =i [::].