Definition bijection {X Y} (f : X -> Y) : Prop :=
  exists g : Y -> X,
    (forall x, g (f x) = x) /\
    (forall y, f (g y) = y).

(* Specifications: *)
Lemma Qsum_map {X} (f g : X -> Q) (xs : list X): (forall x, f x == g x) -> Qsum (map f xs) == Qsum (map g xs).
Lemma uniform_bind_bijection {X Y} `{EqDec X, EqDec Y} (f : X -> Y) (d : dist X) : uniform d -> bijection f -> uniform (mbind d (fun x => mreturn (f x))).
Lemma uniform_bind_bijection_rev {X Y} `{EqDec X, EqDec Y} (f : X -> Y) (d : dist X) : uniform (mbind d (fun x => mreturn (f x))) -> bijection f -> uniform d.
Lemma uniform_snd {X Y} `{Finite X, Finite Y} (d : dist (X * Y)) : uniform d -> uniform (monad_map snd d).
Lemma Qsum_map {X} (f g : X -> Q) (xs : list X): (forall x, f x == g x) -> Qsum (map f xs) == Qsum (map g xs).
Lemma uniform_bind_bijection {X Y} `{EqDec X, EqDec Y} (f : X -> Y) (d : dist X) : uniform d -> bijection f -> uniform (mbind d (fun x => mreturn (f x))).
Lemma uniform_bind_bijection_rev {X Y} `{EqDec X, EqDec Y} (f : X -> Y) (d : dist X) : uniform (mbind d (fun x => mreturn (f x))) -> bijection f -> uniform d.
Lemma uniform_snd {X Y} `{Finite X, Finite Y} (d : dist (X * Y)) : uniform d -> uniform (monad_map snd d).