(* extract a value from a distribution arbitrarily, in this case
   taking the first elt of the underlying list *)
Definition peek {X} (d : dist X) : X :=
  match d with
  | {| dist_pmf := dist; dist_law := law |} =>
    match dist as l return ((sum_dist l == 1)%Q -> X) with
    | [] => fun law => 
      match zero_one_neq law with end
    | (x,_) :: _ => fun _ => x
       end law
  end.(* WARNING: distribution should contain non-zero weighted support *)
Definition dist_lift {X} (P : X -> Prop) (d : dist X) : Prop.

(* Specifications: *)
Lemma dist_lift_peek {X} (P : X -> Prop) (dx : dist X) : dist_lift P dx -> P (peek dx).
Lemma dist_lift_ret : forall (X : Type) (x : X) (P : X -> Prop), P x -> dist_lift P (mreturn x).
Lemma dist_lift_weaken {X} (P Q : X -> Prop) : (forall x, P x -> Q x) -> forall d, dist_lift P d -> dist_lift Q d.
Lemma dist_split {X} (P Q : X -> Prop) d : dist_lift P d -> dist_lift Q d -> dist_lift (fun x => P x /\ Q x) d.
Lemma dist_true {X} (d : dist X) : dist_lift (fun _ => True) d.
Lemma dist_comm {X Y} (P : X -> Y -> Prop) (m1 : dist X) (m2 : dist Y) : dist_lift (fun y => dist_lift (fun x => P x y) m1) m2 -> dist_lift (fun x => dist_lift (P x) m2) m1.
Lemma dist_lift_peek {X} (P : X -> Prop) (dx : dist X) : dist_lift P dx -> P (peek dx).
Lemma dist_lift_ret : forall (X : Type) (x : X) (P : X -> Prop), P x -> dist_lift P (mreturn x).
Lemma dist_lift_weaken {X} (P Q : X -> Prop) : (forall x, P x -> Q x) -> forall d, dist_lift P d -> dist_lift Q d.
Lemma dist_split {X} (P Q : X -> Prop) d : dist_lift P d -> dist_lift Q d -> dist_lift (fun x => P x /\ Q x) d.
Lemma dist_true {X} (d : dist X) : dist_lift (fun _ => True) d.
Lemma dist_comm {X Y} (P : X -> Y -> Prop) (m1 : dist X) (m2 : dist Y) : dist_lift (fun y => dist_lift (fun x => P x y) m1) m2 -> dist_lift (fun x => dist_lift (P x) m2) m1.