Section MonadToys.
Definition liftM (A B: Set) (f: A -> B) (M: Monad) (x: M A): M B :=
xv <- x ; ret (f xv).
Definition liftM2 (A B C: Set) (f: A -> B -> C) (M: Monad) (x: M A) (y: M B): M C :=
xv <- x ; yv <- y ; ret (f xv yv).
Fixpoint foldlM {A B: Set} {M: Monad} (f: A -> B -> M A) (x: A) (l: list B) {struct l}: M A :=
match l with
| nil => ret x
| h :: t => fax <- f x h ; foldlM f fax t
end. (* Haskell's foldM *)
Fixpoint foldrM {A B: Set} {M: Monad} (f: B -> A -> M A) (x: A) (l: list B) {struct l}: M A :=
match l with
| nil => ret x
| h :: t => t' <- foldrM f x t; f h t'
end. (* missing in Haskell.. *)

Lemma foldlM_cons (A B: Set) (M: Monad) (f: A -> B -> M A) (x: A) (h: B) (t: list B):
foldlM f x (h :: t) = fax <- f x h ; foldlM f fax t.