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
  }.Class Monad (M : Type -> Type) :=
  { mreturn : forall {A : Type}, A -> M A
  ; mbind   : forall {A B : Type}, M A -> (A -> M B) -> M B
  }.Class Monad (M : Type -> Type) :=
  { mreturn : forall {A : Type}, A -> M A
  ; mbind   : forall {A B : Type}, M A -> (A -> M B) -> M B
  }.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).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
  }.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
  }.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
  }.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
  }.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
  }.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
  }.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
  }.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
  }.

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