Definition eval_dist {X} (mu : dist X) (f : X -> bool) : Q :=
  sum_dist (filter_dist (dist_pmf mu) f).Goal eval_dist coin_flip_two (fun '(p,q) => andb p q) = 1 / 4.(* mapM :: Monad m => (a -> m b) -> t a -> m (t b) *)

Definition mapM {A B M} `{Monad M} (f : A -> M B) (l : list (M A)) 
    :list (M B) := 
  (List.map
     (fun s => mbind s f) l).Definition distr_eqv {X} d d' : Prop :=
  forall (E : X -> bool), 
  Qeq (eval_dist d E) (eval_dist d' E).(* Definition acc_list_1 {C : Config} (arg_list : list (block_id * operation)) (s : state) : *)
(*   list (dist path). *)
(*   pose (List.map (fun '(bid, op) => access bid op) arg_list). *)
(*   refine (List.map _ l). *)
(*   intros prm. *)
(*   specialize (prm s). *)
(*   pose (map fst prm). *)
(*   pose (map fst d). *)
(*   exact d0. *)
(* Defined. *)

Definition acc_dist_list {C : Config}
  (arg_list : list (block_id * operation)) : Poram (list path) :=
  let l := List.map (fun '(bid, op) => access bid op) arg_list in
  let p := sequence l in
  monad_map (List.map fst) p.Definition get_dist_list_bool {C : Config}
  (arg_list : list (block_id * operation))(s : state) : dist (list bool) :=
  monad_map (@List.concat bool) (monad_map fst ((acc_dist_list arg_list) s)).

Lemma state_plift_P_split : forall {C : Config} {S M X} `{PredLift M} (P Q : X -> Prop) (Pre Post: S -> Prop) (s : StateT S M X), state_plift Pre Post P s /\ state_plift Pre Post Q s -> state_plift Pre Post (fun x => (P x /\ Q x)) s.