Definition count {X} `{Finite X} (p : X -> bool) : nat :=
  length (filter p enum).Global Instance Finite_prod {X Y} `{Finite X, Finite Y} : Finite (X * Y).(*model *)
Inductive ID := A | B.(*model *)
Inductive ID := A | B.(*model *)
Inductive ID := A | B.Record PosMap : Type := {
  A_path : bool;
  B_path : bool
  }.Record PosMap : Type := {
  A_path : bool;
  B_path : bool
  }.Record PosMap : Type := {
  A_path : bool;
  B_path : bool
  }.Definition M :=
  StateT PosMap dist.Variant op :=
  Acc (id : ID).Variant op :=
  Acc (id : ID).Definition lookup (id : ID) : PosMap -> bool :=
  match id with
  | A => A_path
  | B => B_path
  end.Definition update (id : ID) (p : bool) (s : PosMap) : PosMap :=
  match id with
  | A => {|
      A_path := p;
      B_path := B_path s;
    |}
  | B => {|
      A_path := A_path s;
      B_path := p;
    |}
  end.Definition hoare {X} (Pre : dist PosMap -> Prop) (Post : dist (X * PosMap) -> Prop)
  (m : M X) : Prop :=
  forall d, Pre d -> Post (mbind d m).Definition eval (o : op) : M bool :=
  match o with
  | Acc r => acc r
  end.Fixpoint vec n X : Type :=
  match n with
  | 0 => unit
  | S m => X * vec m X
  end.Definition eval_dist {X} (mu : dist X) (f : X -> bool) : Q :=
  sum_dist (filter_dist (dist_pmf mu) f).Definition conj_pred {X Y} (E1 : X -> bool) (E2 : Y -> bool) : X * Y -> bool :=
  fun p => E1 (fst p) && E2 (snd p).Definition Q_of_nat (n : nat) : Q :=
  inject_Z (Z.of_nat n).Definition uniform {X} `{EqDec X} (d : dist X) : Prop :=
  forall x x' : X,
    eval_dist d (Classes.eqb x) == eval_dist d (Classes.eqb x').Fixpoint Qsum (l : list Q) : Q :=
  match l with
  | [] => 0
  | q :: l' => q + Qsum l'
  end.Definition sigma_dist {X} (d : dist X) (f : X -> Q -> Q) : Q :=
  Qsum (map (fun p => f (fst p) (snd p)) (dist_pmf d)).

(* Specifications: *)
Lemma sigma_dist_eq {X} (d : dist X) (f g : X -> Q -> Q) : (forall x q, f x q == g x q) -> sigma_dist d f == sigma_dist d g.
Lemma sigma_dist_eq {X} (d : dist X) (f g : X -> Q -> Q) : (forall x q, f x q == g x q) -> sigma_dist d f == sigma_dist d g.