[project @ 1996-12-19 18:35:23 by simonpj]
[ghc-hetmet.git] / ghc / lib / required / Monad.lhs
1 %
2 % (c) The AQUA Project, Glasgow University, 1994-1996
3 %
4
5 \section[Monad]{Module @Monad@}
6
7 \begin{code}
8 module Monad (
9     Functor(..), Monad(..), MonadZero(..), MonadPlus(..),
10
11         -- Prelude monad functions
12     accumulate, sequence, mapM, mapM_, guard, filter, concat, applyM,
13
14         -- Other monad functions
15     join, mapAndUnzipM, zipWithM, foldM, when, unless, ap, unless, when,
16     liftM, liftM2, liftM3, liftM4, liftM5
17   ) where
18
19 import Prelude  ()
20 import PrelList
21 import PrelTup
22 import PrelBase
23 \end{code}
24
25 %*********************************************************
26 %*                                                      *
27 \subsection{Functions mandated by the Prelude}
28 %*                                                      *
29 %*********************************************************
30
31 \begin{code}
32 accumulate      :: Monad m => [m a] -> m [a] 
33 accumulate []     = return []
34 accumulate (m:ms) = do { x <- m; xs <- accumulate ms; return (x:xs) }
35
36 sequence        :: Monad m => [m a] -> m () 
37 sequence        =  foldr (>>) (return ())
38
39 mapM            :: Monad m => (a -> m b) -> [a] -> m [b]
40 mapM f as       =  accumulate (map f as)
41
42 mapM_           :: Monad m => (a -> m b) -> [a] -> m ()
43 mapM_ f as      =  sequence (map f as)
44
45 guard           :: MonadZero m => Bool -> m ()
46 guard p         =  if p then return () else zero
47
48 -- This subsumes the list-based filter function.
49
50 filter          :: MonadZero m => (a -> Bool) -> m a -> m a
51 filter p        =  applyM (\x -> if p x then return x else zero)
52
53 -- This subsumes the list-based concat function.
54
55 concat          :: MonadPlus m => [m a] -> m a
56 concat          =  foldr (++) zero
57  
58 applyM          :: Monad m => (a -> m b) -> m a -> m b
59 applyM f x      =  x >>= f
60 \end{code}
61
62
63 %*********************************************************
64 %*                                                      *
65 \subsection{Other monad functions}
66 %*                                                      *
67 %*********************************************************
68
69 \begin{code}
70 join             :: (Monad m) => m (m a) -> m a
71 join x           = x >>= id
72
73 mapAndUnzipM     :: (Monad m) => (a -> m (b,c)) -> [a] -> m ([b], [c])
74 mapAndUnzipM f xs = accumulate (map f xs) >>= return . unzip
75
76 zipWithM         :: (Monad m) => (a -> b -> m c) -> [a] -> [b] -> m [c]
77 zipWithM f xs ys = accumulate (zipWith f xs ys)
78
79 foldM            :: (Monad m) => (a -> b -> m a) -> a -> [b] -> m a
80 foldM f a []     = return a
81 foldM f a (x:xs) = f a x >>= \fax -> foldM f fax xs
82
83 unless           :: (Monad m) => Bool -> m () -> m ()
84 unless p s       =  if p then return () else s
85
86 when             :: (Monad m) => Bool -> m () -> m ()
87 when p s         =  if p then s else return ()
88
89 liftM   :: (Monad m) => (a1 -> r) -> m a1 -> m r
90 liftM2  :: (Monad m) => (a1 -> a2 -> r) -> m a1 -> m a2 -> m r
91 liftM3  :: (Monad m) => (a1 -> a2 -> a3 -> r) -> m a1 -> m a2 -> m a3 -> m r
92 liftM4  :: (Monad m) => (a1 -> a2 -> a3 -> a4 -> r) -> m a1 -> m a2 -> m a3 -> m a4 -> m r
93 liftM5  :: (Monad m) => (a1 -> a2 -> a3 -> a4 -> a5 -> r) -> m a1 -> m a2 -> m a3 -> m a4 -> m a5 -> m r
94
95 liftM f m1              = do { x1 <- m1; return (f x1) }
96 liftM2 f m1 m2          = do { x1 <- m1; x2 <- m2; return (f x1 x2) }
97 liftM3 f m1 m2 m3       = do { x1 <- m1; x2 <- m2; x3 <- m3; return (f x1 x2 x3) }
98 liftM4 f m1 m2 m3 m4    = do { x1 <- m1; x2 <- m2; x3 <- m3; x4 <- m4; return (f x1 x2 x3 x4) }
99 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) }
100
101 ap :: (Monad m) => m (a->b) -> m a -> m b
102 ap = liftM2 ($)
103
104 \end{code}