Generalize `Control.Monad.forever`
[ghc.git] / libraries / base / Control / Monad.hs
1 {-# LANGUAGE Trustworthy #-}
2 {-# LANGUAGE NoImplicitPrelude #-}
3
4 -----------------------------------------------------------------------------
5 -- |
6 -- Module : Control.Monad
7 -- Copyright : (c) The University of Glasgow 2001
8 -- License : BSD-style (see the file libraries/base/LICENSE)
9 --
10 -- Maintainer : libraries@haskell.org
11 -- Stability : provisional
12 -- Portability : portable
13 --
14 -- The 'Functor', 'Monad' and 'MonadPlus' classes,
15 -- with some useful operations on monads.
16
17 module Control.Monad
18 (
19 -- * Functor and monad classes
20
21 Functor(fmap)
22 , Monad((>>=), (>>), return, fail)
23 , MonadPlus(mzero, mplus)
24 -- * Functions
25
26 -- ** Naming conventions
27 -- $naming
28
29 -- ** Basic @Monad@ functions
30
31 , mapM
32 , mapM_
33 , forM
34 , forM_
35 , sequence
36 , sequence_
37 , (=<<)
38 , (>=>)
39 , (<=<)
40 , forever
41 , void
42
43 -- ** Generalisations of list functions
44
45 , join
46 , msum
47 , mfilter
48 , filterM
49 , mapAndUnzipM
50 , zipWithM
51 , zipWithM_
52 , foldM
53 , foldM_
54 , replicateM
55 , replicateM_
56
57 -- ** Conditional execution of monadic expressions
58
59 , guard
60 , when
61 , unless
62
63 -- ** Monadic lifting operators
64
65 , liftM
66 , liftM2
67 , liftM3
68 , liftM4
69 , liftM5
70
71 , ap
72
73 -- ** Strict monadic functions
74
75 , (<$!>)
76 ) where
77
78 import Data.Foldable ( Foldable, sequence_, msum, mapM_, foldlM, forM_ )
79 import Data.Functor ( void )
80 import Data.Traversable ( forM, mapM, sequence )
81
82 import GHC.Base hiding ( mapM, sequence )
83 import GHC.List ( zipWith, unzip, replicate )
84
85 -- -----------------------------------------------------------------------------
86 -- Functions mandated by the Prelude
87
88 -- | @'guard' b@ is @'pure' ()@ if @b@ is 'True',
89 -- and 'empty' if @b@ is 'False'.
90 guard :: (Alternative f) => Bool -> f ()
91 guard True = pure ()
92 guard False = empty
93
94 -- | This generalizes the list-based 'filter' function.
95
96 {-# INLINE filterM #-}
97 filterM :: (Monad m) => (a -> m Bool) -> [a] -> m [a]
98 filterM p = foldr go (return [])
99 where
100 go x r = do
101 flg <- p x
102 ys <- r
103 return (if flg then x:ys else ys)
104
105 infixr 1 <=<, >=>
106
107 -- | Left-to-right Kleisli composition of monads.
108 (>=>) :: Monad m => (a -> m b) -> (b -> m c) -> (a -> m c)
109 f >=> g = \x -> f x >>= g
110
111 -- | Right-to-left Kleisli composition of monads. @('>=>')@, with the arguments flipped
112 (<=<) :: Monad m => (b -> m c) -> (a -> m b) -> (a -> m c)
113 (<=<) = flip (>=>)
114
115 -- | @'forever' act@ repeats the action infinitely.
116 forever :: (Applicative f) => f a -> f b
117 {-# INLINE forever #-}
118 forever a = let a' = a *> a' in a'
119 -- Use explicit sharing here, as it is prevents a space leak regardless of
120 -- optimizations.
121
122 -- -----------------------------------------------------------------------------
123 -- Other monad functions
124
125 -- | The 'mapAndUnzipM' function maps its first argument over a list, returning
126 -- the result as a pair of lists. This function is mainly used with complicated
127 -- data structures or a state-transforming monad.
128 mapAndUnzipM :: (Monad m) => (a -> m (b,c)) -> [a] -> m ([b], [c])
129 {-# INLINE mapAndUnzipM #-}
130 mapAndUnzipM f xs = sequence (map f xs) >>= return . unzip
131
132 -- | The 'zipWithM' function generalizes 'zipWith' to arbitrary monads.
133 zipWithM :: (Monad m) => (a -> b -> m c) -> [a] -> [b] -> m [c]
134 {-# INLINE zipWithM #-}
135 zipWithM f xs ys = sequence (zipWith f xs ys)
136
137 -- | 'zipWithM_' is the extension of 'zipWithM' which ignores the final result.
138 zipWithM_ :: (Monad m) => (a -> b -> m c) -> [a] -> [b] -> m ()
139 {-# INLINE zipWithM_ #-}
140 zipWithM_ f xs ys = sequence_ (zipWith f xs ys)
141
142 {- | The 'foldM' function is analogous to 'foldl', except that its result is
143 encapsulated in a monad. Note that 'foldM' works from left-to-right over
144 the list arguments. This could be an issue where @('>>')@ and the `folded
145 function' are not commutative.
146
147
148 > foldM f a1 [x1, x2, ..., xm]
149
150 ==
151
152 > do
153 > a2 <- f a1 x1
154 > a3 <- f a2 x2
155 > ...
156 > f am xm
157
158 If right-to-left evaluation is required, the input list should be reversed.
159
160 Note: 'foldM' is the same as 'foldlM'
161 -}
162
163 foldM :: (Foldable t, Monad m) => (b -> a -> m b) -> b -> t a -> m b
164 {-# INLINEABLE foldM #-}
165 {-# SPECIALISE foldM :: (a -> b -> IO a) -> a -> [b] -> IO a #-}
166 {-# SPECIALISE foldM :: (a -> b -> Maybe a) -> a -> [b] -> Maybe a #-}
167 foldM = foldlM
168
169 -- | Like 'foldM', but discards the result.
170 foldM_ :: (Foldable t, Monad m) => (b -> a -> m b) -> b -> t a -> m ()
171 {-# INLINEABLE foldM_ #-}
172 {-# SPECIALISE foldM_ :: (a -> b -> IO a) -> a -> [b] -> IO () #-}
173 {-# SPECIALISE foldM_ :: (a -> b -> Maybe a) -> a -> [b] -> Maybe () #-}
174 foldM_ f a xs = foldlM f a xs >> return ()
175
176 -- | @'replicateM' n act@ performs the action @n@ times,
177 -- gathering the results.
178 replicateM :: (Monad m) => Int -> m a -> m [a]
179 {-# INLINEABLE replicateM #-}
180 {-# SPECIALISE replicateM :: Int -> IO a -> IO [a] #-}
181 {-# SPECIALISE replicateM :: Int -> Maybe a -> Maybe [a] #-}
182 replicateM n x = sequence (replicate n x)
183
184 -- | Like 'replicateM', but discards the result.
185 replicateM_ :: (Monad m) => Int -> m a -> m ()
186 {-# INLINEABLE replicateM_ #-}
187 {-# SPECIALISE replicateM_ :: Int -> IO a -> IO () #-}
188 {-# SPECIALISE replicateM_ :: Int -> Maybe a -> Maybe () #-}
189 replicateM_ n x = sequence_ (replicate n x)
190
191 -- | The reverse of 'when'.
192 unless :: (Applicative f) => Bool -> f () -> f ()
193 {-# INLINEABLE unless #-}
194 {-# SPECIALISE unless :: Bool -> IO () -> IO () #-}
195 {-# SPECIALISE unless :: Bool -> Maybe () -> Maybe () #-}
196 unless p s = if p then pure () else s
197
198 infixl 4 <$!>
199
200 -- | Strict version of 'Data.Functor.<$>'.
201 --
202 -- @since 4.8.0.0
203 (<$!>) :: Monad m => (a -> b) -> m a -> m b
204 {-# INLINE (<$!>) #-}
205 f <$!> m = do
206 x <- m
207 let z = f x
208 z `seq` return z
209
210
211 -- -----------------------------------------------------------------------------
212 -- Other MonadPlus functions
213
214 -- | Direct 'MonadPlus' equivalent of 'filter'
215 -- @'filter'@ = @(mfilter:: (a -> Bool) -> [a] -> [a]@
216 -- applicable to any 'MonadPlus', for example
217 -- @mfilter odd (Just 1) == Just 1@
218 -- @mfilter odd (Just 2) == Nothing@
219
220 mfilter :: (MonadPlus m) => (a -> Bool) -> m a -> m a
221 {-# INLINEABLE mfilter #-}
222 mfilter p ma = do
223 a <- ma
224 if p a then return a else mzero
225
226 {- $naming
227
228 The functions in this library use the following naming conventions:
229
230 * A postfix \'@M@\' always stands for a function in the Kleisli category:
231 The monad type constructor @m@ is added to function results
232 (modulo currying) and nowhere else. So, for example,
233
234 > filter :: (a -> Bool) -> [a] -> [a]
235 > filterM :: (Monad m) => (a -> m Bool) -> [a] -> m [a]
236
237 * A postfix \'@_@\' changes the result type from @(m a)@ to @(m ())@.
238 Thus, for example:
239
240 > sequence :: Monad m => [m a] -> m [a]
241 > sequence_ :: Monad m => [m a] -> m ()
242
243 * A prefix \'@m@\' generalizes an existing function to a monadic form.
244 Thus, for example:
245
246 > sum :: Num a => [a] -> a
247 > msum :: MonadPlus m => [m a] -> m a
248
249 -}