Fixpoint lm_to_ml {A:Type} (lm:list (monad A)) : monad (list A):=
match lm with
| [] => Mreturn []
| m::ms => m >>::(lm_to_ml ms)
end.

(* Specifications: *)
Lemma empty_lm_to_ml_eq {A:Type}: Meq (@lm_to_ml A []).
Lemma all_le_lm_to_ml_le {A:Type} (lm:list (monad A)):
Forall Mle lm → Mle (lm_to_ml lm).
Lemma all_lt_lm_to_ml_le {A:Type} (lm:list (monad A)):
(Forall Mlt lm) → Mle (lm_to_ml lm).
Lemma lm_to_ml_length {A:Type} (lm: list (monad A))  st:
length (snd (lm_to_ml lm st)) = length lm.
Lemma lm_to_ml_ind {A:Type} (P:A→Prop) (lm:list (monad A)):
(∀ ma, ma ∈ lm → ∀ st, P (snd (ma st))) →
∀ st, Forall P (snd ((lm_to_ml lm) st)).
Lemma all_mono_lm_to_ml_mono {A:Type} (lm: list (monad A)):
Forall Mmono lm → Mmono (lm_to_ml lm).
Lemma in_lm_to_ml {A:Type} (a:A) mal st:
a ∈ snd ((lm_to_ml mal) st) → ∃ ma st', ma ∈ mal ∧ a = snd (ma st').
Lemma lm_to_ml_incl {A B:Type} (mal:list (monad A)) (f:A→B) g st:
(∀ st ma, ma ∈ mal → f (snd (ma st)) ∈ g (snd (ma st))) →
incl (map f (snd ((lm_to_ml mal) st)))
(concat (map g (snd ((lm_to_ml mal) st)))).
Lemma lm_to_ml_incl_incl {A B C:Type} mal f1 (f2 : A → list B) (g : A → list C) st:
(∀ st ma, ma ∈ mal → incl (flat_map f1 (f2 (snd (ma st)))) (g (snd (ma st)))) →
incl (flat_map f1 (concat (map f2 (snd (lm_to_ml mal st)))))
(concat (map g (snd (lm_to_ml mal st)))).
Lemma lm_to_ml_bounds {R T:Type} n (mtl:list (monad T)) f_low f_up f_in (r: T → list R):
fmono f_low → fmono f_up → Forall Mle mtl →
(∀ mt s n', mt ∈ mtl → n' ∈ map f_in (r (snd (mt s))) → f_low s ≤ n' ≤ f_up (fst (mt s))) →
∀ st st', st ≤ st' →  (* st, st' need to be in the induction hypothesis. *)
n ∈ map f_in (concat (map r (snd (lm_to_ml mtl st')))) →
f_low st ≤ n ≤ f_up (fst (lm_to_ml mtl st')).