Global Instance NatOrd : Ord nat := {
ord_dec := Nat.compare;
ord_refl := Nat.compare_refl;
ord_eq := Nat.compare_eq;
ord_lt_trans := compare_lt_trans
}.
Class Monad (M : Type -> Type) :=
{ mreturn : forall {A : Type}, A -> M A
; mbind   : forall {A B : Type}, M A -> (A -> M B) -> M B
}.
Module MonadNotation.
Notation "x <- c1 ;; c2" := (mbind c1 (fun x => c2))
(at level 100, c1 at next level, right associativity).
Notation "e1 ;; e2" := (_ <- e1 ;; e2)
(at level 100, right associativity).
Infix ">>=" := mbind (at level 50, left associativity).
End MonadNotation.
Class PredLift M `{Monad M} := {
plift {X} : (X -> Prop) -> M X -> Prop;
plift_ret {X} : forall x (P : X -> Prop), P x -> plift P (mreturn x);
plift_bind {X Y} : forall (P : X -> Prop) (Q : Y -> Prop)
(mx : M X) (f : X -> M Y), plift P mx ->
(forall x, P x -> plift Q (f x)) ->
plift Q (mbind mx f);
plift_weaken {X} (P Q : X -> Prop) : (forall x, P x -> Q x) ->
forall m, plift P m -> plift Q m;
plift_true {X} : forall (m : M X), plift (fun _ => True) m;
plift_split {X} (P Q : X -> Prop) : forall m,
plift P m -> plift Q m -> plift (fun x => P x /\ Q x) m;
plift_comm {X Y} (P : X -> Y -> Prop) (m1 : M X) (m2 : M Y) :
plift (fun y => plift (fun x => P x y) m1) m2 ->
plift (fun x => plift (P x) m2) m1
}.

Lemma plift_triv {M} `{PredLift M} {X} (P : X -> Prop) (m : M X) :
(forall x, P x) -> plift P m.