Definition Mmono {A:Type} (m:monad A) :=
forall st st', st ≤ st' → fst (Meval m st) ≤ fst (Meval m st').(* We need a very strong monotonicity for the functions used by Mbind and Mbind2 *)
Definition Mmono_one {A B:Type} (f: A → monad B) :=
(∀ a, Mmono (f a)) ∧
(∀ ma st st' n, st ≤ st' → Mmono ma →
  fst (Meval (f (snd (Meval ma st))) n) ≤ fst (Meval (f (snd (Meval ma st'))) n)).Definition Mmono_two {A B C:Type} (f: A → B → monad C) :=
(∀ a b, Mmono (f a b)) ∧
(∀ {D:Type} (mab: monad (A*D)) b st st' n, st ≤ st' → Mmono mab →
  fst (Meval (f (fst (snd (Meval mab st))) b) n) ≤ fst (Meval (f (fst (snd (Meval mab st'))) b) n)) ∧ 
(∀ {D:Type} a (mab: monad (D*B)) st st' n, st ≤ st' → Mmono mab →
  fst (Meval (f a (snd (snd (Meval mab st)))) n) ≤ fst (Meval (f a (snd (snd (Meval mab st')))) n)).Definition Mreturn {A:Type} (x:A) := (λ s, (s, x)):monad A.

(* Specifications: *)
Lemma Mreturn_eq {A:Type} (x:A): Meq (Mreturn x).
Lemma Mreturn_le {A:Type} (x:A): Mle (Mreturn x).
Lemma Mreturn_mono {A:Type} (x:A): Mmono (Mreturn x).