module Control.Monad( MonadPlus(mzero, mplus), join, guard, when, unless, ap, msum, filterM, mapAndUnzipM, zipWithM, zipWithM_, foldM, liftM, liftM2, liftM3, liftM4, liftM5, foldM_,replicateM,replicateM_,(>=>),(<=<),forever, -- ...and what the Prelude exports Monad((>>=), (>>), return, fail), Functor(fmap), mapM, mapM_, sequence, sequence_, (=<<) )where import Lhc.Basics class Monad m => MonadPlus m where mzero :: m a mplus :: m a -> m a -> m a mzero = fail "mzero" instance MonadPlus Maybe where mzero = Nothing Nothing `mplus` y = y x `mplus` _ = x instance MonadPlus [] where mzero = [] mplus = (++) -- Functions msum :: MonadPlus m => [m a] -> m a msum xs = foldr mplus mzero xs join :: (Monad m) => m (m a) -> m a join x = x >>= id when :: (Monad m) => Bool -> m () -> m () when p s = if p then s else return () unless :: (Monad m) => Bool -> m () -> m () unless p s = when (not p) s ap :: (Monad m) => m (a -> b) -> m a -> m b ap = liftM2 ($) guard :: MonadPlus m => Bool -> m () guard p = if p then return () else mzero mapAndUnzipM :: (Monad m) => (a -> m (b,c)) -> [a] -> m ([b], [c]) mapAndUnzipM f xs = sequence (map f xs) >>= return . unzip zipWithM :: (Monad m) => (a -> b -> m c) -> [a] -> [b] -> m [c] zipWithM f xs ys = sequence (zipWith f xs ys) zipWithM_ :: (Monad m) => (a -> b -> m c) -> [a] -> [b] -> m () zipWithM_ f xs ys = sequence_ (zipWith f xs ys) foldM :: (Monad m) => (a -> b -> m a) -> a -> [b] -> m a foldM f a [] = return a foldM f a (x:xs) = f a x >>= \ y -> foldM f y xs filterM :: Monad m => (a -> m Bool) -> [a] -> m [a] filterM p [] = return [] filterM p (x:xs) = do { b <- p x; ys <- filterM p xs; return (if b then (x:ys) else ys) } liftM :: (Monad m) => (a -> b) -> (m a -> m b) liftM f = \a -> do { a' <- a; return (f a') } liftM2 :: (Monad m) => (a -> b -> c) -> (m a -> m b -> m c) liftM2 f = \a b -> do { a' <- a; b' <- b; return (f a' b') } liftM3 :: (Monad m) => (a -> b -> c -> d) -> (m a -> m b -> m c -> m d) liftM3 f = \a b c -> do { a' <- a; b' <- b; c' <- c; return (f a' b' c') } liftM4 :: (Monad m) => (a -> b -> c -> d -> e) -> (m a -> m b -> m c -> m d -> m e) liftM4 f = \a b c d -> do { a' <- a; b' <- b; c' <- c; d' <- d; return (f a' b' c' d') } liftM5 :: (Monad m) => (a -> b -> c -> d -> e -> f) -> (m a -> m b -> m c -> m d -> m e -> m f) liftM5 f = \a b c d e -> do { a' <- a; b' <- b; c' <- c; d' <- d; e' <- e; return (f a' b' c' d' e') } -- extensions -- | Like 'foldM', but discards the result. foldM_ :: (Monad m) => (a -> b -> m a) -> a -> [b] -> m () foldM_ f a xs = foldM f a xs >> return () -- | @'replicateM' n act@ performs the action @n@ times, -- gathering the results. replicateM :: (Monad m) => Int -> m a -> m [a] replicateM n x = sequence (replicate n x) -- | Like 'replicateM', but discards the result. replicateM_ :: (Monad m) => Int -> m a -> m () replicateM_ n x = sequence_ (replicate n x) -- | 'forM' is 'mapM' with its arguments flipped forM :: Monad m => [a] -> (a -> m b) -> m [b] {-# INLINE forM #-} forM = flip mapM -- | 'forM_' is 'mapM_' with its arguments flipped forM_ :: Monad m => [a] -> (a -> m b) -> m () {-# INLINE forM_ #-} forM_ = flip mapM_ infixr 1 <=<, >=> -- | Left-to-right Kleisli composition of monads. (>=>) :: Monad m => (a -> m b) -> (b -> m c) -> (a -> m c) f >=> g = \x -> f x >>= g -- | Right-to-left Kleisli composition of monads. '(>=>)', with the -- arguments flipped (<=<) :: Monad m => (b -> m c) -> (a -> m b) -> (a -> m c) (<=<) = flip (>=>) -- | @'forever' act@ repeats the action infinitely. forever :: (Monad m) => m a -> m () forever a = a >> forever a