Any list comprehension can be correspondingly coded with list monad's do
notation.
[f x | x <- xs] f <$> xs do { x <- xs ; return (f x) }
[f x | f <- fs, x <- xs] fs <*> xs do { f <- fs ; x <- xs ; return (f x) }
[y | x <- xs, y <- f x] f =<< xs do { x <- xs ; y <- f x ; return y }
The guards can be handled using Control.Monad.guard
:
[x | x <- xs, even x] do { x <- xs ; guard (even x) ; return x }