on master help sign in
Add some convenient runner functions
67600c0Harendra Kumar
Changelog.md+1
@@ -12,6 +12,7 @@
12 * Generation: `replicate`, `fromIndices`, `fromIndicesM`
12 * Generation: `replicate`, `fromIndices`, `fromIndicesM`
13 * Enumeration: `Enumerable`, `enumerateFrom`, `enumerateFromTo`,
13 * Enumeration: `Enumerable`, `enumerateFrom`, `enumerateFromTo`,
14 `enumerateFromThen`, `enumerateFromThenTo`, `enumerate`
14 `enumerateFromThen`, `enumerateFromThenTo`, `enumerate`
15+ * Running: `runIters`, `runWhile`
15 * Folds: `(!!)`, `maximumBy`, `minimumBy`, `the`
16 * Folds: `(!!)`, `maximumBy`, `minimumBy`, `the`
16 * Scans: `scanl1'`, `scanl1M'
17 * Scans: `scanl1'`, `scanl1M'
17 * Filters: `uniq`, `insertBy`, `deleteBy`, `findM`
18 * Filters: `uniq`, `insertBy`, `deleteBy`, `findM`
examples/AcidRain.hs+13−9
@@ -25,27 +25,31 @@ userAction = S.repeatM $ liftIO askUser
25acidRain :: MonadAsync m => SerialT m Event
25acidRain :: MonadAsync m => SerialT m Event
26acidRain = asyncly $ constRate 1 $ S.repeatM $ liftIO $ return $ Harm 1
26acidRain = asyncly $ constRate 1 $ S.repeatM $ liftIO $ return $ Harm 1
27
27
28−data Status = Check | Done
28+data Result = Check | Done
29
29
30−processEvents :: (MonadAsync m, MonadState Int m) => SerialT m Status
30+runEvents :: (MonadAsync m, MonadState Int m) => SerialT m Result
31−processEvents = do
31+runEvents = do
32 event <- userAction `parallel` acidRain
32 event <- userAction `parallel` acidRain
33 case event of
33 case event of
34 Harm n -> modify (\h -> h - n) >> return Check
34 Harm n -> modify (\h -> h - n) >> return Check
35 Heal n -> modify (\h -> h + n) >> return Check
35 Heal n -> modify (\h -> h + n) >> return Check
36 Quit -> return Done
36 Quit -> return Done
37
37
38−checkStatus status =
38+data Status = Alive | GameOver deriving Eq
39+
40+getStatus :: (MonadAsync m, MonadState Int m) => Result -> m Status
41+getStatus result =
39− case status of
42+ case result of
40− Done -> liftIO $ putStrLn "You quit!" >> return False
43+ Done -> liftIO $ putStrLn "You quit!" >> return GameOver
41 Check -> do
44 Check -> do
42 h <- get
45 h <- get
43 liftIO $ if (h <= 0)
46 liftIO $ if (h <= 0)
44− then putStrLn "You die!" >> return False
47+ then putStrLn "You die!" >> return GameOver
45− else putStrLn ("Health = " <> show h) >> return True
48+ else putStrLn ("Health = " <> show h) >> return Alive
46
49
47main :: IO ()
50main :: IO ()
48main = do
51main = do
49 putStrLn "Your health is deteriorating due to acid rain,\
52 putStrLn "Your health is deteriorating due to acid rain,\
50 \ type \"potion\" or \"quit\""
53 \ type \"potion\" or \"quit\""
54+ let runGame = S.runWhile (== Alive) $ S.mapM getStatus runEvents
51− void $ runStateT (S.any (== False) $ S.mapM checkStatus $ processEvents) 60
55+ void $ runStateT runGame 60
src/Streamly.hs+10−21
@@ -89,8 +89,7 @@ module Streamly
89 , ZipAsyncM
89 , ZipAsyncM
90
90
91 -- * Running Streams
91 -- * Running Streams
92− , runStream
92+ , P.runStream
93−
94 -- * Parallel Function Application
93 -- * Parallel Function Application
95 -- $application
94 -- $application
96 , (|$)
95 , (|$)
@@ -153,6 +152,7 @@ module Streamly
153
152
154 -- * Re-exports
153 -- * Re-exports
155 , Semigroup (..)
154 , Semigroup (..)
155+
156 -- * Deprecated
156 -- * Deprecated
157 , Streaming
157 , Streaming
158 , runStreaming
158 , runStreaming
@@ -184,7 +184,7 @@ import Streamly.Streams.Serial
184import Streamly.Streams.StreamK hiding (runStream, serial)
184import Streamly.Streams.StreamK hiding (runStream, serial)
185import Streamly.Streams.Zip
185import Streamly.Streams.Zip
186
186
187−import qualified Streamly.Streams.StreamD as D
187+import qualified Streamly.Prelude as P
188import qualified Streamly.Streams.StreamK as K
188import qualified Streamly.Streams.StreamK as K
189
189
190-- XXX This should perhaps be moved to Prelude.
190-- XXX This should perhaps be moved to Prelude.
@@ -193,65 +193,54 @@ import qualified Streamly.Streams.StreamK as K
193-- Eliminating a stream
193-- Eliminating a stream
194------------------------------------------------------------------------------
194------------------------------------------------------------------------------
195
195
196−-- | Run a streaming composition, discard the results. By default it interprets
197−-- the stream as 'SerialT', to run other types of streams use the type adapting
198−-- combinators for example @runStream . 'asyncly'@.
199−--
200−-- @since 0.2.0
201−{-# INLINE_EARLY runStream #-}
202−runStream :: Monad m => SerialT m a -> m ()
203−runStream m = D.runStream $ D.fromStreamK (toStream m)
204−{-# RULES "runStream fallback to CPS" [1]
205− forall a. D.runStream (D.fromStreamK a) = K.runStream a #-}
206−
207-- | Same as 'runStream'
196-- | Same as 'runStream'
208--
197--
209-- @since 0.1.0
198-- @since 0.1.0
210{-# DEPRECATED runStreaming "Please use runStream instead." #-}
199{-# DEPRECATED runStreaming "Please use runStream instead." #-}
211runStreaming :: (Monad m, IsStream t) => t m a -> m ()
200runStreaming :: (Monad m, IsStream t) => t m a -> m ()
212−runStreaming = runStream . K.adapt
201+runStreaming = P.runStream . K.adapt
213
202
214-- | Same as @runStream@.
203-- | Same as @runStream@.
215--
204--
216-- @since 0.1.0
205-- @since 0.1.0
217{-# DEPRECATED runStreamT "Please use runStream instead." #-}
206{-# DEPRECATED runStreamT "Please use runStream instead." #-}
218runStreamT :: Monad m => SerialT m a -> m ()
207runStreamT :: Monad m => SerialT m a -> m ()
219−runStreamT = runStream
208+runStreamT = P.runStream
220
209
221-- | Same as @runStream . wSerially@.
210-- | Same as @runStream . wSerially@.
222--
211--
223-- @since 0.1.0
212-- @since 0.1.0
224{-# DEPRECATED runInterleavedT "Please use 'runStream . interleaving' instead." #-}
213{-# DEPRECATED runInterleavedT "Please use 'runStream . interleaving' instead." #-}
225runInterleavedT :: Monad m => WSerialT m a -> m ()
214runInterleavedT :: Monad m => WSerialT m a -> m ()
226−runInterleavedT = runStream . K.adapt
215+runInterleavedT = P.runStream . K.adapt
227
216
228-- | Same as @runStream . parallely@.
217-- | Same as @runStream . parallely@.
229--
218--
230-- @since 0.1.0
219-- @since 0.1.0
231{-# DEPRECATED runParallelT "Please use 'runStream . parallely' instead." #-}
220{-# DEPRECATED runParallelT "Please use 'runStream . parallely' instead." #-}
232runParallelT :: Monad m => ParallelT m a -> m ()
221runParallelT :: Monad m => ParallelT m a -> m ()
233−runParallelT = runStream . K.adapt
222+runParallelT = P.runStream . K.adapt
234
223
235-- | Same as @runStream . asyncly@.
224-- | Same as @runStream . asyncly@.
236--
225--
237-- @since 0.1.0
226-- @since 0.1.0
238{-# DEPRECATED runAsyncT "Please use 'runStream . asyncly' instead." #-}
227{-# DEPRECATED runAsyncT "Please use 'runStream . asyncly' instead." #-}
239runAsyncT :: Monad m => AsyncT m a -> m ()
228runAsyncT :: Monad m => AsyncT m a -> m ()
240−runAsyncT = runStream . K.adapt
229+runAsyncT = P.runStream . K.adapt
241
230
242-- | Same as @runStream . zipping@.
231-- | Same as @runStream . zipping@.
243--
232--
244-- @since 0.1.0
233-- @since 0.1.0
245{-# DEPRECATED runZipStream "Please use 'runStream . zipSerially instead." #-}
234{-# DEPRECATED runZipStream "Please use 'runStream . zipSerially instead." #-}
246runZipStream :: Monad m => ZipSerialM m a -> m ()
235runZipStream :: Monad m => ZipSerialM m a -> m ()
247−runZipStream = runStream . K.adapt
236+runZipStream = P.runStream . K.adapt
248
237
249-- | Same as @runStream . zippingAsync@.
238-- | Same as @runStream . zippingAsync@.
250--
239--
251-- @since 0.1.0
240-- @since 0.1.0
252{-# DEPRECATED runZipAsync "Please use 'runStream . zipAsyncly instead." #-}
241{-# DEPRECATED runZipAsync "Please use 'runStream . zipAsyncly instead." #-}
253runZipAsync :: Monad m => ZipAsyncM m a -> m ()
242runZipAsync :: Monad m => ZipAsyncM m a -> m ()
254−runZipAsync = runStream . K.adapt
243+runZipAsync = P.runStream . K.adapt
255
244
256------------------------------------------------------------------------------
245------------------------------------------------------------------------------
257-- Documentation
246-- Documentation
src/Streamly/Prelude.hs+34
@@ -180,6 +180,11 @@ module Streamly.Prelude
180 , foldx
180 , foldx
181 , foldxM
181 , foldxM
182
182
183+ -- ** Run Effects
184+ , runStream
185+ , runN
186+ , runWhile
187+
183 -- ** To Elements
188 -- ** To Elements
184 -- | Folds that extract selected elements of a stream or their properties.
189 -- | Folds that extract selected elements of a stream or their properties.
185 , (!!)
190 , (!!)
@@ -1346,6 +1351,35 @@ foldlM' step begin m = S.foldlM' step begin $ toStreamS m
1346-- Specialized folds
1351-- Specialized folds
1347------------------------------------------------------------------------------
1352------------------------------------------------------------------------------
1348
1353
1354+-- | Run a stream, discarding the results. By default it interprets the stream
1355+-- as 'SerialT', to run other types of streams use the type adapting
1356+-- combinators for example @runStream . 'asyncly'@.
1357+--
1358+-- @since 0.2.0
1359+{-# INLINE runStream #-}
1360+runStream :: Monad m => SerialT m a -> m ()
1361+runStream = P.runStream
1362+
1363+-- |
1364+-- > runN n = runStream . take n
1365+--
1366+-- Run maximum up to @n@ iterations of a stream.
1367+--
1368+-- @since 0.6.0
1369+{-# INLINE runN #-}
1370+runN :: Monad m => Int -> SerialT m a -> m ()
1371+runN n = runStream . take n
1372+
1373+-- |
1374+-- > runWhile p = runStream . takeWhile p
1375+--
1376+-- Run a stream as long as the predicate holds true.
1377+--
1378+-- @since 0.6.0
1379+{-# INLINE runWhile #-}
1380+runWhile :: Monad m => (a -> Bool) -> SerialT m a -> m ()
1381+runWhile p = runStream . takeWhile p
1382+
1349-- | Determine whether the stream is empty.
1383-- | Determine whether the stream is empty.
1350--
1384--
1351-- @since 0.1.1
1385-- @since 0.1.1
src/Streamly/Streams/Prelude.hs+18
@@ -22,6 +22,9 @@ module Streamly.Streams.Prelude
22 fromStreamS
22 fromStreamS
23 , toStreamS
23 , toStreamS
24
24
25+ -- * Running Effects
26+ , runStream
27+
25 -- * Conversion operations
28 -- * Conversion operations
26 , fromList
29 , fromList
27 , toList
30 , toList
@@ -72,6 +75,21 @@ toStreamS = S.fromStreamK . toStream
72-- Conversions
75-- Conversions
73------------------------------------------------------------------------------
76------------------------------------------------------------------------------
74
77
78+-- | Run a streaming composition, discard the results. By default it interprets
79+-- the stream as 'SerialT', to run other types of streams use the type adapting
80+-- combinators for example @run . 'asyncly'@.
81+--
82+-- @since 0.6.0
83+{-# INLINE_EARLY runStream #-}
84+runStream :: (IsStream t, Monad m) => t m a -> m ()
85+runStream m = D.runStream $ D.fromStreamK (toStream m)
86+{-# RULES "run fallback to CPS" [1]
87+ forall a. D.runStream (D.fromStreamK a) = K.runStream a #-}
88+
89+------------------------------------------------------------------------------
90+-- Conversions
91+------------------------------------------------------------------------------
92+
75-- |
93-- |
76-- @
94-- @
77-- fromList = 'Prelude.foldr' 'K.cons' 'K.nil'
95-- fromList = 'Prelude.foldr' 'K.cons' 'K.nil'