summaryrefslogtreecommitdiff
path: root/ghc/lib/std/Monad.lhs
diff options
context:
space:
mode:
Diffstat (limited to 'ghc/lib/std/Monad.lhs')
-rw-r--r--ghc/lib/std/Monad.lhs118
1 files changed, 118 insertions, 0 deletions
diff --git a/ghc/lib/std/Monad.lhs b/ghc/lib/std/Monad.lhs
new file mode 100644
index 0000000000..2be1dba439
--- /dev/null
+++ b/ghc/lib/std/Monad.lhs
@@ -0,0 +1,118 @@
+%
+% (c) The AQUA Project, Glasgow University, 1994-1996
+%
+\section[Monad]{Module @Monad@}
+
+\begin{code}
+{-# OPTIONS -fno-implicit-prelude #-}
+
+module Monad (
+ Functor(..),
+ Monad(..), MonadZero(..), MonadPlus(..),
+
+ -- Prelude monad functions
+ accumulate, sequence,
+ mapM, mapM_, guard, filter, concat, applyM,
+
+ -- Standard Monad interface:
+ join, -- :: (Monad m) => m (m a) -> m a
+ mapAndUnzipM, -- :: (Monad m) => (a -> m (b,c)) -> [a] -> m ([b], [c])
+ zipWithM, -- :: (Monad m) => (a -> b -> m c) -> [a] -> [b] -> m [c]
+ zipWithM_, -- :: (Monad m) => (a -> b -> m c) -> [a] -> [b] -> m ()
+ foldM, -- :: (Monad m) => (a -> b -> m a) -> a -> [b] -> m a
+ when, -- :: (Monad m) => Bool -> m () -> m ()
+ unless, -- :: (Monad m) => Bool -> m () -> m ()
+ ap, -- :: (Monad m) => (m (a -> b)) -> (m a) -> m b
+ liftM, liftM2,
+ liftM3, liftM4,
+ liftM5
+ ) where
+
+import PrelList
+import PrelTup
+import PrelBase
+\end{code}
+
+%*********************************************************
+%* *
+\subsection{Functions mandated by the Prelude}
+%* *
+%*********************************************************
+
+\begin{code}
+accumulate :: Monad m => [m a] -> m [a]
+accumulate [] = return []
+accumulate (m:ms) = do { x <- m; xs <- accumulate ms; return (x:xs) }
+
+sequence :: Monad m => [m a] -> m ()
+sequence = foldr (>>) (return ())
+
+mapM :: Monad m => (a -> m b) -> [a] -> m [b]
+mapM f as = accumulate (map f as)
+
+mapM_ :: Monad m => (a -> m b) -> [a] -> m ()
+mapM_ f as = sequence (map f as)
+
+guard :: MonadZero m => Bool -> m ()
+guard p = if p then return () else zero
+
+-- This subsumes the list-based filter function.
+
+filter :: MonadZero m => (a -> Bool) -> m a -> m a
+filter p = applyM (\x -> if p x then return x else zero)
+
+-- This subsumes the list-based concat function.
+
+concat :: MonadPlus m => [m a] -> m a
+concat = foldr (++) zero
+
+applyM :: Monad m => (a -> m b) -> m a -> m b
+applyM f x = x >>= f
+\end{code}
+
+
+%*********************************************************
+%* *
+\subsection{Other monad functions}
+%* *
+%*********************************************************
+
+\begin{code}
+join :: (Monad m) => m (m a) -> m a
+join x = x >>= id
+
+mapAndUnzipM :: (Monad m) => (a -> m (b,c)) -> [a] -> m ([b], [c])
+mapAndUnzipM f xs = accumulate (map f xs) >>= return . unzip
+
+zipWithM :: (Monad m) => (a -> b -> m c) -> [a] -> [b] -> m [c]
+zipWithM f xs ys = accumulate (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 >>= \fax -> foldM f fax xs
+
+unless :: (Monad m) => Bool -> m () -> m ()
+unless p s = if p then return () else s
+
+when :: (Monad m) => Bool -> m () -> m ()
+when p s = if p then s else return ()
+
+ap :: (Monad m) => m (a->b) -> m a -> m b
+ap = liftM2 ($)
+
+liftM :: (Monad m) => (a1 -> r) -> m a1 -> m r
+liftM2 :: (Monad m) => (a1 -> a2 -> r) -> m a1 -> m a2 -> m r
+liftM3 :: (Monad m) => (a1 -> a2 -> a3 -> r) -> m a1 -> m a2 -> m a3 -> m r
+liftM4 :: (Monad m) => (a1 -> a2 -> a3 -> a4 -> r) -> m a1 -> m a2 -> m a3 -> m a4 -> m r
+liftM5 :: (Monad m) => (a1 -> a2 -> a3 -> a4 -> a5 -> r) -> m a1 -> m a2 -> m a3 -> m a4 -> m a5 -> m r
+
+liftM f m1 = do { x1 <- m1; return (f x1) }
+liftM2 f m1 m2 = do { x1 <- m1; x2 <- m2; return (f x1 x2) }
+liftM3 f m1 m2 m3 = do { x1 <- m1; x2 <- m2; x3 <- m3; return (f x1 x2 x3) }
+liftM4 f m1 m2 m3 m4 = do { x1 <- m1; x2 <- m2; x3 <- m3; x4 <- m4; return (f x1 x2 x3 x4) }
+liftM5 f m1 m2 m3 m4 m5 = do { x1 <- m1; x2 <- m2; x3 <- m3; x4 <- m4; x5 <- m5; return (f x1 x2 x3 x4 x5) }
+
+\end{code}