on master help sign in
Deprecate Streamly module and move the exports to Streamly.Prelude.
ad05792pranaysashank
Changelog.md+9
@@ -28,6 +28,15 @@
28 fully drained. Also, the resource acquisition and release is atomic with
28 fully drained. Also, the resource acquisition and release is atomic with
29 respect to async exceptions.
29 respect to async exceptions.
30
30
31+### Deprecations
32+
33+* The `Streamly` module is now deprecated, its functionality is subsumed
34+ by `Streamly.Prelude`.
35+* Some functions from `Streamly` module have been renamed in `Streamly.Prelude` module:
36+ * `foldWith` has been replaced by `concatFoldableWith`
37+ * `foldMapWith` has been replaced by `concatMapFoldableWith`
38+ * `forEachWith` has been replaced by `concatForFoldableWith`
39+
31## 0.7.2
40## 0.7.2
32
41
33### Bug Fixes
42### Bug Fixes
README.md+14−20
@@ -106,9 +106,9 @@ Please see [INSTALL.md](./INSTALL.md) for instructions on how to use streamly
106with your Haskell build tool or package manager. You may want to go through it
106with your Haskell build tool or package manager. You may want to go through it
107before jumping to run the examples below.
107before jumping to run the examples below.
108
108
109−The module `Streamly` provides just the core stream types, type casting and
109+The module `Streamly.Prelude` provides the core stream types and combinators
110−concurrency control combinators. Stream construction, transformation, folding,
110+for type casting, controlling concurrency, stream construction, transformation,
111−merging, zipping combinators are found in `Streamly.Prelude`.
111+folding, merging, and zipping.
112
112
113## Streaming Pipelines
113## Streaming Pipelines
114
114
@@ -117,7 +117,6 @@ numbers from stdin, prints the squares of even numbers and exits if an even
117number more than 9 is entered.
117number more than 9 is entered.
118
118
119``` haskell
119``` haskell
120−import Streamly
121import qualified Streamly.Prelude as S
120import qualified Streamly.Prelude as S
122import Data.Function ((&))
121import Data.Function ((&))
123
122
@@ -150,7 +149,7 @@ each action is finished (asyncly):
150
149
151``` haskell
150``` haskell
152> let p n = threadDelay (n * 1000000) >> return n
151> let p n = threadDelay (n * 1000000) >> return n
153−> S.toList $ asyncly $ p 3 |: p 2 |: p 1 |: S.nil
152+> S.toList $ S.asyncly $ p 3 |: p 2 |: p 1 |: S.nil
154[1,2,3]
153[1,2,3]
155```
154```
156
155
@@ -158,7 +157,7 @@ Use `aheadly` if you want speculative concurrency i.e. execute the actions in
158the stream concurrently but consume the results in the specified order:
157the stream concurrently but consume the results in the specified order:
159
158
160``` haskell
159``` haskell
161−> S.toList $ aheadly $ p 3 |: p 2 |: p 1 |: S.nil
160+> S.toList $ S.aheadly $ p 3 |: p 2 |: p 1 |: S.nil
162[3,2,1]
161[3,2,1]
163```
162```
164
163
@@ -168,7 +167,7 @@ Monadic stream generation functions e.g. `unfoldrM`, `replicateM`, `repeatM`,
168The following finishes in 10 seconds (100 seconds when serial):
167The following finishes in 10 seconds (100 seconds when serial):
169
168
170``` haskell
169``` haskell
171−S.drain $ asyncly $ S.replicateM 10 $ p 10
170+S.drain $ S.asyncly $ S.replicateM 10 $ p 10
172```
171```
173
172
174## Concurrency Auto Scaling
173## Concurrency Auto Scaling
@@ -177,7 +176,7 @@ Concurrency is auto-scaled i.e. more actions are executed concurrently if the
177consumer is consuming the stream at a higher speed. How many tasks are executed
176consumer is consuming the stream at a higher speed. How many tasks are executed
178concurrently can be controlled by `maxThreads` and how many results are
177concurrently can be controlled by `maxThreads` and how many results are
179buffered ahead of consumption can be controlled by `maxBuffer`. See the
178buffered ahead of consumption can be controlled by `maxBuffer`. See the
180−documentation in the `Streamly` module.
179+documentation in the `Streamly.Prelude` module.
181
180
182## Concurrent Streaming Pipelines
181## Concurrent Streaming Pipelines
183
182
@@ -198,7 +197,7 @@ We can use `mapM` or `sequence` functions concurrently on a stream.
198
197
199``` haskell
198``` haskell
200> let p n = threadDelay (n * 1000000) >> return n
199> let p n = threadDelay (n * 1000000) >> return n
201−> S.drain $ aheadly $ S.mapM (\x -> p 1 >> print x) (serially $ repeatM (p 1))
200+> S.drain $ S.aheadly $ S.mapM (\x -> p 1 >> print x) (S.serially $ S.repeatM (p 1))
202```
201```
203
202
204## Serial and Concurrent Merging
203## Serial and Concurrent Merging
@@ -209,11 +208,10 @@ stream, each with a delay of 1 to 10 seconds, respectively. Since all the
209actions are concurrent we see one output printed every second:
208actions are concurrent we see one output printed every second:
210
209
211``` haskell
210``` haskell
212−import Streamly
213import qualified Streamly.Prelude as S
211import qualified Streamly.Prelude as S
214import Control.Concurrent (threadDelay)
212import Control.Concurrent (threadDelay)
215
213
216−main = S.toList $ parallely $ foldMap delay [1..10]
214+main = S.toList $ S.parallely $ foldMap delay [1..10]
217 where delay n = S.yieldM $ threadDelay (n * 1000000) >> print n
215 where delay n = S.yieldM $ threadDelay (n * 1000000) >> print n
218```
216```
219
217
@@ -222,7 +220,6 @@ below, see the tutorial for more ways. We use the following `delay`
222function in the examples to demonstrate the concurrency aspects:
220function in the examples to demonstrate the concurrency aspects:
223
221
224``` haskell
222``` haskell
225−import Streamly
226import qualified Streamly.Prelude as S
223import qualified Streamly.Prelude as S
227import Control.Concurrent
224import Control.Concurrent
228
225
@@ -245,7 +242,7 @@ ThreadId 36: Delay 1
245### Parallel
242### Parallel
246
243
247``` haskell
244``` haskell
248−main = S.drain . parallely $ delay 3 <> delay 2 <> delay 1
245+main = S.drain . S.parallely $ delay 3 <> delay 2 <> delay 1
249```
246```
250```
247```
251ThreadId 42: Delay 1
248ThreadId 42: Delay 1
@@ -258,7 +255,6 @@ ThreadId 40: Delay 3
258The monad instance composes like a list monad.
255The monad instance composes like a list monad.
259
256
260``` haskell
257``` haskell
261−import Streamly
262import qualified Streamly.Prelude as S
258import qualified Streamly.Prelude as S
263
259
264loops = do
260loops = do
@@ -282,7 +278,7 @@ loop can run concurrently but the results are presented to the consumer of the
282output in the same order as serial execution:
278output in the same order as serial execution:
283
279
284``` haskell
280``` haskell
285−main = S.drain $ aheadly $ loops
281+main = S.drain $ S.aheadly $ loops
286```
282```
287
283
288Different stream types execute the loop iterations in different ways. For
284Different stream types execute the loop iterations in different ways. For
@@ -298,11 +294,10 @@ to concurrently generate squares of a stream of numbers and then concurrently
298sum the square roots of all combinations of two streams:
294sum the square roots of all combinations of two streams:
299
295
300``` haskell
296``` haskell
301−import Streamly
302import qualified Streamly.Prelude as S
297import qualified Streamly.Prelude as S
303
298
304main = do
299main = do
305− s <- S.sum $ asyncly $ do
300+ s <- S.sum $ S.asyncly $ do
306 -- Each square is performed concurrently, (<>) is concurrent
301 -- Each square is performed concurrently, (<>) is concurrent
307 x2 <- foldMap (\x -> return $ x * x) [1..100]
302 x2 <- foldMap (\x -> return $ x * x) [1..100]
308 y2 <- foldMap (\y -> return $ y * y) [1..100]
303 y2 <- foldMap (\y -> return $ y * y) [1..100]
@@ -324,7 +319,7 @@ directories concurrently:
324```haskell
319```haskell
325import Control.Monad.IO.Class (liftIO)
320import Control.Monad.IO.Class (liftIO)
326import Path.IO (listDir, getCurrentDir) -- from path-io package
321import Path.IO (listDir, getCurrentDir) -- from path-io package
327−import Streamly (AsyncT, adapt)
322+import Streamly.Prelude (AsyncT, adapt)
328import qualified Streamly.Prelude as S
323import qualified Streamly.Prelude as S
329
324
330listDirRecursive :: AsyncT IO ()
325listDirRecursive :: AsyncT IO ()
@@ -350,10 +345,9 @@ For bounded concurrent streams, stream yield rate can be specified. For
350example, to print hello once every second you can simply write this:
345example, to print hello once every second you can simply write this:
351
346
352``` haskell
347``` haskell
353−import Streamly
354import Streamly.Prelude as S
348import Streamly.Prelude as S
355
349
356−main = S.drain $ asyncly $ avgRate 1 $ S.repeatM $ putStrLn "hello"
350+main = S.drain $ S.asyncly $ S.avgRate 1 $ S.repeatM $ putStrLn "hello"
357```
351```
358
352
359For some practical uses of rate control, see
353For some practical uses of rate control, see
benchmark/NanoBenchmarks.hs+1−1
@@ -6,7 +6,7 @@
6{-# LANGUAGE FlexibleContexts #-}
6{-# LANGUAGE FlexibleContexts #-}
7{-# LANGUAGE ScopedTypeVariables #-}
7{-# LANGUAGE ScopedTypeVariables #-}
8
8
9−import Streamly (SerialT)
9+import Streamly.Prelude (SerialT)
10import Streamly.Internal.Data.SVar (MonadAsync)
10import Streamly.Internal.Data.SVar (MonadAsync)
11
11
12import qualified Streamly.Data.Array.Storable.Foreign as A
12import qualified Streamly.Data.Array.Storable.Foreign as A
benchmark/Streamly/Benchmark/Data/ArrayOps.hs−1
@@ -21,7 +21,6 @@ import Control.Monad.IO.Class (MonadIO)
21import Prelude (Bool, Int, Maybe(..), ($), (+), (.), (==), (>), undefined)
21import Prelude (Bool, Int, Maybe(..), ($), (+), (.), (==), (>), undefined)
22
22
23import qualified Prelude as P
23import qualified Prelude as P
24−import qualified Streamly as S hiding (foldMapWith, runStream)
25import qualified Streamly.Prelude as S
24import qualified Streamly.Prelude as S
26
25
27#ifndef DATA_PRIM_ARRAY
26#ifndef DATA_PRIM_ARRAY
benchmark/Streamly/Benchmark/Data/Fold.hs+1−3
@@ -17,7 +17,6 @@ import Prelude (IO, Int, Double, String, (>), (<*>), (<$>), (+), ($),
17 (<=), Monad(..), (==), Maybe(..), (.), fromIntegral,
17 (<=), Monad(..), (==), Maybe(..), (.), fromIntegral,
18 compare, (>=), concat, seq)
18 compare, (>=), concat, seq)
19
19
20−import qualified Streamly as S hiding (runStream)
21import qualified Streamly.Prelude as S
20import qualified Streamly.Prelude as S
22import qualified Streamly.Internal.Data.Fold as FL
21import qualified Streamly.Internal.Data.Fold as FL
23import qualified Streamly.Internal.Data.Pipe as Pipe
22import qualified Streamly.Internal.Data.Pipe as Pipe
@@ -30,7 +29,6 @@ import qualified Streamly.Internal.Data.Fold as IFL
30import qualified Streamly.Internal.Data.Stream.IsStream as IP
29import qualified Streamly.Internal.Data.Stream.IsStream as IP
31
30
32import Gauge
31import Gauge
33−import Streamly hiding (runStream)
34import Streamly.Benchmark.Common
32import Streamly.Benchmark.Common
35
33
36-- We need a monadic bind here to make sure that the function f does not get
34-- We need a monadic bind here to make sure that the function f does not get
@@ -52,7 +50,7 @@ source = sourceUnfoldrM
52-- | Takes a fold method, and uses it with a default source.
50-- | Takes a fold method, and uses it with a default source.
53{-# INLINE benchIOSink #-}
51{-# INLINE benchIOSink #-}
54benchIOSink
52benchIOSink
55− :: (IsStream t, NFData b)
53+ :: (S.IsStream t, NFData b)
56 => Int -> String -> (t IO Int -> IO b) -> Benchmark
54 => Int -> String -> (t IO Int -> IO b) -> Benchmark
57benchIOSink value name f = bench name $ nfIO $ randomRIO (1,1) >>= f . source value
55benchIOSink value name f = bench name $ nfIO $ randomRIO (1,1) >>= f . source value
58
56
benchmark/Streamly/Benchmark/Data/Parser.hs+2−3
@@ -24,14 +24,13 @@ import Prelude
24import qualified Data.Traversable as TR
24import qualified Data.Traversable as TR
25import qualified Data.Foldable as F
25import qualified Data.Foldable as F
26import qualified Control.Applicative as AP
26import qualified Control.Applicative as AP
27−import qualified Streamly as S hiding (runStream)
28import qualified Streamly.Prelude as S
27import qualified Streamly.Prelude as S
29import qualified Streamly.Internal.Data.Fold as FL
28import qualified Streamly.Internal.Data.Fold as FL
30import qualified Streamly.Internal.Data.Parser as PR
29import qualified Streamly.Internal.Data.Parser as PR
31import qualified Streamly.Internal.Data.Stream.IsStream as IP
30import qualified Streamly.Internal.Data.Stream.IsStream as IP
32
31
33import Gauge
32import Gauge
34−import Streamly hiding (runStream)
33+import Streamly.Prelude (SerialT)
35import Streamly.Benchmark.Common
34import Streamly.Benchmark.Common
36
35
37-------------------------------------------------------------------------------
36-------------------------------------------------------------------------------
@@ -52,7 +51,7 @@ sourceUnfoldrM value n = S.unfoldrM step n
52-- | Takes a fold method, and uses it with a default source.
51-- | Takes a fold method, and uses it with a default source.
53{-# INLINE benchIOSink #-}
52{-# INLINE benchIOSink #-}
54benchIOSink
53benchIOSink
55− :: (IsStream t, NFData b)
54+ :: (S.IsStream t, NFData b)
56 => Int -> String -> (t IO Int -> IO b) -> Benchmark
55 => Int -> String -> (t IO Int -> IO b) -> Benchmark
57benchIOSink value name f =
56benchIOSink value name f =
58 bench name $ nfIO $ randomRIO (1,1) >>= f . sourceUnfoldrM value
57 bench name $ nfIO $ randomRIO (1,1) >>= f . sourceUnfoldrM value
benchmark/Streamly/Benchmark/Data/Parser/ParserD.hs+2−3
@@ -22,14 +22,13 @@ import Prelude hiding (any, all, take, sequence, sequenceA, takeWhile)
22import qualified Data.Traversable as TR
22import qualified Data.Traversable as TR
23import qualified Data.Foldable as F
23import qualified Data.Foldable as F
24import qualified Control.Applicative as AP
24import qualified Control.Applicative as AP
25−import qualified Streamly as S hiding (runStream)
26import qualified Streamly.Prelude as S
25import qualified Streamly.Prelude as S
27import qualified Streamly.Internal.Data.Fold as FL
26import qualified Streamly.Internal.Data.Fold as FL
28import qualified Streamly.Internal.Data.Parser.ParserD as PR
27import qualified Streamly.Internal.Data.Parser.ParserD as PR
29import qualified Streamly.Internal.Data.Stream.IsStream as IP
28import qualified Streamly.Internal.Data.Stream.IsStream as IP
30
29
31import Gauge
30import Gauge
32−import Streamly hiding (runStream)
31+import Streamly.Prelude (SerialT, MonadAsync, IsStream)
33import Streamly.Benchmark.Common
32import Streamly.Benchmark.Common
34
33
35-------------------------------------------------------------------------------
34-------------------------------------------------------------------------------
@@ -39,7 +38,7 @@ import Streamly.Benchmark.Common
39-- XXX these can be moved to the common module
38-- XXX these can be moved to the common module
40
39
41{-# INLINE sourceUnfoldrM #-}
40{-# INLINE sourceUnfoldrM #-}
42−sourceUnfoldrM :: (S.IsStream t, S.MonadAsync m) => Int -> Int -> t m Int
41+sourceUnfoldrM :: (IsStream t, MonadAsync m) => Int -> Int -> t m Int
43sourceUnfoldrM value n = S.unfoldrM step n
42sourceUnfoldrM value n = S.unfoldrM step n
44 where
43 where
45 step cnt =
44 step cnt =
benchmark/Streamly/Benchmark/Data/Parser/ParserK.hs+2−3
@@ -23,7 +23,6 @@ import Prelude hiding (any, all, take, sequence, sequenceA, takeWhile)
23import qualified Control.Applicative as AP
23import qualified Control.Applicative as AP
24import qualified Data.Foldable as F
24import qualified Data.Foldable as F
25import qualified Data.Traversable as TR
25import qualified Data.Traversable as TR
26−import qualified Streamly as S hiding (runStream)
27import qualified Streamly.Prelude as S
26import qualified Streamly.Prelude as S
28import qualified Streamly.Internal.Data.Fold as FL
27import qualified Streamly.Internal.Data.Fold as FL
29import qualified Streamly.Internal.Data.Parser.ParserK.Types as PR
28import qualified Streamly.Internal.Data.Parser.ParserK.Types as PR
@@ -31,7 +30,7 @@ import qualified Streamly.Internal.Data.Parser.ParserD as PRD
31import qualified Streamly.Internal.Data.Stream.IsStream as IP
30import qualified Streamly.Internal.Data.Stream.IsStream as IP
32
31
33import Gauge
32import Gauge
34−import Streamly hiding (runStream)
33+import Streamly.Prelude (SerialT, MonadAsync, IsStream)
35import Streamly.Benchmark.Common
34import Streamly.Benchmark.Common
36
35
37-------------------------------------------------------------------------------
36-------------------------------------------------------------------------------
@@ -41,7 +40,7 @@ import Streamly.Benchmark.Common
41-- XXX these can be moved to the common module
40-- XXX these can be moved to the common module
42
41
43{-# INLINE sourceUnfoldrM #-}
42{-# INLINE sourceUnfoldrM #-}
44−sourceUnfoldrM :: (S.IsStream t, S.MonadAsync m) => Int -> Int -> t m Int
43+sourceUnfoldrM :: (IsStream t, MonadAsync m) => Int -> Int -> t m Int
45sourceUnfoldrM value n = S.unfoldrM step n
44sourceUnfoldrM value n = S.unfoldrM step n
46 where
45 where
47 step cnt =
46 step cnt =
benchmark/Streamly/Benchmark/Data/Stream/StreamK.hs+5−5
@@ -121,11 +121,11 @@ sourceFromFoldableM n =
121
121
122{-# INLINE sourceFoldMapWith #-}
122{-# INLINE sourceFoldMapWith #-}
123sourceFoldMapWith :: Int -> Stream m Int
123sourceFoldMapWith :: Int -> Stream m Int
124−sourceFoldMapWith n = SP.foldMapWith S.serial S.yield [n..n+value]
124+sourceFoldMapWith n = SP.concatMapFoldableWith S.serial S.yield [n..n+value]
125
125
126{-# INLINE sourceFoldMapWithM #-}
126{-# INLINE sourceFoldMapWithM #-}
127sourceFoldMapWithM :: Monad m => Int -> Stream m Int
127sourceFoldMapWithM :: Monad m => Int -> Stream m Int
128−sourceFoldMapWithM n = SP.foldMapWith S.serial (S.yieldM . return) [n..n+value]
128+sourceFoldMapWithM n = SP.concatMapFoldableWith S.serial (S.yieldM . return) [n..n+value]
129
129
130-------------------------------------------------------------------------------
130-------------------------------------------------------------------------------
131-- Elimination
131-- Elimination
@@ -484,8 +484,8 @@ o_1_space =
484 , benchFold "fromFoldableM" toNull sourceFromFoldableM
484 , benchFold "fromFoldableM" toNull sourceFromFoldableM
485
485
486 -- appends
486 -- appends
487− , benchFold "foldMapWith" toNull sourceFoldMapWith
487+ , benchFold "concatMapFoldableWith" toNull sourceFoldMapWith
488− , benchFold "foldMapWithM" toNull sourceFoldMapWithM
488+ , benchFold "concatMapFoldableWithM" toNull sourceFoldMapWithM
489 ]
489 ]
490 , bgroup "elimination"
490 , bgroup "elimination"
491 [ benchFold "toNull" toNull sourceUnfoldrM
491 [ benchFold "toNull" toNull sourceUnfoldrM
@@ -542,7 +542,7 @@ o_1_space =
542 , benchIOSrc1 "concatMapRepl (sqrt n of sqrt n)"
542 , benchIOSrc1 "concatMapRepl (sqrt n of sqrt n)"
543 (concatMapRepl value2 value2)
543 (concatMapRepl value2 value2)
544
544
545− -- This is for comparison with foldMapWith
545+ -- This is for comparison with concatMapFoldableWith
546 , benchIOSrc1 "concatMapWithId (n of 1) (fromFoldable)"
546 , benchIOSrc1 "concatMapWithId (n of 1) (fromFoldable)"
547 (S.drain . S.concatMapBy S.serial id . sourceConcatMapId value)
547 (S.drain . S.concatMapBy S.serial id . sourceConcatMapId value)
548
548
benchmark/Streamly/Benchmark/Prelude/Adaptive.hs−1
@@ -9,7 +9,6 @@ import Control.Concurrent (threadDelay)
9import Control.Monad (when)
9import Control.Monad (when)
10import Control.Monad.IO.Class (liftIO)
10import Control.Monad.IO.Class (liftIO)
11import Gauge
11import Gauge
12−import Streamly
13import Streamly.Prelude as S
12import Streamly.Prelude as S
14import System.Random (randomRIO)
13import System.Random (randomRIO)
15
14
benchmark/Streamly/Benchmark/Prelude/Ahead.hs+1−1
@@ -7,7 +7,7 @@
7
7
8import Prelude hiding (mapM)
8import Prelude hiding (mapM)
9
9
10−import Streamly (aheadly, serially, ahead, maxBuffer, maxThreads)
10+import Streamly.Prelude (aheadly, serially, ahead, maxBuffer, maxThreads)
11import qualified Streamly.Prelude as S
11import qualified Streamly.Prelude as S
12
12
13import Streamly.Benchmark.Common
13import Streamly.Benchmark.Common
benchmark/Streamly/Benchmark/Prelude/Async.hs+1−1
@@ -7,7 +7,7 @@
7
7
8import Prelude hiding (mapM)
8import Prelude hiding (mapM)
9
9
10−import Streamly (asyncly, async, maxBuffer, maxThreads, serially)
10+import Streamly.Prelude (asyncly, async, maxBuffer, maxThreads, serially)
11import qualified Streamly.Prelude as S
11import qualified Streamly.Prelude as S
12import qualified Streamly.Internal.Data.Stream.StreamK.Type as Internal
12import qualified Streamly.Internal.Data.Stream.StreamK.Type as Internal
13
13
benchmark/Streamly/Benchmark/Prelude/Concurrent.hs+1−1
@@ -10,7 +10,7 @@ import Control.Concurrent
10import Control.Monad (when, replicateM)
10import Control.Monad (when, replicateM)
11
11
12import Gauge
12import Gauge
13−import Streamly
13+import Streamly.Prelude hiding (mapM_, replicateM)
14import qualified Streamly.Prelude as S
14import qualified Streamly.Prelude as S
15
15
16-------------------------------------------------------------------------------
16-------------------------------------------------------------------------------
benchmark/Streamly/Benchmark/Prelude/Parallel.hs+2−2
@@ -9,9 +9,9 @@
9
9
10import Prelude hiding (mapM)
10import Prelude hiding (mapM)
11
11
12+import Streamly.Prelude
12−import Streamly (SerialT, parallely, parallel, serially, maxBuffer, maxThreads)
13+ ( SerialT, parallely, parallel, serially, maxBuffer, maxThreads)
13
14
14−import qualified Streamly as S
15import qualified Streamly.Prelude as S
15import qualified Streamly.Prelude as S
16import qualified Streamly.Internal.Data.Fold as FL
16import qualified Streamly.Internal.Data.Fold as FL
17import qualified Streamly.Internal.Data.Stream.Parallel as Par
17import qualified Streamly.Internal.Data.Stream.Parallel as Par
benchmark/Streamly/Benchmark/Prelude/Rate.hs+2−3
@@ -5,9 +5,8 @@
5-- License : BSD3
5-- License : BSD3
6-- Maintainer : streamly@composewell.com
6-- Maintainer : streamly@composewell.com
7
7
8−import Streamly (asyncly, aheadly, maxThreads)
8+import Streamly.Prelude (asyncly, aheadly, maxThreads)
9−
10−import qualified Streamly as S
9+import qualified Streamly.Prelude as S
11
10
12import Streamly.Benchmark.Common
11import Streamly.Benchmark.Common
13import Streamly.Benchmark.Prelude
12import Streamly.Benchmark.Prelude
benchmark/Streamly/Benchmark/Prelude/Serial.hs+4−2
@@ -22,6 +22,8 @@
22{-# OPTIONS_GHC -fplugin Test.Inspection.Plugin #-}
22{-# OPTIONS_GHC -fplugin Test.Inspection.Plugin #-}
23#endif
23#endif
24
24
25+module Main where
26+
25import Control.DeepSeq (NFData(..))
27import Control.DeepSeq (NFData(..))
26import Control.Monad (when)
28import Control.Monad (when)
27import Control.Monad.IO.Class (MonadIO(..))
29import Control.Monad.IO.Class (MonadIO(..))
@@ -48,14 +50,14 @@ import Test.Inspection
48import qualified Streamly.Internal.Data.Stream.StreamD as D
50import qualified Streamly.Internal.Data.Stream.StreamD as D
49#endif
51#endif
50
52
51−import qualified Streamly as S
53+
52import qualified Streamly.Prelude as S
54import qualified Streamly.Prelude as S
53import qualified Streamly.Internal.Data.Stream.IsStream as Internal
55import qualified Streamly.Internal.Data.Stream.IsStream as Internal
54import qualified Streamly.Internal.Data.Fold as FL
56import qualified Streamly.Internal.Data.Fold as FL
55import qualified Streamly.Internal.Data.Unfold as UF
57import qualified Streamly.Internal.Data.Unfold as UF
56
58
57import Gauge
59import Gauge
58−import Streamly
60+import Streamly.Prelude (SerialT, IsStream, serially, serial)
59import Streamly.Benchmark.Common
61import Streamly.Benchmark.Common
60import Streamly.Benchmark.Prelude
62import Streamly.Benchmark.Prelude
61import Streamly.Internal.Data.Time.Units
63import Streamly.Internal.Data.Time.Units
benchmark/Streamly/Benchmark/Prelude/WAsync.hs+1−1
@@ -7,7 +7,7 @@
7
7
8import Prelude hiding (mapM)
8import Prelude hiding (mapM)
9
9
10−import Streamly (wAsyncly, serially, wAsync, maxBuffer, maxThreads)
10+import Streamly.Prelude (wAsyncly, serially, wAsync, maxBuffer, maxThreads)
11import qualified Streamly.Prelude as S
11import qualified Streamly.Prelude as S
12
12
13import Streamly.Benchmark.Common
13import Streamly.Benchmark.Common
benchmark/Streamly/Benchmark/Prelude/WSerial.hs+1−1
@@ -19,7 +19,7 @@
19{-# OPTIONS_GHC -fplugin Test.Inspection.Plugin #-}
19{-# OPTIONS_GHC -fplugin Test.Inspection.Plugin #-}
20#endif
20#endif
21
21
22−import Streamly
22+import Streamly.Prelude (wSerial, wSerially)
23import qualified Streamly.Prelude as S
23import qualified Streamly.Prelude as S
24import qualified Streamly.Internal.Data.Stream.IsStream as Internal
24import qualified Streamly.Internal.Data.Stream.IsStream as Internal
25import qualified Streamly.Internal.Data.Unfold as UF
25import qualified Streamly.Internal.Data.Unfold as UF
benchmark/Streamly/Benchmark/Prelude/ZipAsync.hs+1−2
@@ -7,8 +7,7 @@
7
7
8{-# LANGUAGE FlexibleContexts #-}
8{-# LANGUAGE FlexibleContexts #-}
9
9
10−import Streamly (serially)
10+import Streamly.Prelude (serially)
11−import qualified Streamly as S
12import qualified Streamly.Prelude as S
11import qualified Streamly.Prelude as S
13
12
14import Streamly.Benchmark.Common
13import Streamly.Benchmark.Common
benchmark/Streamly/Benchmark/Prelude/ZipSerial.hs+4−6
@@ -21,8 +21,7 @@
21
21
22import Prelude hiding (zip)
22import Prelude hiding (zip)
23
23
24−import Streamly (zipSerially)
24+import Streamly.Prelude (MonadAsync)
25−import qualified Streamly as S
26import qualified Streamly.Prelude as S
25import qualified Streamly.Prelude as S
27
26
28import Streamly.Benchmark.Common
27import Streamly.Benchmark.Common
@@ -47,7 +46,7 @@ moduleName = "Prelude.ZipSerial"
47-- XXX somehow copying this definition here instead of importing it performs
46-- XXX somehow copying this definition here instead of importing it performs
48-- better. Need to investigate why.
47-- better. Need to investigate why.
49{-# INLINE sourceUnfoldrM #-}
48{-# INLINE sourceUnfoldrM #-}
50−sourceUnfoldrM :: (S.IsStream t, S.MonadAsync m) => Int -> Int -> t m Int
49+sourceUnfoldrM :: (S.IsStream t, MonadAsync m) => Int -> Int -> t m Int
51sourceUnfoldrM count start = S.unfoldrM step start
50sourceUnfoldrM count start = S.unfoldrM step start
52 where
51 where
53 step cnt =
52 step cnt =
@@ -100,7 +99,7 @@ o_1_space_joining value =
100o_1_space_mapping :: Int -> [Benchmark]
99o_1_space_mapping :: Int -> [Benchmark]
101o_1_space_mapping value =
100o_1_space_mapping value =
102 [ bgroup "mapping"
101 [ bgroup "mapping"
103− [ benchIOSink value "fmap" $ fmapN zipSerially 1
102+ [ benchIOSink value "fmap" $ fmapN S.zipSerially 1
104 ]
103 ]
105 ]
104 ]
106
105
@@ -113,7 +112,7 @@ o_1_space_outerProduct :: Int -> [Benchmark]
113o_1_space_outerProduct value =
112o_1_space_outerProduct value =
114 [ bgroup "monad-outer-product"
113 [ bgroup "monad-outer-product"
115 -- XXX needs fixing
114 -- XXX needs fixing
116− [ benchIO "toNullAp" $ toNullAp value zipSerially
115+ [ benchIO "toNullAp" $ toNullAp value S.zipSerially
117 ]
116 ]
118 ]
117 ]
119-}
118-}
@@ -140,4 +139,3 @@ main = do
140 -- , o_1_space_outerProduct size
139 -- , o_1_space_outerProduct size
141 ]
140 ]
142 ]
141 ]
143−
benchmark/lib/Streamly/Benchmark/Common.hs+1−1
@@ -48,7 +48,7 @@ import System.Random (randomRIO)
48
48
49import qualified Streamly.Prelude as S
49import qualified Streamly.Prelude as S
50
50
51−import Streamly
51+import Streamly.Prelude (SerialT)
52import Gauge
52import Gauge
53
53
54-------------------------------------------------------------------------------
54-------------------------------------------------------------------------------
benchmark/lib/Streamly/Benchmark/Prelude.hs+9−7
@@ -16,11 +16,13 @@ import Control.Applicative (liftA2)
16import Control.DeepSeq (NFData(..))
16import Control.DeepSeq (NFData(..))
17import Control.Exception (try)
17import Control.Exception (try)
18import Data.Functor.Identity (Identity)
18import Data.Functor.Identity (Identity)
19+#if !(MIN_VERSION_base(4,11,0))
20+import Data.Semigroup (Semigroup((<>)))
21+#endif
19import GHC.Exception (ErrorCall)
22import GHC.Exception (ErrorCall)
20import System.Random (randomRIO)
23import System.Random (randomRIO)
21
24
22import qualified Data.Foldable as F
25import qualified Data.Foldable as F
23−import qualified Streamly as S
24import qualified Streamly.Prelude as S
26import qualified Streamly.Prelude as S
25import qualified Streamly.Internal.Data.Stream.IsStream as Internal
27import qualified Streamly.Internal.Data.Stream.IsStream as Internal
26import qualified Streamly.Internal.Data.Pipe as Pipe
28import qualified Streamly.Internal.Data.Pipe as Pipe
@@ -293,21 +295,21 @@ transformZipMapM t n =
293-------------------------------------------------------------------------------
295-------------------------------------------------------------------------------
294
296
295{-# INLINE sourceFoldMapWith #-}
297{-# INLINE sourceFoldMapWith #-}
296−sourceFoldMapWith :: (S.IsStream t, S.Semigroup (t m Int))
298+sourceFoldMapWith :: (S.IsStream t, Semigroup (t m Int))
297 => Int -> Int -> t m Int
299 => Int -> Int -> t m Int
298−sourceFoldMapWith value n = S.foldMapWith (S.<>) S.yield [n..n+value]
300+sourceFoldMapWith value n = S.concatMapFoldableWith (<>) S.yield [n..n+value]
299
301
300{-# INLINE sourceFoldMapWithStream #-}
302{-# INLINE sourceFoldMapWithStream #-}
301−sourceFoldMapWithStream :: (S.IsStream t, S.Semigroup (t m Int))
303+sourceFoldMapWithStream :: (S.IsStream t, Semigroup (t m Int))
302 => Int -> Int -> t m Int
304 => Int -> Int -> t m Int
303−sourceFoldMapWithStream value n = S.foldMapWith (S.<>) S.yield
305+sourceFoldMapWithStream value n = S.concatMapFoldableWith (<>) S.yield
304 $ (S.enumerateFromTo n (n + value) :: S.SerialT Identity Int)
306 $ (S.enumerateFromTo n (n + value) :: S.SerialT Identity Int)
305
307
306{-# INLINE sourceFoldMapWithM #-}
308{-# INLINE sourceFoldMapWithM #-}
307−sourceFoldMapWithM :: (S.IsStream t, Monad m, S.Semigroup (t m Int))
309+sourceFoldMapWithM :: (S.IsStream t, Monad m, Semigroup (t m Int))
308 => Int -> Int -> t m Int
310 => Int -> Int -> t m Int
309sourceFoldMapWithM value n =
311sourceFoldMapWithM value n =
310− S.foldMapWith (S.<>) (S.yieldM . return) [n..n+value]
312+ S.concatMapFoldableWith (<>) (S.yieldM . return) [n..n+value]
311
313
312{-# INLINE sourceFoldMapM #-}
314{-# INLINE sourceFoldMapM #-}
313sourceFoldMapM :: (S.IsStream t, Monad m, Monoid (t m Int))
315sourceFoldMapM :: (S.IsStream t, Monad m, Monoid (t m Int))
examples/AcidRain.hs+7−4
@@ -1,3 +1,4 @@
1+{-# LANGUAGE CPP #-}
1{-# LANGUAGE FlexibleContexts #-}
2{-# LANGUAGE FlexibleContexts #-}
2
3
3-- Copyright : (c) 2017 Harendra Kumar
4-- Copyright : (c) 2017 Harendra Kumar
@@ -6,7 +7,9 @@
6-- This example is adapted from Gabriel Gonzalez's pipes-concurrency package.
7-- This example is adapted from Gabriel Gonzalez's pipes-concurrency package.
7-- https://hackage.haskell.org/package/pipes-concurrency-2.0.8/docs/Pipes-Concurrent-Tutorial.html
8-- https://hackage.haskell.org/package/pipes-concurrency-2.0.8/docs/Pipes-Concurrent-Tutorial.html
8
9
9−import Streamly
10+#if !(MIN_VERSION_base(4,11,0))
11+import Data.Semigroup ((<>))
12+#endif
10import Streamly.Prelude as S
13import Streamly.Prelude as S
11import Control.Monad (void)
14import Control.Monad (void)
12import Control.Monad.IO.Class (MonadIO(liftIO))
15import Control.Monad.IO.Class (MonadIO(liftIO))
@@ -26,13 +29,13 @@ userAction = S.repeatM $ liftIO askUser
26 _ -> putStrLn "Type potion or harm or quit" >> askUser
29 _ -> putStrLn "Type potion or harm or quit" >> askUser
27
30
28acidRain :: MonadAsync m => SerialT m Event
31acidRain :: MonadAsync m => SerialT m Event
29−acidRain = asyncly $ constRate 1 $ S.repeatM $ liftIO $ return $ Harm 1
32+acidRain = S.asyncly $ S.constRate 1 $ S.repeatM $ liftIO $ return $ Harm 1
30
33
31data Result = Check | Done
34data Result = Check | Done
32
35
33runEvents :: (MonadAsync m, MonadState Int m) => SerialT m Result
36runEvents :: (MonadAsync m, MonadState Int m) => SerialT m Result
34runEvents = do
37runEvents = do
35− event <- userAction `parallel` acidRain
38+ event <- userAction `S.parallel` acidRain
36 case event of
39 case event of
37 Harm n -> modify (\h -> h - n) >> return Check
40 Harm n -> modify (\h -> h - n) >> return Check
38 Heal n -> modify (\h -> h + n) >> return Check
41 Heal n -> modify (\h -> h + n) >> return Check
@@ -52,7 +55,7 @@ getStatus result =
52
55
53main :: IO ()
56main :: IO ()
54main = do
57main = do
55− putStrLn "Your health is deteriorating due to acid rain,\
58+ putStrLn "Your health is deteriorating due to acid rain,\\
56 \ type \"potion\" or \"quit\""
59 \ type \"potion\" or \"quit\""
57 let runGame = S.drainWhile (== Alive) $ S.mapM getStatus runEvents
60 let runGame = S.drainWhile (== Alive) $ S.mapM getStatus runEvents
58 void $ runStateT runGame 60
61 void $ runStateT runGame 60
examples/CirclingSquare.hs+2−3
@@ -8,7 +8,6 @@
8
8
9import Data.IORef
9import Data.IORef
10import Graphics.UI.SDL as SDL
10import Graphics.UI.SDL as SDL
11−import Streamly
12import Streamly.Prelude as S
11import Streamly.Prelude as S
13
12
14------------------------------------------------------------------------------
13------------------------------------------------------------------------------
@@ -78,6 +77,6 @@ main :: IO ()
78main = do
77main = do
79 sdlInit
78 sdlInit
80 cref <- newIORef (0,0)
79 cref <- newIORef (0,0)
81− S.drain $ asyncly $ constRate 40
80+ S.drain $ S.asyncly $ S.constRate 40
82 $ S.repeatM (updateController cref)
81 $ S.repeatM (updateController cref)
83− `parallel` S.repeatM (updateDisplay cref)
82+ `S.parallel` S.repeatM (updateDisplay cref)
examples/ControlFlow.hs+7−2
@@ -1,4 +1,5 @@
1+{-# LANGUAGE CPP #-}
1−{-# LANGUAGE FlexibleContexts #-}
2+{-# LANGUAGE FlexibleContexts #-}
2{-# LANGUAGE ScopedTypeVariables #-}
3{-# LANGUAGE ScopedTypeVariables #-}
3
4
4-------------------------------------------------------------------------------
5-------------------------------------------------------------------------------
@@ -14,8 +15,12 @@
14-- This file provides an example where we enter a sequence of characters "x",
15-- This file provides an example where we enter a sequence of characters "x",
15-- and "y" on separate lines, on the command line. When any other sequence is
16-- and "y" on separate lines, on the command line. When any other sequence is
16-- entered the control flow short circuits at the first non-matching char and
17-- entered the control flow short circuits at the first non-matching char and
18+
17-- exits.
19-- exits.
18
20
21+#if !(MIN_VERSION_base(4,11,0))
22+import Data.Semigroup (Semigroup(..))
23+#endif
19import Control.Concurrent (threadDelay)
24import Control.Concurrent (threadDelay)
20import Control.Exception (catch, SomeException)
25import Control.Exception (catch, SomeException)
21import Control.Monad
26import Control.Monad
@@ -25,7 +30,7 @@ import Control.Monad.Trans.Class
25import Control.Monad.Trans.Maybe
30import Control.Monad.Trans.Maybe
26import Control.Monad.Trans.Except
31import Control.Monad.Trans.Except
27import Control.Monad.Trans.Cont
32import Control.Monad.Trans.Cont
28−import Streamly
33+import Streamly.Prelude
29import qualified Streamly.Prelude as S
34import qualified Streamly.Prelude as S
30
35
31-------------------------------------------------------------------------------
36-------------------------------------------------------------------------------
examples/EchoServer.hs+2−3
@@ -2,7 +2,6 @@
2
2
3import Data.Function ((&))
3import Data.Function ((&))
4
4
5−import Streamly
6import Streamly.Internal.Network.Socket (handleWithM)
5import Streamly.Internal.Network.Socket (handleWithM)
7import Streamly.Network.Socket
6import Streamly.Network.Socket
8
7
@@ -11,8 +10,8 @@ import qualified Streamly.Prelude as S
11
10
12main :: IO ()
11main :: IO ()
13main =
12main =
14− serially (S.unfold TCP.acceptOnPort 8091)
13+ S.serially (S.unfold TCP.acceptOnPort 8091)
15− & parallely . S.mapM (handleWithM echo)
14+ & S.parallely . S.mapM (handleWithM echo)
16 & S.drain
15 & S.drain
17
16
18 where
17 where
examples/FileSinkServer.hs+1−2
@@ -9,7 +9,6 @@ import Control.Monad.IO.Class (liftIO)
9import Network.Socket (close)
9import Network.Socket (close)
10import System.Environment (getArgs)
10import System.Environment (getArgs)
11
11
12−import Streamly
13import Streamly.Unicode.Stream
12import Streamly.Unicode.Stream
14import qualified Streamly.FileSystem.Handle as FH
13import qualified Streamly.FileSystem.Handle as FH
15import qualified Streamly.Data.Array.Storable.Foreign as A
14import qualified Streamly.Data.Array.Storable.Foreign as A
@@ -26,7 +25,7 @@ main = do
26 (\src -> S.fold (FH.write src)
25 (\src -> S.fold (FH.write src)
27 $ encodeLatin1Lax
26 $ encodeLatin1Lax
28 $ S.concatUnfold A.read
27 $ S.concatUnfold A.read
29− $ S.concatMapWith parallel use
28+ $ S.concatMapWith S.parallel use
30 $ S.unfold TCP.acceptOnPort 8090)
29 $ S.unfold TCP.acceptOnPort 8090)
31
30
32 where
31 where
examples/FromFileClient.hs+1−2
@@ -5,7 +5,6 @@
5
5
6import System.Environment (getArgs)
6import System.Environment (getArgs)
7
7
8−import Streamly
9import qualified Streamly.Prelude as S
8import qualified Streamly.Prelude as S
10import qualified Streamly.Internal.FileSystem.Handle as IFH
9import qualified Streamly.Internal.FileSystem.Handle as IFH
11import qualified Streamly.Internal.Network.Inet.TCP as TCP
10import qualified Streamly.Internal.Network.Inet.TCP as TCP
@@ -18,4 +17,4 @@ main =
18 withFile file ReadMode $ \src ->
17 withFile file ReadMode $ \src ->
19 S.fold (TCP.writeChunks (127, 0, 0, 1) 8090)
18 S.fold (TCP.writeChunks (127, 0, 0, 1) 8090)
20 $ IFH.toChunks src
19 $ IFH.toChunks src
21− in getArgs >>= S.drain . parallely . S.mapM sendFile . S.fromList
20+ in getArgs >>= S.drain . S.parallely . S.mapM sendFile . S.fromList
examples/ListDir.hs+1−2
@@ -3,7 +3,6 @@ module Main (main) where
3import Data.Bifunctor (bimap)
3import Data.Bifunctor (bimap)
4import Data.Function ((&))
4import Data.Function ((&))
5import System.IO (stdout, hSetBuffering, BufferMode(LineBuffering))
5import System.IO (stdout, hSetBuffering, BufferMode(LineBuffering))
6−import Streamly (ahead)
7
6
8import qualified Streamly.Prelude as S
7import qualified Streamly.Prelude as S
9import qualified Streamly.Internal.Data.Stream.IsStream as S
8import qualified Streamly.Internal.Data.Stream.IsStream as S
@@ -14,7 +13,7 @@ import qualified Streamly.Internal.FileSystem.Dir as Dir
14main :: IO ()
13main :: IO ()
15main = do
14main = do
16 hSetBuffering stdout LineBuffering
15 hSetBuffering stdout LineBuffering
17− S.mapM_ print $ S.iterateMapLeftsWith ahead listDir (S.yield $ (Left "."))
16+ S.mapM_ print $ S.iterateMapLeftsWith S.ahead listDir (S.yield $ (Left "."))
18
17
19 where
18 where
20
19
examples/MergeSort.hs+1−1
@@ -10,7 +10,7 @@ import Data.Word
10import System.Random (getStdGen, randoms)
10import System.Random (getStdGen, randoms)
11import Data.List (sort)
11import Data.List (sort)
12
12
13−import Streamly
13+import Streamly.Prelude (Serial)
14import qualified Streamly.Prelude as S
14import qualified Streamly.Prelude as S
15
15
16getSorted :: Serial Word16
16getSorted :: Serial Word16
examples/Rate.hs+2−3
@@ -1,11 +1,10 @@
1−import Streamly
2import qualified Streamly.Prelude as S
1import qualified Streamly.Prelude as S
3import qualified Streamly.Internal.Data.Stream.IsStream as Internal
2import qualified Streamly.Internal.Data.Stream.IsStream as Internal
4
3
5main :: IO ()
4main :: IO ()
6main =
5main =
7 S.mapM_ print
6 S.mapM_ print
8− $ asyncly
7+ $ S.asyncly
9− $ avgRate 1
8+ $ S.avgRate 1
10 $ Internal.timestamped
9 $ Internal.timestamped
11 $ S.repeatM (pure "tick")
10 $ S.repeatM (pure "tick")
examples/SearchQuery.hs+10−4
@@ -1,7 +1,13 @@
1−import Streamly
1+{-# LANGUAGE CPP #-}
2+
3+#if !(MIN_VERSION_base(4,11,0))
4+import Data.Semigroup ((<>))
5+#endif
2import Streamly.Prelude (drain, nil, yieldM, (|:))
6import Streamly.Prelude (drain, nil, yieldM, (|:))
3import Network.HTTP.Simple
7import Network.HTTP.Simple
4
8
9+import qualified Streamly.Prelude as S
10+
5-- | Runs three search engine queries in parallel and prints the search engine
11-- | Runs three search engine queries in parallel and prints the search engine
6-- names in the fastest first order.
12-- names in the fastest first order.
7--
13--
@@ -10,13 +16,13 @@ import Network.HTTP.Simple
10main :: IO ()
16main :: IO ()
11main = do
17main = do
12 putStrLn "Using parallel stream construction"
18 putStrLn "Using parallel stream construction"
13− drain . parallely $ google |: bing |: duckduckgo |: nil
19+ drain . S.parallely $ google |: bing |: duckduckgo |: nil
14
20
15 putStrLn "\nUsing parallel semigroup composition"
21 putStrLn "\nUsing parallel semigroup composition"
16− drain . parallely $ yieldM google <> yieldM bing <> yieldM duckduckgo
22+ drain . S.parallely $ yieldM google <> yieldM bing <> yieldM duckduckgo
17
23
18 putStrLn "\nUsing parallel applicative zip"
24 putStrLn "\nUsing parallel applicative zip"
19− drain . zipAsyncly $
25+ drain . S.zipAsyncly $
20 (,,) <$> yieldM google <*> yieldM bing <*> yieldM duckduckgo
26 (,,) <$> yieldM google <*> yieldM bing <*> yieldM duckduckgo
21
27
22 where
28 where
examples/WordCount.hs+1−2
@@ -40,11 +40,10 @@ import Streamly.Internal.Unicode.Stream
40 (DecodeState, DecodeError(..), CodePoint, decodeUtf8Either,
40 (DecodeState, DecodeError(..), CodePoint, decodeUtf8Either,
41 resumeDecodeUtf8Either)
41 resumeDecodeUtf8Either)
42
42
43−import qualified Streamly as S
43+import qualified Streamly.Internal.Data.Stream.IsStream as S
44import qualified Streamly.Unicode.Stream as S
44import qualified Streamly.Unicode.Stream as S
45import qualified Streamly.FileSystem.Handle as FH
45import qualified Streamly.FileSystem.Handle as FH
46import qualified Streamly.Data.Array.Storable.Foreign as A
46import qualified Streamly.Data.Array.Storable.Foreign as A
47−import qualified Streamly.Prelude as S
48import qualified Data.Vector.Storable.Mutable as V
47import qualified Data.Vector.Storable.Mutable as V
49
48
50-------------------------------------------------------------------------------
49-------------------------------------------------------------------------------
src/Streamly.hs+29−13
@@ -51,11 +51,12 @@
51-- please see the "Streamly.Tutorial" module and the examples directory in this
51-- please see the "Streamly.Tutorial" module and the examples directory in this
52-- package.
52-- package.
53
53
54+{-# LANGUAGE NoMonomorphismRestriction #-}
54{-# OPTIONS_GHC -Wno-orphans #-}
55{-# OPTIONS_GHC -Wno-orphans #-}
55
56
56#include "inline.hs"
57#include "inline.hs"
57
58
58−module Streamly
59+module Streamly {-# DEPRECATED "Please use \"Streamly.Prelude\" instead." #-}
59 (
60 (
60 -- -- * Concepts Overview
61 -- -- * Concepts Overview
61 -- -- ** Streams
62 -- -- ** Streams
@@ -181,13 +182,12 @@ module Streamly
181 -- finite container of streams. Note that these are just special cases of
182 -- finite container of streams. Note that these are just special cases of
182 -- the more general 'concatMapWith' operation.
183 -- the more general 'concatMapWith' operation.
183 --
184 --
184− , IP.foldWith
185+ , foldWith
185− , IP.foldMapWith
186+ , foldMapWith
186− , IP.forEachWith
187+ , forEachWith
187
188
188 -- * Re-exports
189 -- * Re-exports
189 , Semigroup (..)
190 , Semigroup (..)
190−
191 -- * Deprecated
191 -- * Deprecated
192 , Streaming
192 , Streaming
193 , runStream
193 , runStream
@@ -206,14 +206,6 @@ module Streamly
206 , zippingAsync
206 , zippingAsync
207 , (<=>)
207 , (<=>)
208 , (<|)
208 , (<|)
209−
210− {-
211− -- * Deprecated/Moved
212− -- | These APIs have been moved to other modules
213− , foldWith
214− , foldMapWith
215− , forEachWith
216− -}
217 )
209 )
218where
210where
219
211
@@ -640,3 +632,27 @@ mkAsync = return . Async.mkAsync
640-- which specific type you are converting from or to. If you see a an
632-- which specific type you are converting from or to. If you see a an
641-- @ambiguous type variable@ error then most likely you are using 'adapt'
633-- @ambiguous type variable@ error then most likely you are using 'adapt'
642-- unnecessarily on polymorphic code.
634-- unnecessarily on polymorphic code.
635+
636+-- | Same as 'Streamly.Prelude.concatFoldableWith'
637+--
638+-- @since 0.1.0
639+{-# DEPRECATED foldWith "Please use 'Streamly.Prelude.concatFoldableWith' instead." #-}
640+{-# INLINEABLE foldWith #-}
641+foldWith :: (IsStream t, Foldable f) => (t m a -> t m a -> t m a) -> f (t m a) -> t m a
642+foldWith = P.concatFoldableWith
643+
644+-- | Same as 'Streamly.Prelude.concatMapFoldableWith'
645+--
646+-- @since 0.1.0
647+{-# DEPRECATED foldMapWith "Please use 'Streamly.Prelude.concatMapFoldableWith' instead." #-}
648+{-# INLINEABLE foldMapWith #-}
649+foldMapWith :: (IsStream t, Foldable f) => (t m b -> t m b -> t m b) -> (a -> t m b) -> f a -> t m b
650+foldMapWith = P.concatMapFoldableWith
651+
652+-- | Same as 'Streamly.Prelude.concatForFoldableWith'
653+--
654+-- @since 0.1.0
655+{-# DEPRECATED forEachWith "Please use 'Streamly.Prelude.concatForFoldableWith' instead." #-}
656+{-# INLINEABLE forEachWith #-}
657+forEachWith :: (IsStream t, Foldable f) => (t m b -> t m b -> t m b) -> f a -> (a -> t m b) -> t m b
658+forEachWith = P.concatForFoldableWith
src/Streamly/Internal/Data/Pipe.hs+1−1
@@ -242,7 +242,7 @@ import Prelude
242-- import qualified Data.Map.Strict as Map
242-- import qualified Data.Map.Strict as Map
243-- import qualified Prelude
243-- import qualified Prelude
244
244
245−-- import Streamly (MonadAsync, parallel)
245+-- import Streamly.Prelude (MonadAsync, parallel)
246-- import Streamly.Data.Fold.Types (Fold(..))
246-- import Streamly.Data.Fold.Types (Fold(..))
247import Streamly.Internal.Data.Pipe.Types
247import Streamly.Internal.Data.Pipe.Types
248 (Pipe(..), PipeState(..), Step(..), zipWith, tee, map, compose)
248 (Pipe(..), PipeState(..), Step(..), zipWith, tee, map, compose)
src/Streamly/Internal/Data/SVar.hs+8−3
@@ -228,7 +228,6 @@ data WorkerInfo = WorkerInfo
228 , workerLatencyStart :: IORef (Count, AbsTime)
228 , workerLatencyStart :: IORef (Count, AbsTime)
229 }
229 }
230
230
231−
232-- | Specifies the stream yield rate in yields per second (@Hertz@).
231-- | Specifies the stream yield rate in yields per second (@Hertz@).
233-- We keep accumulating yield credits at 'rateGoal'. At any point of time we
232-- We keep accumulating yield credits at 'rateGoal'. At any point of time we
234-- allow only as many yields as we have accumulated as per 'rateGoal' since the
233-- allow only as many yields as we have accumulated as per 'rateGoal' since the
@@ -248,7 +247,9 @@ data WorkerInfo = WorkerInfo
248-- If the 'rateGoal' is 0 or negative the stream never yields a value.
247-- If the 'rateGoal' is 0 or negative the stream never yields a value.
249-- If the 'rateBuffer' is 0 or negative we do not attempt to recover.
248-- If the 'rateBuffer' is 0 or negative we do not attempt to recover.
250--
249--
250+-- /Since: 0.5.0 ("Streamly")/
251+--
251−-- @since 0.5.0
252+-- @since 0.8.0
252data Rate = Rate
253data Rate = Rate
253 { rateLow :: Double -- ^ The lower rate limit
254 { rateLow :: Double -- ^ The lower rate limit
254 , rateGoal :: Double -- ^ The target rate we want to achieve
255 , rateGoal :: Double -- ^ The target rate we want to achieve
@@ -897,11 +898,15 @@ withDiagMVar sv label action =
897-- Spawning threads
898-- Spawning threads
898------------------------------------------------------------------------------
899------------------------------------------------------------------------------
899
900
901+-- /Since: 0.8.0 ("Streamly.Prelude")/
902+--
900-- | A monad that can perform concurrent or parallel IO operations. Streams
903-- | A monad that can perform concurrent or parallel IO operations. Streams
901-- that can be composed concurrently require the underlying monad to be
904-- that can be composed concurrently require the underlying monad to be
902-- 'MonadAsync'.
905-- 'MonadAsync'.
903--
906--
907+-- /Since: 0.1.0 ("Streamly")/
908+--
904−-- @since 0.1.0
909+-- @since 0.8.0
905type MonadAsync m = (MonadIO m, MonadBaseControl IO m, MonadThrow m)
910type MonadAsync m = (MonadIO m, MonadBaseControl IO m, MonadThrow m)
906
911
907-- When we run computations concurrently, we completely isolate the state of
912-- When we run computations concurrently, we completely isolate the state of
src/Streamly/Internal/Data/Stream/Ahead.hs+15−7
@@ -596,7 +596,9 @@ infixr 6 `ahead`
596-- | Polymorphic version of the 'Semigroup' operation '<>' of 'AheadT'.
596-- | Polymorphic version of the 'Semigroup' operation '<>' of 'AheadT'.
597-- Merges two streams sequentially but with concurrent lookahead.
597-- Merges two streams sequentially but with concurrent lookahead.
598--
598--
599+-- /Since: 0.3.0 ("Streamly")/
600+--
599−-- @since 0.3.0
601+-- @since 0.8.0
600{-# INLINE ahead #-}
602{-# INLINE ahead #-}
601ahead :: (IsStream t, MonadAsync m) => t m a -> t m a -> t m a
603ahead :: (IsStream t, MonadAsync m) => t m a -> t m a -> t m a
602ahead m1 m2 = mkStream $ \st yld sng stp ->
604ahead m1 m2 = mkStream $ \st yld sng stp ->
@@ -628,12 +630,12 @@ consMAhead m r = fromStream $ K.yieldM m `ahead` (toStream r)
628-- container of streams.
630-- container of streams.
629--
631--
630-- @
632-- @
631−-- import "Streamly"
633+-- import "Streamly.Prelude"
632-- import qualified "Streamly.Prelude" as S
634-- import qualified "Streamly.Prelude" as S
633-- import Control.Concurrent
635-- import Control.Concurrent
634--
636--
635-- main = do
637-- main = do
636−-- xs \<- S.'toList' . 'aheadly' $ (p 1 |: p 2 |: nil) <> (p 3 |: p 4 |: nil)
638+-- xs \<- S.'toList' . S.'aheadly' $ (p 1 |: p 2 |: nil) <> (p 3 |: p 4 |: nil)
637-- print xs
639-- print xs
638-- where p n = threadDelay 1000000 >> return n
640-- where p n = threadDelay 1000000 >> return n
639-- @
641-- @
@@ -650,7 +652,7 @@ consMAhead m r = fromStream $ K.yieldM m `ahead` (toStream r)
650-- 'SerialT'.
652-- 'SerialT'.
651--
653--
652-- @
654-- @
653−-- main = S.drain . 'aheadly' $ do
655+-- main = S.drain . S.'aheadly' $ do
654-- n <- return 3 \<\> return 2 \<\> return 1
656-- n <- return 3 \<\> return 2 \<\> return 1
655-- S.yieldM $ do
657-- S.yieldM $ do
656-- threadDelay (n * 1000000)
658-- threadDelay (n * 1000000)
@@ -662,19 +664,25 @@ consMAhead m r = fromStream $ K.yieldM m `ahead` (toStream r)
662-- ThreadId 38: Delay 3
664-- ThreadId 38: Delay 3
663-- @
665-- @
664--
666--
667+-- /Since: 0.3.0 ("Streamly")/
668+--
665−-- @since 0.3.0
669+-- @since 0.8.0
666newtype AheadT m a = AheadT {getAheadT :: Stream m a}
670newtype AheadT m a = AheadT {getAheadT :: Stream m a}
667 deriving (MonadTrans)
671 deriving (MonadTrans)
668
672
669-- | A serial IO stream of elements of type @a@ with concurrent lookahead. See
673-- | A serial IO stream of elements of type @a@ with concurrent lookahead. See
670-- 'AheadT' documentation for more details.
674-- 'AheadT' documentation for more details.
671--
675--
676+-- /Since: 0.3.0 ("Streamly")/
677+--
672−-- @since 0.3.0
678+-- @since 0.8.0
673type Ahead = AheadT IO
679type Ahead = AheadT IO
674
680
675-- | Fix the type of a polymorphic stream as 'AheadT'.
681-- | Fix the type of a polymorphic stream as 'AheadT'.
676--
682--
683+-- /Since: 0.3.0 ("Streamly")/
684+--
677−-- @since 0.3.0
685+-- @since 0.8.0
678aheadly :: IsStream t => AheadT m a -> t m a
686aheadly :: IsStream t => AheadT m a -> t m a
679aheadly = K.adapt
687aheadly = K.adapt
680
688
src/Streamly/Internal/Data/Stream/Async.hs+31−15
@@ -513,6 +513,8 @@ mkAsyncD m = D.Stream step Nothing
513 D.Skip s -> D.Skip (Just $ D.Stream step1 s)
513 D.Skip s -> D.Skip (Just $ D.Stream step1 s)
514 D.Stop -> D.Stop
514 D.Stop -> D.Stop
515
515
516+-- /Since: 0.8.0 ("Streamly.Prelude")/
517+--
516-- This is slightly faster than the CPS version above
518-- This is slightly faster than the CPS version above
517--
519--
518-- | Make the stream producer and consumer run concurrently by introducing a
520-- | Make the stream producer and consumer run concurrently by introducing a
@@ -635,7 +637,9 @@ infixr 6 `async`
635-- Merges two streams possibly concurrently, preferring the
637-- Merges two streams possibly concurrently, preferring the
636-- elements from the left one when available.
638-- elements from the left one when available.
637--
639--
640+-- /Since: 0.2.0 ("Streamly")/
641+--
638−-- @since 0.2.0
642+-- @since 0.8.0
639{-# INLINE async #-}
643{-# INLINE async #-}
640async :: (IsStream t, MonadAsync m) => t m a -> t m a -> t m a
644async :: (IsStream t, MonadAsync m) => t m a -> t m a -> t m a
641async = joinStreamVarAsync AsyncVar
645async = joinStreamVarAsync AsyncVar
@@ -675,11 +679,10 @@ consMAsync m r = fromStream $ K.yieldM m `async` (toStream r)
675-- operation can be used to fold an infinite lazy container of streams.
679-- operation can be used to fold an infinite lazy container of streams.
676--
680--
677-- @
681-- @
678−-- import "Streamly"
679-- import qualified "Streamly.Prelude" as S
682-- import qualified "Streamly.Prelude" as S
680-- import Control.Concurrent
683-- import Control.Concurrent
681--
684--
682−-- main = (S.toList . 'asyncly' $ (S.fromList [1,2]) \<> (S.fromList [3,4])) >>= print
685+-- main = (S.toList . S.'asyncly' $ (S.fromList [1,2]) \<> (S.fromList [3,4])) >>= print
683-- @
686-- @
684-- @
687-- @
685-- [1,2,3,4]
688-- [1,2,3,4]
@@ -698,7 +701,7 @@ consMAsync m r = fromStream $ K.yieldM m `async` (toStream r)
698-- consumer.
701-- consumer.
699--
702--
700-- @
703-- @
701−-- main = 'drain' . 'asyncly' $ do
704+-- main = S.'drain' . S.'asyncly' $ do
702-- n <- return 3 \<\> return 2 \<\> return 1
705-- n <- return 3 \<\> return 2 \<\> return 1
703-- S.yieldM $ do
706-- S.yieldM $ do
704-- threadDelay (n * 1000000)
707-- threadDelay (n * 1000000)
@@ -710,19 +713,25 @@ consMAsync m r = fromStream $ K.yieldM m `async` (toStream r)
710-- ThreadId 38: Delay 3
713-- ThreadId 38: Delay 3
711-- @
714-- @
712--
715--
716+-- /Since: 0.1.0 ("Streamly")/
717+--
713−-- @since 0.1.0
718+-- @since 0.8.0
714newtype AsyncT m a = AsyncT {getAsyncT :: Stream m a}
719newtype AsyncT m a = AsyncT {getAsyncT :: Stream m a}
715 deriving (MonadTrans)
720 deriving (MonadTrans)
716
721
717-- | A demand driven left biased parallely composing IO stream of elements of
722-- | A demand driven left biased parallely composing IO stream of elements of
718-- type @a@. See 'AsyncT' documentation for more details.
723-- type @a@. See 'AsyncT' documentation for more details.
719--
724--
725+-- /Since: 0.2.0 ("Streamly")/
726+--
720−-- @since 0.2.0
727+-- @since 0.8.0
721type Async = AsyncT IO
728type Async = AsyncT IO
722
729
723-- | Fix the type of a polymorphic stream as 'AsyncT'.
730-- | Fix the type of a polymorphic stream as 'AsyncT'.
724--
731--
732+-- /Since: 0.1.0 ("Streamly")/
733+--
725−-- @since 0.1.0
734+-- @since 0.8.0
726asyncly :: IsStream t => AsyncT m a -> t m a
735asyncly :: IsStream t => AsyncT m a -> t m a
727asyncly = adapt
736asyncly = adapt
728
737
@@ -810,7 +819,9 @@ infixr 6 `wAsync`
810-- | Polymorphic version of the 'Semigroup' operation '<>' of 'WAsyncT'.
819-- | Polymorphic version of the 'Semigroup' operation '<>' of 'WAsyncT'.
811-- Merges two streams concurrently choosing elements from both fairly.
820-- Merges two streams concurrently choosing elements from both fairly.
812--
821--
813−-- @since 0.2.0
822+-- @since 0.8.0
823+--
824+-- /Since: 0.2.0 ("Streamly")/
814{-# INLINE wAsync #-}
825{-# INLINE wAsync #-}
815wAsync :: (IsStream t, MonadAsync m) => t m a -> t m a -> t m a
826wAsync :: (IsStream t, MonadAsync m) => t m a -> t m a -> t m a
816wAsync = joinStreamVarAsync WAsyncVar
827wAsync = joinStreamVarAsync WAsyncVar
@@ -828,11 +839,10 @@ wAsync = joinStreamVarAsync WAsyncVar
828-- contrast to the depth wise scheduling behavior of 'AsyncT'.
839-- contrast to the depth wise scheduling behavior of 'AsyncT'.
829--
840--
830-- @
841-- @
831−-- import "Streamly"
832-- import qualified "Streamly.Prelude" as S
842-- import qualified "Streamly.Prelude" as S
833-- import Control.Concurrent
843-- import Control.Concurrent
834--
844--
835−-- main = (S.toList . 'wAsyncly' . maxThreads 1 $ (S.fromList [1,2]) \<> (S.fromList [3,4])) >>= print
845+-- main = (S.toList . S.'wAsyncly' . S.maxThreads 1 $ (S.fromList [1,2]) \<> (S.fromList [3,4])) >>= print
836-- @
846-- @
837-- @
847-- @
838-- [1,3,2,4]
848-- [1,3,2,4]
@@ -843,7 +853,7 @@ wAsync = joinStreamVarAsync WAsyncVar
843-- now take a more general example:
853-- now take a more general example:
844--
854--
845-- @
855-- @
846−-- main = (S.toList . 'wAsyncly' . maxThreads 1 $ (S.fromList [1,2,3]) \<> (S.fromList [4,5,6]) \<> (S.fromList [7,8,9])) >>= print
856+-- main = (S.toList . S.'wAsyncly' . S.maxThreads 1 $ (S.fromList [1,2,3]) \<> (S.fromList [4,5,6]) \<> (S.fromList [7,8,9])) >>= print
847-- @
857-- @
848-- @
858-- @
849-- [1,4,2,7,5,3,8,6,9]
859-- [1,4,2,7,5,3,8,6,9]
@@ -899,7 +909,7 @@ wAsync = joinStreamVarAsync WAsyncVar
899-- concurrently using a round robin scheduling.
909-- concurrently using a round robin scheduling.
900--
910--
901-- @
911-- @
902−-- main = 'drain' . 'wAsyncly' $ do
912+-- main = S.'drain' . S.'wAsyncly' $ do
903-- n <- return 3 \<\> return 2 \<\> return 1
913-- n <- return 3 \<\> return 2 \<\> return 1
904-- S.yieldM $ do
914-- S.yieldM $ do
905-- threadDelay (n * 1000000)
915-- threadDelay (n * 1000000)
@@ -911,19 +921,25 @@ wAsync = joinStreamVarAsync WAsyncVar
911-- ThreadId 38: Delay 3
921-- ThreadId 38: Delay 3
912-- @
922-- @
913--
923--
924+-- /Since: 0.2.0 ("Streamly")/
925+--
914−-- @since 0.2.0
926+-- @since 0.8.0
915newtype WAsyncT m a = WAsyncT {getWAsyncT :: Stream m a}
927newtype WAsyncT m a = WAsyncT {getWAsyncT :: Stream m a}
916 deriving (MonadTrans)
928 deriving (MonadTrans)
917
929
918-- | A round robin parallely composing IO stream of elements of type @a@.
930-- | A round robin parallely composing IO stream of elements of type @a@.
919-- See 'WAsyncT' documentation for more details.
931-- See 'WAsyncT' documentation for more details.
920--
932--
933+-- /Since: 0.2.0 ("Streamly")/
934+--
921−-- @since 0.2.0
935+-- @since 0.8.0
922type WAsync = WAsyncT IO
936type WAsync = WAsyncT IO
923
937
924-- | Fix the type of a polymorphic stream as 'WAsyncT'.
938-- | Fix the type of a polymorphic stream as 'WAsyncT'.
925--
939--
940+-- /Since: 0.2.0 ("Streamly")/
941+--
926−-- @since 0.2.0
942+-- @since 0.8.0
927wAsyncly :: IsStream t => WAsyncT m a -> t m a
943wAsyncly :: IsStream t => WAsyncT m a -> t m a
928wAsyncly = adapt
944wAsyncly = adapt
929
945
src/Streamly/Internal/Data/Stream/Combinators.hs+21−7
@@ -48,7 +48,9 @@ import Streamly.Internal.Data.Stream.Serial (SerialT)
48-- When the actions are CPU bound this option can be used to
48-- When the actions are CPU bound this option can be used to
49-- control the amount of CPU used by the stream.
49-- control the amount of CPU used by the stream.
50--
50--
51+-- /Since: 0.4.0 ("Streamly")/
52+--
51−-- @since 0.4.0
53+-- @since 0.8.0
52{-# INLINE_NORMAL maxThreads #-}
54{-# INLINE_NORMAL maxThreads #-}
53maxThreads :: IsStream t => Int -> t m a -> t m a
55maxThreads :: IsStream t => Int -> t m a -> t m a
54maxThreads n m = mkStream $ \st stp sng yld ->
56maxThreads n m = mkStream $ \st stp sng yld ->
@@ -73,7 +75,9 @@ maxThreadsSerial _ = id
73-- applicative zip streams generates an infinite stream causing unbounded
75-- applicative zip streams generates an infinite stream causing unbounded
74-- concurrent generation with no limit on the buffer or threads.
76-- concurrent generation with no limit on the buffer or threads.
75--
77--
78+-- /Since: 0.4.0 ("Streamly")/
79+--
76−-- @since 0.4.0
80+-- @since 0.8.0
77{-# INLINE_NORMAL maxBuffer #-}
81{-# INLINE_NORMAL maxBuffer #-}
78maxBuffer :: IsStream t => Int -> t m a -> t m a
82maxBuffer :: IsStream t => Int -> t m a -> t m a
79maxBuffer n m = mkStream $ \st stp sng yld ->
83maxBuffer n m = mkStream $ \st stp sng yld ->
@@ -97,7 +101,9 @@ maxBufferSerial _ = id
97-- * The maximum rate that the stream producer can achieve
101-- * The maximum rate that the stream producer can achieve
98-- * The maximum rate that the stream consumer can achieve
102-- * The maximum rate that the stream consumer can achieve
99--
103--
104+-- /Since: 0.5.0 ("Streamly")/
105+--
100−-- @since 0.5.0
106+-- @since 0.8.0
101{-# INLINE_NORMAL rate #-}
107{-# INLINE_NORMAL rate #-}
102rate :: IsStream t => Maybe Rate -> t m a -> t m a
108rate :: IsStream t => Maybe Rate -> t m a -> t m a
103rate r m = mkStream $ \st stp sng yld ->
109rate r m = mkStream $ \st stp sng yld ->
@@ -126,7 +132,9 @@ yieldRateSerial _ = id
126-- go down to half of the specified rate on the lower side and double of
132-- go down to half of the specified rate on the lower side and double of
127-- the specified rate on the higher side.
133-- the specified rate on the higher side.
128--
134--
135+-- /Since: 0.5.0 ("Streamly")/
136+--
129−-- @since 0.5.0
137+-- @since 0.8.0
130avgRate :: IsStream t => Double -> t m a -> t m a
138avgRate :: IsStream t => Double -> t m a -> t m a
131avgRate r = rate (Just $ Rate (r/2) r (2*r) maxBound)
139avgRate r = rate (Just $ Rate (r/2) r (2*r) maxBound)
132
140
@@ -137,7 +145,9 @@ avgRate r = rate (Just $ Rate (r/2) r (2*r) maxBound)
137-- specified rate, even though it may possibly go above it at times, the
145-- specified rate, even though it may possibly go above it at times, the
138-- upper limit is double of the specified rate.
146-- upper limit is double of the specified rate.
139--
147--
148+-- /Since: 0.5.0 ("Streamly")/
149+--
140−-- @since 0.5.0
150+-- @since 0.8.0
141minRate :: IsStream t => Double -> t m a -> t m a
151minRate :: IsStream t => Double -> t m a -> t m a
142minRate r = rate (Just $ Rate r r (2*r) maxBound)
152minRate r = rate (Just $ Rate r r (2*r) maxBound)
143
153
@@ -150,7 +160,9 @@ minRate r = rate (Just $ Rate r r (2*r) maxBound)
150-- applications where certain resource usage must not be allowed to go
160-- applications where certain resource usage must not be allowed to go
151-- beyond certain limits.
161-- beyond certain limits.
152--
162--
163+-- /Since: 0.5.0 ("Streamly")/
164+--
153−-- @since 0.5.0
165+-- @since 0.8.0
154maxRate :: IsStream t => Double -> t m a -> t m a
166maxRate :: IsStream t => Double -> t m a -> t m a
155maxRate r = rate (Just $ Rate (r/2) r r maxBound)
167maxRate r = rate (Just $ Rate (r/2) r r maxBound)
156
168
@@ -162,7 +174,9 @@ maxRate r = rate (Just $ Rate (r/2) r r maxBound)
162-- applications like graphics frame refresh where we need to maintain a
174-- applications like graphics frame refresh where we need to maintain a
163-- constant refresh rate.
175-- constant refresh rate.
164--
176--
177+-- /Since: 0.5.0 ("Streamly")/
178+--
165−-- @since 0.5.0
179+-- @since 0.8.0
166constRate :: IsStream t => Double -> t m a -> t m a
180constRate :: IsStream t => Double -> t m a -> t m a
167constRate r = rate (Just $ Rate r r r 0)
181constRate r = rate (Just $ Rate r r r 0)
168
182
src/Streamly/Internal/Data/Stream/IsStream.hs+98−19
@@ -19,9 +19,51 @@
19
19
20module Streamly.Internal.Data.Stream.IsStream
20module Streamly.Internal.Data.Stream.IsStream
21 (
21 (
22+ -- * Stream Types
23+ -- ** Serial Streams
24+ SerialT
25+ , Serial
26+ , WSerialT
27+ , WSerial
28+
29+ -- ** Speculative Streams
30+ , AheadT
31+ , Ahead
32+
33+ -- ** Asynchronous Streams
34+ , AsyncT
35+ , Async
36+ , WAsyncT
37+ , WAsync
38+ , ParallelT
39+ , Parallel
40+ , mkAsync
41+
42+ -- ** Zipping Streams
43+ , ZipSerialM
44+ , ZipSerial
45+ , ZipAsyncM
46+ , ZipAsync
47+
48+ -- * Stream Type Adapters
49+ , IsStream ()
50+
51+ , serially
52+ , wSerially
53+ , asyncly
54+ , aheadly
55+ , wAsyncly
56+ , parallely
57+ , zipSerially
58+ , zipAsyncly
59+ , adapt
60+
61+ -- * Type Synonyms
62+ , MonadAsync
63+
22 -- * Construction
64 -- * Construction
23 -- ** Primitives
65 -- ** Primitives
24− K.nil
66+ , K.nil
25 , K.nilM
67 , K.nilM
26 , K.cons
68 , K.cons
27 , (K..:)
69 , (K..:)
@@ -415,6 +457,7 @@ module Streamly.Internal.Data.Stream.IsStream
415 -- * Combining Streams
457 -- * Combining Streams
416
458
417 -- ** Appending
459 -- ** Appending
460+ , serial
418 , append
461 , append
419
462
420 -- ** Interleaving
463 -- ** Interleaving
@@ -423,18 +466,22 @@ module Streamly.Internal.Data.Stream.IsStream
423 , interleaveSuffix
466 , interleaveSuffix
424 , interleaveInfix
467 , interleaveInfix
425
468
469+ , wSerial
426 , Serial.wSerialFst
470 , Serial.wSerialFst
427 , Serial.wSerialMin
471 , Serial.wSerialMin
428
472
429 -- ** Scheduling
473 -- ** Scheduling
474+ , ahead
475+ , async
476+ , wAsync
430 , roundrobin
477 , roundrobin
431
478
432 -- ** Parallel
479 -- ** Parallel
480+ , parallel
433 , Par.parallelFst
481 , Par.parallelFst
434 , Par.parallelMin
482 , Par.parallelMin
435
483
436 -- ** Merging
484 -- ** Merging
437−
438 -- , merge
485 -- , merge
439 , mergeBy
486 , mergeBy
440 , mergeByM
487 , mergeByM
@@ -448,9 +495,9 @@ module Streamly.Internal.Data.Stream.IsStream
448 , Z.zipAsyncWithM
495 , Z.zipAsyncWithM
449
496
450 -- ** Flattening a Container of Streams
497 -- ** Flattening a Container of Streams
451− , foldWith
498+ , concatFoldableWith
452− , foldMapWith
499+ , concatMapFoldableWith
453− , forEachWith
500+ , concatForFoldableWith
454
501
455 -- ** Flattening a Stream of Streams
502 -- ** Flattening a Stream of Streams
456 , concat
503 , concat
@@ -514,6 +561,18 @@ module Streamly.Internal.Data.Stream.IsStream
514 , rights
561 , rights
515 , iterateMapLeftsWith
562 , iterateMapLeftsWith
516
563
564+ -- * Concurrency Control
565+ , maxThreads
566+ , maxBuffer
567+
568+ -- * Rate Limiting
569+ , Rate (..)
570+ , rate
571+ , avgRate
572+ , minRate
573+ , maxRate
574+ , constRate
575+
517 -- * Diagnostics
576 -- * Diagnostics
518 , inspectMode
577 , inspectMode
519
578
@@ -555,14 +614,26 @@ import Streamly.Internal.Data.Fold.Types (Fold (..), Fold2 (..))
555import Streamly.Internal.Data.Parser (Parser (..))
614import Streamly.Internal.Data.Parser (Parser (..))
556import Streamly.Internal.Data.Unfold.Types (Unfold)
615import Streamly.Internal.Data.Unfold.Types (Unfold)
557import Streamly.Internal.Data.Array.Storable.Foreign.Types (Array, writeNUnsafe)
616import Streamly.Internal.Data.Array.Storable.Foreign.Types (Array, writeNUnsafe)
558−import Streamly.Internal.Data.SVar (MonadAsync, defState, Rate)
617+import Streamly.Internal.Data.SVar (MonadAsync, defState, Rate (..))
618+import Streamly.Internal.Data.Stream.Ahead (AheadT, Ahead, ahead, aheadly)
619+import Streamly.Internal.Data.Stream.Async
620+ ( AsyncT, Async, WAsyncT, WAsync, mkAsync, async, asyncly, wAsync
621+ , wAsyncly)
559−import Streamly.Internal.Data.Stream.Combinators (inspectMode, maxYields)
622+import Streamly.Internal.Data.Stream.Combinators
623+ ( inspectMode, maxBuffer, maxThreads, maxYields, rate, avgRate, minRate
624+ , maxRate, constRate)
625+import Streamly.Internal.Data.Stream.Parallel
626+ ( ParallelT, Parallel, parallel, parallely)
560import Streamly.Internal.Data.Stream.Prelude
627import Streamly.Internal.Data.Stream.Prelude
561− (fromStreamS, toStreamS, foldWith, foldMapWith, forEachWith)
628+ (fromStreamS, toStreamS, concatFoldableWith, concatMapFoldableWith
629+ , concatForFoldableWith)
562import Streamly.Internal.Data.Stream.StreamD (fromStreamD, toStreamD)
630import Streamly.Internal.Data.Stream.StreamD (fromStreamD, toStreamD)
563−import Streamly.Internal.Data.Stream.StreamK (IsStream((|:), consM))
631+import Streamly.Internal.Data.Stream.StreamK (IsStream((|:), consM), adapt)
564−import Streamly.Internal.Data.Stream.Serial (SerialT, WSerialT)
632+import Streamly.Internal.Data.Stream.Serial
633+ ( SerialT, WSerialT, Serial, WSerial, serial, wSerial, serially
634+ , wSerially)
565−import Streamly.Internal.Data.Stream.Zip (ZipSerialM)
635+import Streamly.Internal.Data.Stream.Zip
636+ ( ZipSerialM, ZipSerial, ZipAsyncM, ZipAsync, zipSerially, zipAsyncly)
566import Streamly.Internal.Data.Pipe.Types (Pipe (..))
637import Streamly.Internal.Data.Pipe.Types (Pipe (..))
567import Streamly.Internal.Data.Time.Units
638import Streamly.Internal.Data.Time.Units
568 ( AbsTime, MilliSecond64(..), addToAbsTime, toRelTime
639 ( AbsTime, MilliSecond64(..), addToAbsTime, toRelTime
@@ -918,9 +989,9 @@ iterate step = fromStreamS . S.iterate step
918--
989--
919-- /Concurrent/
990-- /Concurrent/
920--
991--
921−-- /Since: 0.7.0 (signature change)/
922−--
923-- /Since: 0.1.2/
992-- /Since: 0.1.2/
993+--
994+-- /Since: 0.7.0 (signature change)/
924{-# INLINE_EARLY iterateM #-}
995{-# INLINE_EARLY iterateM #-}
925iterateM :: (IsStream t, MonadAsync m) => (a -> m a) -> m a -> t m a
996iterateM :: (IsStream t, MonadAsync m) => (a -> m a) -> m a -> t m a
926iterateM = K.iterateM
997iterateM = K.iterateM
@@ -1997,7 +2068,9 @@ infixl 1 |&.
1997--
2068--
1998-- /Concurrent/
2069-- /Concurrent/
1999--
2070--
2071+-- /Since: 0.3.0 ("Streamly")/
2072+--
2000−-- @since 0.3.0
2073+-- @since 0.8.0
2001{-# INLINE (|$) #-}
2074{-# INLINE (|$) #-}
2002(|$) :: (IsStream t, MonadAsync m) => (t m a -> t m b) -> (t m a -> t m b)
2075(|$) :: (IsStream t, MonadAsync m) => (t m a -> t m b) -> (t m a -> t m b)
2003-- (|$) f = f . Async.mkAsync
2076-- (|$) f = f . Async.mkAsync
@@ -2024,7 +2097,9 @@ applyAsync = (|$)
2024--
2097--
2025-- /Concurrent/
2098-- /Concurrent/
2026--
2099--
2100+-- /Since: 0.3.0 ("Streamly")/
2101+--
2027−-- @since 0.3.0
2102+-- @since 0.8.0
2028{-# INLINE (|&) #-}
2103{-# INLINE (|&) #-}
2029(|&) :: (IsStream t, MonadAsync m) => t m a -> (t m a -> t m b) -> t m b
2104(|&) :: (IsStream t, MonadAsync m) => t m a -> (t m a -> t m b) -> t m b
2030x |& f = f |$ x
2105x |& f = f |$ x
@@ -2049,7 +2124,9 @@ x |& f = f |$ x
2049--
2124--
2050-- /Concurrent/
2125-- /Concurrent/
2051--
2126--
2127+-- /Since: 0.3.0 ("Streamly")/
2128+--
2052−-- @since 0.3.0
2129+-- @since 0.8.0
2053{-# INLINE (|$.) #-}
2130{-# INLINE (|$.) #-}
2054(|$.) :: (IsStream t, MonadAsync m) => (t m a -> m b) -> (t m a -> m b)
2131(|$.) :: (IsStream t, MonadAsync m) => (t m a -> m b) -> (t m a -> m b)
2055-- (|$.) f = f . Async.mkAsync
2132-- (|$.) f = f . Async.mkAsync
@@ -2073,7 +2150,9 @@ foldAsync = (|$.)
2073--
2150--
2074-- /Concurrent/
2151-- /Concurrent/
2075--
2152--
2153+-- /Since: 0.3.0 ("Streamly")/
2154+--
2076−-- @since 0.3.0
2155+-- @since 0.8.0
2077{-# INLINE (|&.) #-}
2156{-# INLINE (|&.) #-}
2078(|&.) :: (IsStream t, MonadAsync m) => t m a -> (t m a -> m b) -> m b
2157(|&.) :: (IsStream t, MonadAsync m) => t m a -> (t m a -> m b) -> m b
2079x |&. f = f |$. x
2158x |&. f = f |$. x
@@ -2109,9 +2188,9 @@ transform pipe xs = fromStreamD $ D.transform pipe (toStreamD xs)
2109-- designed to work with the @foldl@ library. The suffix @x@ is a mnemonic for
2188-- designed to work with the @foldl@ library. The suffix @x@ is a mnemonic for
2110-- extraction.
2189-- extraction.
2111--
2190--
2112−-- /Since: 0.7.0 (Monad m constraint)/
2113−--
2114-- /Since 0.2.0/
2191-- /Since 0.2.0/
2192+--
2193+-- /Since: 0.7.0 (Monad m constraint)/
2115{-# DEPRECATED scanx "Please use scanl followed by map instead." #-}
2194{-# DEPRECATED scanx "Please use scanl followed by map instead." #-}
2116{-# INLINE scanx #-}
2195{-# INLINE scanx #-}
2117scanx :: (IsStream t, Monad m) => (x -> a -> x) -> x -> (x -> b) -> t m a -> t m b
2196scanx :: (IsStream t, Monad m) => (x -> a -> x) -> x -> (x -> b) -> t m a -> t m b
src/Streamly/Internal/Data/Stream/Parallel.hs+14−7
@@ -249,7 +249,9 @@ infixr 6 `parallel`
249--
249--
250-- `nilM` is currently @Internal@.
250-- `nilM` is currently @Internal@.
251--
251--
252+-- /Since: 0.2.0 ("Streamly")/
253+--
252−-- @since 0.2.0
254+-- @since 0.8.0
253{-# INLINE parallel #-}
255{-# INLINE parallel #-}
254parallel :: (IsStream t, MonadAsync m) => t m a -> t m a -> t m a
256parallel :: (IsStream t, MonadAsync m) => t m a -> t m a -> t m a
255parallel = joinStreamVarPar ParallelVar StopNone
257parallel = joinStreamVarPar ParallelVar StopNone
@@ -451,7 +453,7 @@ distributeAsync_ = flip (foldr tapAsync)
451-- efficient than 'ParallelT'.
453-- efficient than 'ParallelT'.
452--
454--
453-- @
455-- @
454−-- main = ('toList' . 'parallely' $ (fromFoldable [1,2]) \<> (fromFoldable [3,4])) >>= print
456+-- main = (S.'toList' . S.'parallely' $ (S.fromFoldable [1,2]) \<> (S.fromFoldable [3,4])) >>= print
455-- @
457-- @
456-- @
458-- @
457-- [1,3,2,4]
459-- [1,3,2,4]
@@ -471,11 +473,10 @@ distributeAsync_ = flip (foldr tapAsync)
471-- of the loop concurrently.
473-- of the loop concurrently.
472--
474--
473-- @
475-- @
474−-- import "Streamly"
475-- import qualified "Streamly.Prelude" as S
476-- import qualified "Streamly.Prelude" as S
476-- import Control.Concurrent
477-- import Control.Concurrent
477--
478--
478−-- main = 'drain' . 'parallely' $ do
479+-- main = S.'drain' . S.'parallely' $ do
479-- n <- return 3 \<\> return 2 \<\> return 1
480-- n <- return 3 \<\> return 2 \<\> return 1
480-- S.yieldM $ do
481-- S.yieldM $ do
481-- threadDelay (n * 1000000)
482-- threadDelay (n * 1000000)
@@ -490,21 +491,27 @@ distributeAsync_ = flip (foldr tapAsync)
490-- Note that parallel composition can only combine a finite number of
491-- Note that parallel composition can only combine a finite number of
491-- streams as it needs to retain state for each unfinished stream.
492-- streams as it needs to retain state for each unfinished stream.
492--
493--
494+-- /Since: 0.1.0 ("Streamly")/
495+--
493-- /Since: 0.7.0 (maxBuffer applies to ParallelT streams)/
496-- /Since: 0.7.0 (maxBuffer applies to ParallelT streams)/
494--
497--
495−-- /Since: 0.1.0/
498+-- @since 0.8.0
496newtype ParallelT m a = ParallelT {getParallelT :: Stream m a}
499newtype ParallelT m a = ParallelT {getParallelT :: Stream m a}
497 deriving (MonadTrans)
500 deriving (MonadTrans)
498
501
499-- | A parallely composing IO stream of elements of type @a@.
502-- | A parallely composing IO stream of elements of type @a@.
500-- See 'ParallelT' documentation for more details.
503-- See 'ParallelT' documentation for more details.
501--
504--
505+-- /Since: 0.2.0 ("Streamly")/
506+--
502−-- @since 0.2.0
507+-- @since 0.8.0
503type Parallel = ParallelT IO
508type Parallel = ParallelT IO
504
509
505-- | Fix the type of a polymorphic stream as 'ParallelT'.
510-- | Fix the type of a polymorphic stream as 'ParallelT'.
506--
511--
512+-- /Since: 0.1.0 ("Streamly")/
513+--
507−-- @since 0.1.0
514+-- @since 0.8.0
508parallely :: IsStream t => ParallelT m a -> t m a
515parallely :: IsStream t => ParallelT m a -> t m a
509parallely = adapt
516parallely = adapt
510
517
src/Streamly/Internal/Data/Stream/Prelude.hs+25−24
@@ -58,9 +58,9 @@ module Streamly.Internal.Data.Stream.Prelude
58 , K.concatMap
58 , K.concatMap
59
59
60 -- * Fold Utilities
60 -- * Fold Utilities
61− , foldWith
61+ , concatFoldableWith
62− , foldMapWith
62+ , concatMapFoldableWith
63− , forEachWith
63+ , concatForFoldableWith
64 )
64 )
65where
65where
66
66
@@ -292,58 +292,59 @@ foldbWith :: IsStream t
292foldbWith f = K.foldb f K.nil
292foldbWith f = K.foldb f K.nil
293-}
293-}
294
294
295−-- /Since: 0.7.0 ("Streamly.Prelude")/
295+
296−--
297-- | A variant of 'Data.Foldable.fold' that allows you to fold a 'Foldable'
296-- | A variant of 'Data.Foldable.fold' that allows you to fold a 'Foldable'
298-- container of streams using the specified stream sum operation.
297-- container of streams using the specified stream sum operation.
299--
298--
300−-- @foldWith 'async' $ map return [1..3]@
299+-- @concatFoldableWith 'async' $ map return [1..3]@
301--
300--
302-- Equivalent to:
301-- Equivalent to:
303--
302--
304-- @
303-- @
305−-- foldWith f = S.foldMapWith f id
304+-- concatFoldableWith f = S.concatMapFoldableWith f id
306-- @
305-- @
307--
306--
307+-- /Since: 0.8.0 (Renamed foldWith to concatFoldableWith)/
308+--
308-- /Since: 0.1.0 ("Streamly")/
309-- /Since: 0.1.0 ("Streamly")/
309−{-# INLINABLE foldWith #-}
310+{-# INLINABLE concatFoldableWith #-}
310−foldWith :: (IsStream t, Foldable f)
311+concatFoldableWith :: (IsStream t, Foldable f)
311 => (t m a -> t m a -> t m a) -> f (t m a) -> t m a
312 => (t m a -> t m a -> t m a) -> f (t m a) -> t m a
312−foldWith f = Prelude.foldr f K.nil
313+concatFoldableWith f = Prelude.foldr f K.nil
313
314
314−-- /Since: 0.7.0 ("Streamly.Prelude")/
315−--
316-- | A variant of 'foldMap' that allows you to map a monadic streaming action
315-- | A variant of 'foldMap' that allows you to map a monadic streaming action
317-- on a 'Foldable' container and then fold it using the specified stream merge
316-- on a 'Foldable' container and then fold it using the specified stream merge
318-- operation.
317-- operation.
319--
318--
320−-- @foldMapWith 'async' return [1..3]@
319+-- @concatMapFoldableWith 'async' return [1..3]@
321--
320--
322-- Equivalent to:
321-- Equivalent to:
323--
322--
324-- @
323-- @
325−-- foldMapWith f g xs = S.concatMapWith f g (S.fromFoldable xs)
324+-- concatMapFoldableWith f g xs = S.concatMapWith f g (S.fromFoldable xs)
326-- @
325-- @
327--
326--
327+-- /Since: 0.8.0 (Renamed foldMapWith to concatMapFoldableWith)/
328+--
328-- /Since: 0.1.0 ("Streamly")/
329-- /Since: 0.1.0 ("Streamly")/
329−{-# INLINABLE foldMapWith #-}
330+{-# INLINABLE concatMapFoldableWith #-}
330−foldMapWith :: (IsStream t, Foldable f)
331+concatMapFoldableWith :: (IsStream t, Foldable f)
331 => (t m b -> t m b -> t m b) -> (a -> t m b) -> f a -> t m b
332 => (t m b -> t m b -> t m b) -> (a -> t m b) -> f a -> t m b
332−foldMapWith f g = Prelude.foldr (f . g) K.nil
333+concatMapFoldableWith f g = Prelude.foldr (f . g) K.nil
333
334
334−-- /Since: 0.7.0 ("Streamly.Prelude")/
335−--
336−-- | Like 'foldMapWith' but with the last two arguments reversed i.e. the
335+-- | Like 'concatMapFoldableWith' but with the last two arguments reversed i.e. the
337-- monadic streaming function is the last argument.
336-- monadic streaming function is the last argument.
338--
337--
339-- Equivalent to:
338-- Equivalent to:
340--
339--
341-- @
340-- @
342−-- forEachWith = flip S.foldMapWith
341+-- concatForFoldableWith = flip S.concatMapFoldableWith
343-- @
342-- @
344--
343--
344+-- /Since: 0.8.0 (Renamed forEachWith to concatForFoldableWith)/
345+--
345-- /Since: 0.1.0 ("Streamly")/
346-- /Since: 0.1.0 ("Streamly")/
346−{-# INLINABLE forEachWith #-}
347+{-# INLINABLE concatForFoldableWith #-}
347−forEachWith :: (IsStream t, Foldable f)
348+concatForFoldableWith :: (IsStream t, Foldable f)
348 => (t m b -> t m b -> t m b) -> f a -> (a -> t m b) -> t m b
349 => (t m b -> t m b -> t m b) -> f a -> (a -> t m b) -> t m b
349−forEachWith f xs g = Prelude.foldr (f . g) K.nil xs
350+concatForFoldableWith f xs g = Prelude.foldr (f . g) K.nil xs
src/Streamly/Internal/Data/Stream/Serial.hs+21−7
@@ -137,7 +137,9 @@ import Prelude hiding (map, mapM, errorWithoutStackTrace)
137-- In the code above, the 'serially' combinator can be omitted as the default
137-- In the code above, the 'serially' combinator can be omitted as the default
138-- stream type is 'SerialT'.
138-- stream type is 'SerialT'.
139--
139--
140+-- /Since: 0.2.0 ("Streamly")/
141+--
140−-- @since 0.2.0
142+-- @since 0.8.0
141newtype SerialT m a = SerialT {getSerialT :: Stream m a}
143newtype SerialT m a = SerialT {getSerialT :: Stream m a}
142 -- XXX when deriving do we inherit an INLINE?
144 -- XXX when deriving do we inherit an INLINE?
143 deriving (Semigroup, Monoid, MonadTrans)
145 deriving (Semigroup, Monoid, MonadTrans)
@@ -145,7 +147,9 @@ newtype SerialT m a = SerialT {getSerialT :: Stream m a}
145-- | A serial IO stream of elements of type @a@. See 'SerialT' documentation
147-- | A serial IO stream of elements of type @a@. See 'SerialT' documentation
146-- for more details.
148-- for more details.
147--
149--
150+-- /Since: 0.2.0 ("Streamly")/
151+--
148−-- @since 0.2.0
152+-- @since 0.8.0
149type Serial = SerialT IO
153type Serial = SerialT IO
150
154
151-- |
155-- |
@@ -155,7 +159,9 @@ type StreamT = SerialT
155
159
156-- | Fix the type of a polymorphic stream as 'SerialT'.
160-- | Fix the type of a polymorphic stream as 'SerialT'.
157--
161--
162+-- /Since: 0.1.0 ("Streamly")/
163+--
158−-- @since 0.1.0
164+-- @since 0.8.0
159serially :: IsStream t => SerialT m a -> t m a
165serially :: IsStream t => SerialT m a -> t m a
160serially = adapt
166serially = adapt
161
167
@@ -309,14 +315,18 @@ TRAVERSABLE_INSTANCE(SerialT)
309-- (2,4)
315-- (2,4)
310-- @
316-- @
311--
317--
318+-- /Since: 0.2.0 ("Streamly")/
319+--
312−-- @since 0.2.0
320+-- @since 0.8.0
313newtype WSerialT m a = WSerialT {getWSerialT :: Stream m a}
321newtype WSerialT m a = WSerialT {getWSerialT :: Stream m a}
314 deriving (MonadTrans)
322 deriving (MonadTrans)
315
323
316-- | An interleaving serial IO stream of elements of type @a@. See 'WSerialT'
324-- | An interleaving serial IO stream of elements of type @a@. See 'WSerialT'
317-- documentation for more details.
325-- documentation for more details.
318--
326--
327+-- /Since: 0.2.0 ("Streamly")/
328+--
319−-- @since 0.2.0
329+-- @since 0.8.0
320type WSerial = WSerialT IO
330type WSerial = WSerialT IO
321
331
322-- |
332-- |
@@ -326,7 +336,9 @@ type InterleavedT = WSerialT
326
336
327-- | Fix the type of a polymorphic stream as 'WSerialT'.
337-- | Fix the type of a polymorphic stream as 'WSerialT'.
328--
338--
339+-- /Since: 0.2.0 ("Streamly")/
340+--
329−-- @since 0.2.0
341+-- @since 0.8.0
330wSerially :: IsStream t => WSerialT m a -> t m a
342wSerially :: IsStream t => WSerialT m a -> t m a
331wSerially = adapt
343wSerially = adapt
332
344
@@ -372,7 +384,9 @@ infixr 6 `wSerial`
372-- When one stream stops the rest of the other stream is used in the output
384-- When one stream stops the rest of the other stream is used in the output
373-- stream.
385-- stream.
374--
386--
375−-- @since 0.2.0
387+-- @since 0.8.0
388+--
389+-- /Since: 0.2.0 ("Streamly")/
376{-# INLINE wSerial #-}
390{-# INLINE wSerial #-}
377wSerial :: IsStream t => t m a -> t m a -> t m a
391wSerial :: IsStream t => t m a -> t m a -> t m a
378wSerial m1 m2 = mkStream $ \st yld sng stp -> do
392wSerial m1 m2 = mkStream $ \st yld sng stp -> do
src/Streamly/Internal/Data/Stream/StreamK/Type.hs+9−3
@@ -132,7 +132,9 @@ infixr 5 |:
132-- | Class of types that can represent a stream of elements of some type 'a' in
132-- | Class of types that can represent a stream of elements of some type 'a' in
133-- some monad 'm'.
133-- some monad 'm'.
134--
134--
135+-- /Since: 0.2.0 ("Streamly")/
136+--
135−-- @since 0.2.0
137+-- @since 0.8.0
136class
138class
137#if __GLASGOW_HASKELL__ >= 806
139#if __GLASGOW_HASKELL__ >= 806
138 ( forall m a. MonadAsync m => Semigroup (t m a)
140 ( forall m a. MonadAsync m => Semigroup (t m a)
@@ -198,7 +200,9 @@ type Streaming = IsStream
198--
200--
199-- | Adapt any specific stream type to any other specific stream type.
201-- | Adapt any specific stream type to any other specific stream type.
200--
202--
203+-- /Since: 0.1.0 ("Streamly")/
204+--
201−-- @since 0.1.0
205+-- @since 0.8.0
202adapt :: (IsStream t1, IsStream t2) => t1 m a -> t2 m a
206adapt :: (IsStream t1, IsStream t2) => t1 m a -> t2 m a
203adapt = fromStream . toStream
207adapt = fromStream . toStream
204
208
@@ -761,7 +765,9 @@ infixr 6 `serial`
761-- Appends two streams sequentially, yielding all elements from the first
765-- Appends two streams sequentially, yielding all elements from the first
762-- stream, and then all elements from the second stream.
766-- stream, and then all elements from the second stream.
763--
767--
768+-- /Since: 0.2.0 ("Streamly")/
769+--
764−-- @since 0.2.0
770+-- @since 0.8.0
765{-# INLINE serial #-}
771{-# INLINE serial #-}
766serial :: IsStream t => t m a -> t m a -> t m a
772serial :: IsStream t => t m a -> t m a -> t m a
767-- XXX This doubles the time of toNullAp benchmark, may not be fusing properly
773-- XXX This doubles the time of toNullAp benchmark, may not be fusing properly
src/Streamly/Internal/Data/Stream/Zip.hs+18−6
@@ -130,7 +130,9 @@ zipAsyncWith f = zipAsyncWithM (\a b -> return (f a b))
130-- The 'Semigroup' instance of this type works the same way as that of
130-- The 'Semigroup' instance of this type works the same way as that of
131-- 'SerialT'.
131-- 'SerialT'.
132--
132--
133+-- /Since: 0.2.0 ("Streamly")/
134+--
133−-- @since 0.2.0
135+-- @since 0.8.0
134newtype ZipSerialM m a = ZipSerialM {getZipSerialM :: Stream m a}
136newtype ZipSerialM m a = ZipSerialM {getZipSerialM :: Stream m a}
135 deriving (Semigroup, Monoid)
137 deriving (Semigroup, Monoid)
136
138
@@ -141,12 +143,16 @@ type ZipStream = ZipSerialM
141
143
142-- | An IO stream whose applicative instance zips streams serially.
144-- | An IO stream whose applicative instance zips streams serially.
143--
145--
146+-- /Since: 0.2.0 ("Streamly")/
147+--
144−-- @since 0.2.0
148+-- @since 0.8.0
145type ZipSerial = ZipSerialM IO
149type ZipSerial = ZipSerialM IO
146
150
147-- | Fix the type of a polymorphic stream as 'ZipSerialM'.
151-- | Fix the type of a polymorphic stream as 'ZipSerialM'.
148--
152--
153+-- /Since: 0.2.0 ("Streamly")/
154+--
149−-- @since 0.2.0
155+-- @since 0.8.0
150zipSerially :: IsStream t => ZipSerialM m a -> t m a
156zipSerially :: IsStream t => ZipSerialM m a -> t m a
151zipSerially = K.adapt
157zipSerially = K.adapt
152
158
@@ -209,18 +215,24 @@ TRAVERSABLE_INSTANCE(ZipSerialM)
209-- The 'Semigroup' instance of this type works the same way as that of
215-- The 'Semigroup' instance of this type works the same way as that of
210-- 'SerialT'.
216-- 'SerialT'.
211--
217--
218+-- /Since: 0.2.0 ("Streamly")/
219+--
212−-- @since 0.2.0
220+-- @since 0.8.0
213newtype ZipAsyncM m a = ZipAsyncM {getZipAsyncM :: Stream m a}
221newtype ZipAsyncM m a = ZipAsyncM {getZipAsyncM :: Stream m a}
214 deriving (Semigroup, Monoid)
222 deriving (Semigroup, Monoid)
215
223
216-- | An IO stream whose applicative instance zips streams wAsyncly.
224-- | An IO stream whose applicative instance zips streams wAsyncly.
217--
225--
226+-- /Since: 0.2.0 ("Streamly")/
227+--
218−-- @since 0.2.0
228+-- @since 0.8.0
219type ZipAsync = ZipAsyncM IO
229type ZipAsync = ZipAsyncM IO
220
230
221-- | Fix the type of a polymorphic stream as 'ZipAsyncM'.
231-- | Fix the type of a polymorphic stream as 'ZipAsyncM'.
222--
232--
233+-- /Since: 0.2.0 ("Streamly")/
234+--
223−-- @since 0.2.0
235+-- @since 0.8.0
224zipAsyncly :: IsStream t => ZipAsyncM m a -> t m a
236zipAsyncly :: IsStream t => ZipAsyncM m a -> t m a
225zipAsyncly = K.adapt
237zipAsyncly = K.adapt
226
238
src/Streamly/Internal/FileSystem/Event/Darwin.hs+1−1
@@ -162,7 +162,7 @@ import Foreign.Marshal.Array (withArray)
162import Foreign.Ptr (Ptr, castPtr)
162import Foreign.Ptr (Ptr, castPtr)
163import Foreign.Storable (Storable(..))
163import Foreign.Storable (Storable(..))
164import GHC.IO.Handle.FD (fdToHandle)
164import GHC.IO.Handle.FD (fdToHandle)
165−import Streamly (SerialT)
165+import Streamly.Prelude (SerialT)
166import Streamly.Internal.Data.Cont (contListMap)
166import Streamly.Internal.Data.Cont (contListMap)
167import Streamly.Internal.Data.Parser (Parser)
167import Streamly.Internal.Data.Parser (Parser)
168import Streamly.Internal.Data.Array.Storable.Foreign.Types (Array(..))
168import Streamly.Internal.Data.Array.Storable.Foreign.Types (Array(..))
src/Streamly/Internal/FileSystem/Event/Linux.hs+1−1
@@ -159,7 +159,7 @@ import Foreign.Storable (peek, peekByteOff, sizeOf)
159import GHC.IO.Device (IODeviceType(Stream))
159import GHC.IO.Device (IODeviceType(Stream))
160import GHC.IO.FD (fdFD, mkFD)
160import GHC.IO.FD (fdFD, mkFD)
161import GHC.IO.Handle.FD (mkHandleFromFD)
161import GHC.IO.Handle.FD (mkHandleFromFD)
162−import Streamly (SerialT)
162+import Streamly.Prelude (SerialT)
163import Streamly.Internal.Data.Parser (Parser)
163import Streamly.Internal.Data.Parser (Parser)
164import Streamly.Internal.Data.Array.Storable.Foreign.Types (Array(..))
164import Streamly.Internal.Data.Array.Storable.Foreign.Types (Array(..))
165import System.IO (Handle, hClose, IOMode(ReadMode))
165import System.IO (Handle, hClose, IOMode(ReadMode))
src/Streamly/Internal/FileSystem/Handle.hs+1−1
@@ -109,7 +109,7 @@ import GHC.ForeignPtr (mallocPlainForeignPtrBytes)
109import System.IO (Handle, hGetBufSome, hPutBuf, stdin, stdout)
109import System.IO (Handle, hGetBufSome, hPutBuf, stdin, stdout)
110import Prelude hiding (read)
110import Prelude hiding (read)
111
111
112−import Streamly (MonadAsync)
112+import Streamly.Prelude (MonadAsync)
113import Streamly.Data.Fold (Fold)
113import Streamly.Data.Fold (Fold)
114import Streamly.Internal.Data.Fold.Types (Fold2(..))
114import Streamly.Internal.Data.Fold.Types (Fold2(..))
115import Streamly.Internal.Data.Unfold.Types (Unfold(..))
115import Streamly.Internal.Data.Unfold.Types (Unfold(..))
src/Streamly/Internal/Network/Inet/TCP.hs+1−1
@@ -103,7 +103,7 @@ import Network.Socket
103 socket)
103 socket)
104import Prelude hiding (read)
104import Prelude hiding (read)
105
105
106−import Streamly (MonadAsync)
106+import Streamly.Prelude (MonadAsync)
107import Streamly.Internal.Data.Fold.Types (Fold(..))
107import Streamly.Internal.Data.Fold.Types (Fold(..))
108import Streamly.Internal.Data.SVar (fork)
108import Streamly.Internal.Data.SVar (fork)
109import Streamly.Internal.Data.Unfold.Types (Unfold(..))
109import Streamly.Internal.Data.Unfold.Types (Unfold(..))
src/Streamly/Internal/Network/Socket.hs+1−1
@@ -87,7 +87,7 @@ import Prelude hiding (read)
87
87
88import qualified Network.Socket as Net
88import qualified Network.Socket as Net
89
89
90−import Streamly (MonadAsync)
90+import Streamly.Prelude (MonadAsync)
91import Streamly.Internal.Data.Unfold.Types (Unfold(..))
91import Streamly.Internal.Data.Unfold.Types (Unfold(..))
92import Streamly.Internal.Data.Array.Storable.Foreign.Types (Array(..), lpackArraysChunksOf)
92import Streamly.Internal.Data.Array.Storable.Foreign.Types (Array(..), lpackArraysChunksOf)
93import Streamly.Internal.Data.Array.Storable.Foreign.Mut.Types (mutableArray)
93import Streamly.Internal.Data.Array.Storable.Foreign.Mut.Types (mutableArray)
src/Streamly/Internal/Unicode/Array/Char.hs+2−1
@@ -18,9 +18,10 @@ module Streamly.Internal.Unicode.Array.Char
18where
18where
19
19
20import Control.Monad.IO.Class (MonadIO)
20import Control.Monad.IO.Class (MonadIO)
21−import Streamly (IsStream, MonadAsync)
21+import Streamly.Prelude (MonadAsync)
22import Prelude hiding (String, lines, words, unlines, unwords)
22import Prelude hiding (String, lines, words, unlines, unwords)
23import Streamly.Data.Array.Storable.Foreign (Array)
23import Streamly.Data.Array.Storable.Foreign (Array)
24+import Streamly.Internal.Data.Stream.IsStream (IsStream)
24
25
25import qualified Streamly.Internal.Unicode.Stream as S
26import qualified Streamly.Internal.Unicode.Stream as S
26import qualified Streamly.Data.Array.Storable.Foreign as A
27import qualified Streamly.Data.Array.Storable.Foreign as A
src/Streamly/Internal/Unicode/Array/Prim/Pinned.hs+2−1
@@ -18,8 +18,9 @@ module Streamly.Internal.Unicode.Array.Prim.Pinned
18where
18where
19
19
20import Control.Monad.IO.Class (MonadIO(..))
20import Control.Monad.IO.Class (MonadIO(..))
21−import Streamly (IsStream, MonadAsync)
21+import Streamly.Prelude (MonadAsync)
22import Prelude hiding (String, lines, words, unlines, unwords)
22import Prelude hiding (String, lines, words, unlines, unwords)
23+import Streamly.Internal.Data.Stream.IsStream (IsStream)
23import Streamly.Internal.Data.Array.Prim.Pinned (Array)
24import Streamly.Internal.Data.Array.Prim.Pinned (Array)
24
25
25import qualified Streamly.Internal.Unicode.Stream as S
26import qualified Streamly.Internal.Unicode.Stream as S
src/Streamly/Internal/Unicode/Char.hs+1−1
@@ -24,7 +24,7 @@ where
24
24
25import Data.Char (isAsciiUpper, isAsciiLower)
25import Data.Char (isAsciiUpper, isAsciiLower)
26
26
27−-- import Streamly (IsStream)
27+-- import Streamly.Prelude (IsStream)
28
28
29-------------------------------------------------------------------------------
29-------------------------------------------------------------------------------
30-- Unicode aware operations on strings
30-- Unicode aware operations on strings
src/Streamly/Internal/Unicode/Stream.hs+1−1
@@ -66,11 +66,11 @@ import GHC.ForeignPtr (ForeignPtr (..))
66import GHC.IO.Encoding.Failure (isSurrogate)
66import GHC.IO.Encoding.Failure (isSurrogate)
67import GHC.Ptr (Ptr (..), plusPtr)
67import GHC.Ptr (Ptr (..), plusPtr)
68import System.IO.Unsafe (unsafePerformIO)
68import System.IO.Unsafe (unsafePerformIO)
69−import Streamly (IsStream)
70import Streamly.Data.Fold (Fold)
69import Streamly.Data.Fold (Fold)
71import Streamly.Data.Array.Storable.Foreign (Array)
70import Streamly.Data.Array.Storable.Foreign (Array)
72import Streamly.Internal.Data.Unfold (Unfold)
71import Streamly.Internal.Data.Unfold (Unfold)
73import Streamly.Internal.Data.SVar (adaptState)
72import Streamly.Internal.Data.SVar (adaptState)
73+import Streamly.Internal.Data.Stream.IsStream (IsStream)
74import Streamly.Internal.Data.Stream.StreamD (Stream(..), Step (..))
74import Streamly.Internal.Data.Stream.StreamD (Stream(..), Step (..))
75import Streamly.Internal.Data.Tuple.Strict (Tuple'(..))
75import Streamly.Internal.Data.Tuple.Strict (Tuple'(..))
76
76
src/Streamly/Prelude.hs+274−16
@@ -34,11 +34,62 @@
34-- Deconstruction and folds accept a 'SerialT' type instead of a polymorphic
34-- Deconstruction and folds accept a 'SerialT' type instead of a polymorphic
35-- type to ensure that streams always have a concrete monomorphic type by
35-- type to ensure that streams always have a concrete monomorphic type by
36-- default, reducing type errors. In case you want to use any other type of
36-- default, reducing type errors. In case you want to use any other type of
37−-- stream you can use one of the type combinators provided in the "Streamly"
37+-- stream you can use one of the type combinators provided to convert the
38−-- module to convert the stream type.
38+-- stream type.
39
39
40module Streamly.Prelude
40module Streamly.Prelude
41 (
41 (
42+ -- * Stream Types
43+ -- $streamtypes
44+
45+ -- ** Serial Streams
46+ -- $serial
47+ SerialT
48+ , WSerialT
49+
50+ -- ** Speculative Streams
51+ -- $ahead
52+ , AheadT
53+
54+ -- ** Asynchronous Streams
55+ -- $async
56+ , AsyncT
57+ , WAsyncT
58+ , ParallelT
59+ , mkAsync
60+
61+ -- ** Zipping Streams
62+ -- $zipping
63+ , ZipSerialM
64+ , ZipAsyncM
65+
66+ -- * IO Streams
67+ , Serial
68+ , WSerial
69+ , Ahead
70+ , Async
71+ , WAsync
72+ , Parallel
73+ , ZipSerial
74+ , ZipAsync
75+
76+ -- * Type Synonyms
77+ , MonadAsync
78+
79+ -- * Stream Type Adapters
80+ -- $adapters
81+ , IsStream ()
82+
83+ , serially
84+ , wSerially
85+ , asyncly
86+ , aheadly
87+ , wAsyncly
88+ , parallely
89+ , zipSerially
90+ , zipAsyncly
91+ , adapt
92+
42 -- * Construction
93 -- * Construction
43 -- ** Primitives
94 -- ** Primitives
44 -- | Primitives to construct a stream from pure values or monadic actions.
95 -- | Primitives to construct a stream from pure values or monadic actions.
@@ -47,7 +98,7 @@ module Streamly.Prelude
47 -- versions provided in this module can be much more efficient in most
98 -- versions provided in this module can be much more efficient in most
48 -- cases. Users can create custom combinators using these primitives.
99 -- cases. Users can create custom combinators using these primitives.
49
100
50− nil
101+ , nil
51 , cons
102 , cons
52 , (.:)
103 , (.:)
53
104
@@ -263,6 +314,13 @@ module Streamly.Prelude
263 -- trimming sequences
314 -- trimming sequences
264 , stripPrefix
315 , stripPrefix
265
316
317+ -- * Parallel Function Application
318+ -- $application
319+ , (|$)
320+ , (|&)
321+ , (|$.)
322+ , (|&.)
323+
266 -- * Transformation
324 -- * Transformation
267
325
268 -- ** Mapping
326 -- ** Mapping
@@ -464,6 +522,16 @@ module Streamly.Prelude
464 -- >> S.toList $ fold $ [S.fromList [1,2], S.fromList [3,4]]
522 -- >> S.toList $ fold $ [S.fromList [1,2], S.fromList [3,4]]
465 -- [1,2,3,4]
523 -- [1,2,3,4]
466 -- @
524 -- @
525+ , serial
526+
527+ -- ** Interleaving
528+ , wSerial
529+
530+ -- ** Scheduling
531+ , ahead
532+ , async
533+ , wAsync
534+ , parallel
467
535
468 -- ** Merging
536 -- ** Merging
469 -- | Streams form a commutative semigroup under the merge
537 -- | Streams form a commutative semigroup under the merge
@@ -498,18 +566,6 @@ module Streamly.Prelude
498 , zipAsyncWith
566 , zipAsyncWith
499 , zipAsyncWithM
567 , zipAsyncWithM
500
568
501− {-
502− -- ** Folding Containers of Streams
503− -- | These are variants of standard 'Foldable' fold functions that use a
504− -- polymorphic stream sum operation (e.g. 'async' or 'wSerial') to fold a
505− -- finite container of streams. Note that these are just special cases of
506− -- the more general 'concatMapWith' operation.
507− --
508− , foldMapWith
509− , forEachWith
510− , foldWith
511− -}
512−
513 -- ** Folding Streams of Streams
569 -- ** Folding Streams of Streams
514 -- | Stream operations like map and filter represent loop processing in
570 -- | Stream operations like map and filter represent loop processing in
515 -- imperative programming terms. Similarly, the imperative concept of
571 -- imperative programming terms. Similarly, the imperative concept of
@@ -539,6 +595,16 @@ module Streamly.Prelude
539 , concatMapM
595 , concatMapM
540 , concatUnfold
596 , concatUnfold
541
597
598+ -- ** Folding Containers of Streams
599+ -- | These are variants of standard 'Foldable' fold functions that use a
600+ -- polymorphic stream sum operation (e.g. 'async' or 'wSerial') to fold a
601+ -- finite container of streams. Note that these are just special cases of
602+ -- the more general 'concatMapWith' operation.
603+ --
604+ , concatFoldableWith
605+ , concatMapFoldableWith
606+ , concatForFoldableWith
607+
542 -- * Exceptions
608 -- * Exceptions
543 , before
609 , before
544 , after
610 , after
@@ -547,6 +613,19 @@ module Streamly.Prelude
547 , finally
613 , finally
548 , handle
614 , handle
549
615
616+ -- * Concurrency Control
617+ -- $concurrency
618+ , maxThreads
619+ , maxBuffer
620+
621+ -- * Rate Limiting
622+ , Rate (..)
623+ , rate
624+ , avgRate
625+ , minRate
626+ , maxRate
627+ , constRate
628+
550 -- * Deprecated
629 -- * Deprecated
551 , once
630 , once
552 , each
631 , each
@@ -571,9 +650,124 @@ import Prelude
571
650
572import Streamly.Internal.Data.Stream.IsStream
651import Streamly.Internal.Data.Stream.IsStream
573
652
653+
654+-- $streamtypes
655+-- The basic stream type is 'Serial', it represents a sequence of IO actions,
656+-- and is a 'Monad'. The type 'SerialT' is a monad transformer that can
657+-- represent a sequence of actions in an arbitrary monad. The type 'Serial' is
658+-- in fact a synonym for @SerialT IO@. There are a few more types similar to
659+-- 'SerialT', all of them represent a stream and differ only in the
660+-- 'Semigroup', 'Applicative' and 'Monad' compositions of the stream. 'Serial'
661+-- and 'WSerial' types compose serially whereas 'Async' and 'WAsync'
662+-- types compose concurrently. All these types can be freely inter-converted
663+-- using type combinators without any cost. You can freely switch to any type
664+-- of composition at any point in the program. When no type annotation or
665+-- explicit stream type combinators are used, the default stream type is
666+-- inferred as 'Serial'.
667+
668+-- $serial
669+--
670+-- When a stream consumer demands an element from a serial stream constructed
671+-- as @a \`consM` b \`consM` ... nil@, the action @a@ at the head of the stream
672+-- sequence is executed and the result is supplied to the consumer. When the
673+-- next element is demanded, the action @b@ is executed and its result is
674+-- supplied. Thus, the effects are performed and results are consumed strictly
675+-- in a serial order. Serial streams can be considered as /spatially ordered/
676+-- streams as the order of execution and consumption is the same as the spatial
677+-- order in which the actions are composed by the programmer.
678+--
679+-- Serial streams enforce the side effects as well as the results of the
680+-- actions to be in the same order in which the actions are added to the
681+-- stream. Therefore, the semigroup operation for serial streams is not
682+-- commutative:
683+--
684+-- @
685+-- a <> b is not the same as b <> a
686+-- @
687+--
688+-- There are two serial stream types 'SerialT' and 'WSerialT'. The stream
689+-- evaluation of both the variants works in the same way as described above,
690+-- they differ only in the 'Semigroup' and 'Monad' implementaitons.
691+
692+-- $ahead
693+--
694+-- When a stream consumer demands an element from a speculative stream
695+-- constructed as @a \`consM` b \`consM` ... nil@, the action @a@ at the head
696+-- of the stream is executed and the output of the action is supplied to the
697+-- consumer. However, in addition to the action at the head multiple actions
698+-- following it may also be executed concurrently and the results buffered.
699+-- When the next element is demanded it may be served from the buffer and we
700+-- may execute the next action in the sequence to keep the buffer adequately
701+-- filled. Thus, the actions are executed concurrently but results consumed in
702+-- serial order just like serial streams. `consM` can be used to fold an
703+-- infinite lazy container of effects, as the number of concurrent executions
704+-- is limited.
705+--
706+-- Similar to 'consM', the monadic stream generation (e.g. replicateM) and
707+-- transformation operations (e.g. mapM) on speculative streams can execute
708+-- multiple effects concurrently in a speculative manner.
709+--
710+-- How many effects can be executed concurrently and how many results can be
711+-- buffered are controlled by 'maxThreads' and 'maxBuffer' combinators
712+-- respectively. The actual number of concurrent threads is adjusted according
713+-- to the rate at which the consumer is consuming the stream. It may even
714+-- execute actions serially in a single thread if that is enough to match the
715+-- consumer's speed.
716+--
717+-- Speculative streams enforce ordering of the results of actions in the stream
718+-- but the side effects are only partially ordered. Therefore, the semigroup
719+-- operation for speculative streams is not commutative from the pure outputs
720+-- perspective but commutative from side effects perspective.
721+
722+-- $async
723+--
724+-- /Scheduling and execution:/ In an asynchronous stream @a \`consM` b \`consM`
725+-- c ...@, the actions @a@, @b@, and @c@ are executed concurrently with the
726+-- consumer of the stream. The actions are /scheduled/ for execution in the
727+-- same order as they are specified in the stream. Multiple scheduled actions
728+-- may be /executed/ concurrently in parallel threads of execution. The
729+-- actions may be executed out of order and they may complete at arbitrary
730+-- times. Therefore, the /effects/ of the actions may be observed out of
731+-- order.
732+--
733+-- /Buffering:/ The /results/ from multiple threads of execution are queued in
734+-- a buffer as soon as they become available. The consumer of the stream is
735+-- served from this buffer. Therefore, the consumer may observe the results to
736+-- be out of order. In other words, an asynchronous stream is an unordered
737+-- stream i.e. order does not matter.
738+--
739+-- /Concurrency control:/ Threads are suspended if the `maxBuffer` limit is
740+-- reached, and resumed when the consumer makes space in the buffer. The
741+-- maximum number of concurrent threads depends on `maxThreads`. Number of
742+-- threads is increased or decreased based on the speed of the consumer.
743+--
744+-- /Generation operations:/ Concurrent stream generation operations e.g.
745+-- 'Streamly.Prelude.replicateM' when used in async style schedule and execute
746+-- the stream generating actions in the manner described above. The generation
747+-- actions run concurrently, effects and results of the actions as observed by
748+-- the consumer of the stream may be out of order.
749+--
750+-- /Transformation operations:/ Concurrent stream transformation operations
751+-- e.g. 'Streamly.Prelude.mapM', when used in async style, schedule and
752+-- execute transformation actions in the manner described above. Transformation
753+-- actions run concurrently, effects and results of the actions may be
754+-- observed by the consumer out of order.
755+--
756+-- /Variants:/ There are two asynchronous stream types 'AsyncT' and 'WAsyncT'.
757+-- They are identical with respect to single stream evaluation behavior. Their
758+-- behaviors differ in how they combine multiple streams using 'Semigroup' or
759+-- 'Monad' composition. Since the order of elements does not matter in
760+-- asynchronous streams the 'Semigroup' operation is effectively commutative.
761+
762+-- $zipping
763+--
764+-- 'ZipSerialM' and 'ZipAsyncM', provide 'Applicative' instances for zipping the
765+-- corresponding elements of two streams together. Note that these types are
766+-- not monads.
767+
574-- $rightfolds
768-- $rightfolds
575--
769--
576−-- Let's take a closer look at the @foldr@ definition for lists, as given
770+-- Let's take a closer look at the @foldr@ definition for lists, as given3
577-- earlier:
771-- earlier:
578--
772--
579-- @
773-- @
@@ -802,3 +996,67 @@ import Streamly.Internal.Data.Stream.IsStream
802-- @
996-- @
803-- [1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0,16.0,17.0,18.0,19.0]
997-- [1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0,16.0,17.0,18.0,19.0]
804-- @
998-- @
999+
1000+-- $application
1001+--
1002+-- Stream processing functions can be composed in a chain using function
1003+-- application with or without the '$' operator, or with reverse function
1004+-- application operator '&'. Streamly provides concurrent versions of these
1005+-- operators applying stream processing functions such that each stage of the
1006+-- stream can run in parallel. The operators start with a @|@; we can read '|$'
1007+-- as "@parallel dollar@" to remember that @|@ comes before '$'.
1008+--
1009+-- Imports for the code snippets below:
1010+--
1011+-- @
1012+-- import qualified Streamly.Prelude as S
1013+-- import Control.Concurrent
1014+-- @
1015+
1016+-- $concurrency
1017+--
1018+-- These combinators can be used at any point in a stream composition to set
1019+-- parameters to control the concurrency of the /argument stream/. A control
1020+-- parameter set at any point remains effective for any concurrent combinators
1021+-- used in the argument stream until it is reset by using the combinator again.
1022+-- These control parameters have no effect on non-concurrent combinators in the
1023+-- stream, or on non-concurrent streams.
1024+--
1025+-- /Pitfall:/ Remember that 'maxBuffer' in the following example applies to
1026+-- 'mapM' and any other combinators that may follow it, and it does not apply
1027+-- to the combinators before it:
1028+--
1029+-- @
1030+-- ...
1031+-- $ S.maxBuffer 10
1032+-- $ S.mapM ...
1033+-- ...
1034+-- @
1035+--
1036+-- If we use '&' instead of '$' the situation will reverse, in the following
1037+-- example, 'maxBuffer' does not apply to 'mapM', it applies to combinators
1038+-- that come before it, because those are the arguments to 'maxBuffer':
1039+--
1040+-- @
1041+-- ...
1042+-- & S.maxBuffer 10
1043+-- & S.mapM ...
1044+-- ...
1045+-- @
1046+
1047+-- $adapters
1048+--
1049+-- You may want to use different stream composition styles at different points
1050+-- in your program. Stream types can be freely converted or adapted from one
1051+-- type to another. The 'IsStream' type class facilitates type conversion of
1052+-- one stream type to another. It is not used directly, instead the type
1053+-- combinators provided below are used for conversions.
1054+--
1055+-- To adapt from one monomorphic type (e.g. 'AsyncT') to another monomorphic
1056+-- type (e.g. 'SerialT') use the 'adapt' combinator. To give a polymorphic code
1057+-- a specific interpretation or to adapt a specific type to a polymorphic type
1058+-- use the type specific combinators e.g. 'asyncly' or 'wSerially'. You
1059+-- cannot adapt polymorphic code to polymorphic code, as the compiler would not know
1060+-- which specific type you are converting from or to. If you see a an
1061+-- @ambiguous type variable@ error then most likely you are using 'adapt'
1062+-- unnecessarily on polymorphic code.
src/Streamly/Tutorial.hs+74−91
@@ -170,7 +170,6 @@ module Streamly.Tutorial
170 )
170 )
171where
171where
172
172
173−import Streamly hiding (foldWith, foldMapWith, forEachWith)
174import Streamly.Prelude
173import Streamly.Prelude
175import Data.Semigroup
174import Data.Semigroup
176import Control.Applicative
175import Control.Applicative
@@ -345,8 +344,7 @@ import Control.Monad.Trans.Class (MonadTrans (lift))
345-- GHCi session and import these lines to start playing.
344-- GHCi session and import these lines to start playing.
346--
345--
347-- @
346-- @
348−-- > import "Streamly"
347+-- > import "Streamly.Prelude" ((|:), (|&))
349−-- > import "Streamly.Prelude" ((|:))
350-- > import qualified "Streamly.Prelude" as S
348-- > import qualified "Streamly.Prelude" as S
351--
349--
352-- > import Control.Concurrent
350-- > import Control.Concurrent
@@ -412,15 +410,19 @@ import Control.Monad.Trans.Class (MonadTrans (lift))
412--
410--
413-- @
411-- @
414-- > let p n = threadDelay (n * 1000000) >> return n
412-- > let p n = threadDelay (n * 1000000) >> return n
413+-- > :set +s
415−-- > S.'toList' $ 'parallely' $ p 3 |: p 2 |: p 1 |: S.'nil'
414+-- > S.'toList' $ S.'parallely' $ p 3 |: p 2 |: p 1 |: S.'nil'
416-- [1,2,3]
415-- [1,2,3]
416+-- (3.01 secs, 2,018,432 bytes)
417−-- > S.'toList' $ 'aheadly' $ p 3 |: p 2 |: p 1 |: S.'nil'
417+-- > S.'toList' $ S.'aheadly' $ p 3 |: p 2 |: p 1 |: S.'nil'
418-- [3,2,1]
418-- [3,2,1]
419+-- (3.01 secs, 2,055,880 bytes)
419-- @
420-- @
420-- The following finishes in 10 seconds (100 seconds when serial):
421-- The following finishes in 10 seconds (100 seconds when serial):
421--
422--
422-- @
423-- @
423−-- > S.drain $ 'asyncly' $ S.'replicateM' 10 $ p 10
424+-- > S.'drain' $ S.'asyncly' $ S.'replicateM' 10 $ p 10
425+-- (10.01 secs, 2,080,320 bytes)
424-- @
426-- @
425--
427--
426
428
@@ -456,7 +458,6 @@ import Control.Monad.Trans.Class (MonadTrans (lift))
456-- numbers them and prints them:
458-- numbers them and prints them:
457--
459--
458-- @
460-- @
459−-- import "Streamly"
460-- import qualified "Streamly.Prelude" as S
461-- import qualified "Streamly.Prelude" as S
461-- import Data.Char (toUpper)
462-- import Data.Char (toUpper)
462-- import Data.Function ((&))
463-- import Data.Function ((&))
@@ -482,7 +483,7 @@ import Control.Monad.Trans.Class (MonadTrans (lift))
482--
483--
483-- @
484-- @
484-- > let p n = threadDelay (n * 1000000) >> return n
485-- > let p n = threadDelay (n * 1000000) >> return n
485−-- > S.'drain' $ S.aheadly $ S.'mapM' (\\x -> p 1 >> print x) (serially $ S.repeatM (p 1))
486+-- > S.'drain' $ S.'aheadly' $ S.'mapM' (\\x -> p 1 >> print x) (S.'serially' $ S.'repeatM' (p 1))
486-- @
487-- @
487--
488--
488
489
@@ -515,7 +516,6 @@ import Control.Monad.Trans.Class (MonadTrans (lift))
515-- not explicitly specified use the imports shown below.
516-- not explicitly specified use the imports shown below.
516--
517--
517-- @
518-- @
518−-- import "Streamly"
519-- import "Streamly.Prelude" ((|:), nil)
519-- import "Streamly.Prelude" ((|:), nil)
520-- import qualified "Streamly.Prelude" as S
520-- import qualified "Streamly.Prelude" as S
521--
521--
@@ -553,7 +553,7 @@ import Control.Monad.Trans.Class (MonadTrans (lift))
553-- 3, 4:
553-- 3, 4:
554--
554--
555-- @
555-- @
556−-- main = S.'drain' $ (print 1 |: print 2 |: nil) <> (print 3 |: print 4 |: nil)
556+-- main = S.'drain' $ (print 1 |: print 2 |: S.nil) <> (print 3 |: print 4 |: S.nil)
557-- @
557-- @
558-- @
558-- @
559-- 1
559-- 1
@@ -580,7 +580,7 @@ import Control.Monad.Trans.Class (MonadTrans (lift))
580-- irrespective of the type of stream:
580-- irrespective of the type of stream:
581--
581--
582-- @
582-- @
583−-- main = S.'drain' $ (print 1 |: print 2 |: nil) \`serial` (print 3 |: print 4 |: nil)
583+-- main = S.'drain' $ (print 1 |: print 2 |: S.nil) \`S.serial` (print 3 |: print 4 |: S.nil)
584-- @
584-- @
585
585
586-- $interleaved
586-- $interleaved
@@ -597,7 +597,7 @@ import Control.Monad.Trans.Class (MonadTrans (lift))
597-- The following example prints the sequence 1, 3, 2, 4
597-- The following example prints the sequence 1, 3, 2, 4
598--
598--
599-- @
599-- @
600−-- main = S.'drain' . 'wSerially' $ (print 1 |: print 2 |: nil) <> (print 3 |: print 4 |: nil)
600+-- main = S.'drain' . S.'wSerially' $ (print 1 |: print 2 |: S.'nil') <> (print 3 |: print 4 |: S.'nil')
601-- @
601-- @
602-- @
602-- @
603-- 1
603-- 1
@@ -612,7 +612,7 @@ import Control.Monad.Trans.Class (MonadTrans (lift))
612-- thread and take a combined total of @3 + 2 + 1 = 6@ seconds:
612-- thread and take a combined total of @3 + 2 + 1 = 6@ seconds:
613--
613--
614-- @
614-- @
615−-- main = S.'drain' . 'wSerially' $ delay 3 <> delay 2 <> delay 1
615+-- main = S.'drain' . S.'wSerially' $ delay 3 <> delay 2 <> delay 1
616-- @
616-- @
617-- @
617-- @
618-- ThreadId 36: Delay 3
618-- ThreadId 36: Delay 3
@@ -626,7 +626,7 @@ import Control.Monad.Trans.Class (MonadTrans (lift))
626-- combinator in the following example:
626-- combinator in the following example:
627--
627--
628-- @
628-- @
629−-- main = S.'drain' $ (print 1 |: print 2 |: nil) \`wSerial` (print 3 |: print 4 |: nil)
629+-- main = S.'drain' $ (print 1 |: print 2 |: S.'nil') \`S.wSerial` (print 3 |: print 4 |: S.'nil')
630-- @
630-- @
631-- @
631-- @
632-- 1
632-- 1
@@ -656,7 +656,7 @@ import Control.Monad.Trans.Class (MonadTrans (lift))
656--
656--
657-- @
657-- @
658-- main = do
658-- main = do
659−-- xs \<- S.'toList' . 'aheadly' $ (p 1 |: p 2 |: nil) <> (p 3 |: p 4 |: nil)
659+-- xs \<- S.'toList' . S.'aheadly' $ (p 1 |: p 2 |: S.nil) <> (p 3 |: p 4 |: S.nil)
660-- print xs
660-- print xs
661-- where p n = threadDelay 1000000 >> return n
661-- where p n = threadDelay 1000000 >> return n
662-- @
662-- @
@@ -693,7 +693,7 @@ import Control.Monad.Trans.Class (MonadTrans (lift))
693--
693--
694-- @
694-- @
695-- main = do
695-- main = do
696−-- xs \<- S.'toList' . 'asyncly' $ (p 1 |: p 2 |: nil) <> (p 3 |: p 4 |: nil)
696+-- xs \<- S.'toList' . S.'asyncly' $ (p 1 |: p 2 |: S.'nil') <> (p 3 |: p 4 |: S.'nil')
697-- print xs
697-- print xs
698-- where p n = threadDelay 1000000 >> return n
698-- where p n = threadDelay 1000000 >> return n
699-- @
699-- @
@@ -708,7 +708,7 @@ import Control.Monad.Trans.Class (MonadTrans (lift))
708--
708--
709-- @
709-- @
710-- main = do
710-- main = do
711−-- xs \<- S.'toList' . 'asyncly' $ (serially $ p 1 |: p 2 |: nil) <> (serially $ p 3 |: p 4 |: nil)
711+-- xs \<- S.'toList' . S.'asyncly' $ (S.'serially' $ p 1 |: p 2 |: S.'nil') <> (serially $ p 3 |: p 4 |: S.'nil')
712-- print xs
712-- print xs
713-- where p n = threadDelay 1000000 >> return n
713-- where p n = threadDelay 1000000 >> return n
714-- @
714-- @
@@ -722,7 +722,7 @@ import Control.Monad.Trans.Class (MonadTrans (lift))
722-- (3, 2, 1) = 3@ seconds:
722-- (3, 2, 1) = 3@ seconds:
723--
723--
724-- @
724-- @
725−-- main = S.'drain' . 'asyncly' $ delay 3 '<>' delay 2 '<>' delay 1
725+-- main = S.'drain' . S.'asyncly' $ delay 3 '<>' delay 2 '<>' delay 1
726-- @
726-- @
727-- @
727-- @
728-- ThreadId 42: Delay 1
728-- ThreadId 42: Delay 1
@@ -741,7 +741,7 @@ import Control.Monad.Trans.Class (MonadTrans (lift))
741-- second as all of the actions are concurrent.
741-- second as all of the actions are concurrent.
742--
742--
743-- @
743-- @
744−-- main = S.'drain' . 'asyncly' $ (delay 1 <> delay 2) <> (delay 3 <> delay 4)
744+-- main = S.'drain' . S.'asyncly' $ (delay 1 <> delay 2) <> (delay 3 <> delay 4)
745-- @
745-- @
746-- @
746-- @
747-- 1
747-- 1
@@ -758,7 +758,7 @@ import Control.Monad.Trans.Class (MonadTrans (lift))
758-- even if none of them blocks:
758-- even if none of them blocks:
759--
759--
760-- @
760-- @
761−-- main = S.'drain' . 'asyncly' $ traced (sqrt 9) '<>' traced (sqrt 16) '<>' traced (sqrt 25)
761+-- main = S.'drain' . S.'asyncly' $ traced (sqrt 9) '<>' traced (sqrt 16) '<>' traced (sqrt 25)
762-- where traced m = S.'yieldM' (myThreadId >>= print) >> return m
762-- where traced m = S.'yieldM' (myThreadId >>= print) >> return m
763-- @
763-- @
764-- @
764-- @
@@ -776,7 +776,7 @@ import Control.Monad.Trans.Class (MonadTrans (lift))
776-- not used the 'asyncly' combinator in the following example:
776-- not used the 'asyncly' combinator in the following example:
777--
777--
778-- @
778-- @
779−-- main = S.'drain' $ delay 3 \`async` delay 2 \`async` delay 1
779+-- main = S.'drain' $ delay 3 \`S.'async'` delay 2 \`S.'async'` delay 1
780-- @
780-- @
781-- @
781-- @
782-- ThreadId 42: Delay 1
782-- ThreadId 42: Delay 1
@@ -819,7 +819,7 @@ import Control.Monad.Trans.Class (MonadTrans (lift))
819-- first traversal order but this is not guaranteed.
819-- first traversal order but this is not guaranteed.
820--
820--
821-- @
821-- @
822−-- main = S.'drain' . 'wAsyncly' $ (serially $ print 1 |: print 2 |: nil) <> (serially $ print 3 |: print 4 |: nil)
822+-- main = S.'drain' . S.'wAsyncly' $ (S.'serially' $ print 1 |: print 2 |: S.'nil') <> (S.'serially' $ print 3 |: print 4 |: S.'nil')
823-- @
823-- @
824-- @
824-- @
825-- 1
825-- 1
@@ -834,7 +834,7 @@ import Control.Monad.Trans.Class (MonadTrans (lift))
834-- the 'wAsyncly' combinator in the following example:
834-- the 'wAsyncly' combinator in the following example:
835--
835--
836-- @
836-- @
837−-- main = S.'drain' $ delay 3 \`wAsync` delay 2 \`wAsync` delay 1
837+-- main = S.'drain' $ delay 3 \S.`wAsync` delay 2 \S.`wAsync` delay 1
838-- @
838-- @
839-- @
839-- @
840-- ThreadId 42: Delay 1
840-- ThreadId 42: Delay 1
@@ -873,11 +873,10 @@ import Control.Monad.Trans.Class (MonadTrans (lift))
873-- package to run this example:
873-- package to run this example:
874--
874--
875-- @
875-- @
876−-- import "Streamly"
877-- import qualified Streamly.Prelude as S
876-- import qualified Streamly.Prelude as S
878-- import Network.HTTP.Simple
877-- import Network.HTTP.Simple
879--
878--
880−-- main = S.'drain' . 'parallely' $ google \<> bing \<> duckduckgo
879+-- main = S.'drain' . S.'parallely' $ google \<> bing \<> duckduckgo
881-- where
880-- where
882-- google = get "https://www.google.com/search?q=haskell"
881-- google = get "https://www.google.com/search?q=haskell"
883-- bing = get "https://www.bing.com/search?q=haskell"
882-- bing = get "https://www.bing.com/search?q=haskell"
@@ -891,7 +890,7 @@ import Control.Monad.Trans.Class (MonadTrans (lift))
891-- 'parallely' combinator in the following example:
890-- 'parallely' combinator in the following example:
892--
891--
893-- @
892-- @
894−-- main = S.'drain' $ delay 3 \`parallel` delay 2 \`wAsync` delay 1
893+-- main = S.'drain' $ delay 3 \`S.'parallel'` delay 2 \`S.'wAsync'` delay 1
895-- @
894-- @
896-- @
895-- @
897-- ThreadId 42: Delay 1
896-- ThreadId 42: Delay 1
@@ -921,27 +920,26 @@ import Control.Monad.Trans.Class (MonadTrans (lift))
921-- style using 'fold' or 'foldMap'. We have also provided some fold utilities
920-- style using 'fold' or 'foldMap'. We have also provided some fold utilities
922-- to fold streams using the polymorphic combine operations:
921-- to fold streams using the polymorphic combine operations:
923--
922--
924−-- * 'foldWith' is like 'fold', it folds a 'Foldable' container of streams
923+-- * 'concatFoldableWith' is like 'fold', it folds a 'Foldable' container of
925−-- using the given composition operator.
924+-- streams using the given composition operator.
926−-- * 'foldMapWith' is like 'foldMap', it folds like @foldWith@ but also maps a
925+-- * 'concatMapFoldableWith' is like 'foldMap', it folds like
927−-- function before folding.
926+-- @concatFoldableWith@ but also maps a function before folding.
928−-- * 'forEachWith' is like @foldMapwith@ but the container argument comes before
927+-- * 'concatForFoldableWith' is like @concatMapFoldableWith@ but the container
929−-- the function argument.
928+-- argument comes before the function argument.
930--
929--
931-- All of the following are equivalent and start ten concurrent tasks each with
930-- All of the following are equivalent and start ten concurrent tasks each with
932-- a delay from 1 to 10 seconds, resulting in the printing of each number every
931-- a delay from 1 to 10 seconds, resulting in the printing of each number every
933-- second:
932-- second:
934--
933--
935-- @
934-- @
936−-- import "Streamly"
937-- import qualified "Streamly.Prelude" as S
935-- import qualified "Streamly.Prelude" as S
938-- import Control.Concurrent
936-- import Control.Concurrent
939--
937--
940-- main = do
938-- main = do
941−-- S.'drain' $ 'asyncly' $ foldMap delay [1..10]
939+-- S.'drain' $ S.'asyncly' $ foldMap delay [1..10]
942−-- S.'drain' $ S.'foldWith' 'async' (map delay [1..10])
940+-- S.'drain' $ S.'concatFoldableWith' S.'async' (map delay [1..10])
943−-- S.'drain' $ S.'foldMapWith' 'async' delay [1..10]
941+-- S.'drain' $ S.'concatMapFoldableWith' S.'async' delay [1..10]
944−-- S.'drain' $ S.'forEachWith' 'async' [1..10] delay
942+-- S.'drain' $ S.'concatForFoldableWith' S.'async' [1..10] delay
945-- where delay n = S.'yieldM' $ threadDelay (n * 1000000) >> print n
943-- where delay n = S.'yieldM' $ threadDelay (n * 1000000) >> print n
946-- @
944-- @
947
945
@@ -987,7 +985,6 @@ import Control.Monad.Trans.Class (MonadTrans (lift))
987-- instead.
985-- instead.
988--
986--
989-- @
987-- @
990−-- import "Streamly"
991-- import qualified "Streamly.Prelude" as S
988-- import qualified "Streamly.Prelude" as S
992--
989--
993-- main = S.'drain' $ do
990-- main = S.'drain' $ do
@@ -1009,12 +1006,11 @@ import Control.Monad.Trans.Class (MonadTrans (lift))
1009-- written like this:
1006-- written like this:
1010--
1007--
1011-- @
1008-- @
1012−-- import "Streamly"
1013-- import qualified "Streamly.Prelude" as S
1009-- import qualified "Streamly.Prelude" as S
1014--
1010--
1015-- import Control.Monad (forever)
1011-- import Control.Monad (forever)
1016--
1012--
1017−-- main = S.'drain' $ forever $ S.yieldM getLine >>= S.yieldM . putStrLn
1013+-- main = S.'drain' $ forever $ S.'yieldM' getLine >>= S.'yieldM' . putStrLn
1018-- @
1014-- @
1019--
1015--
1020-- When multiple streams are composed using this style they nest in a DFS
1016-- When multiple streams are composed using this style they nest in a DFS
@@ -1023,7 +1019,6 @@ import Control.Monad.Trans.Class (MonadTrans (lift))
1023-- loops in imperative programming.
1019-- loops in imperative programming.
1024--
1020--
1025-- @
1021-- @
1026−-- import "Streamly"
1027-- import qualified "Streamly.Prelude" as S
1022-- import qualified "Streamly.Prelude" as S
1028--
1023--
1029-- main = S.'drain' $ do
1024-- main = S.'drain' $ do
@@ -1052,10 +1047,9 @@ import Control.Monad.Trans.Class (MonadTrans (lift))
1052-- type of the stream as 'Ahead'.
1047-- type of the stream as 'Ahead'.
1053--
1048--
1054-- @
1049-- @
1055−-- import "Streamly"
1056-- import qualified "Streamly.Prelude" as S
1050-- import qualified "Streamly.Prelude" as S
1057--
1051--
1058−-- comp = S.'toList' . 'aheadly' $ do
1052+-- comp = S.'toList' . S.'aheadly' $ do
1059-- x <- S.'fromFoldable' [3,2,1]
1053-- x <- S.'fromFoldable' [3,2,1]
1060-- delay x >> return x
1054-- delay x >> return x
1061--
1055--
@@ -1093,10 +1087,9 @@ import Control.Monad.Trans.Class (MonadTrans (lift))
1093-- type of the stream as 'Async'.
1087-- type of the stream as 'Async'.
1094--
1088--
1095-- @
1089-- @
1096−-- import "Streamly"
1097-- import qualified "Streamly.Prelude" as S
1090-- import qualified "Streamly.Prelude" as S
1098--
1091--
1099−-- main = S.'drain' . 'asyncly' $ do
1092+-- main = S.'drain' . S.'asyncly' $ do
1100-- x <- S.'fromFoldable' [3,2,1]
1093-- x <- S.'fromFoldable' [3,2,1]
1101-- delay x
1094-- delay x
1102-- @
1095-- @
@@ -1120,10 +1113,9 @@ import Control.Monad.Trans.Class (MonadTrans (lift))
1120-- on the demand from the consumer of the stream.
1113-- on the demand from the consumer of the stream.
1121--
1114--
1122-- @
1115-- @
1123−-- import "Streamly"
1124-- import qualified "Streamly.Prelude" as S
1116-- import qualified "Streamly.Prelude" as S
1125--
1117--
1126−-- main = S.'drain' . 'asyncly' $ do
1118+-- main = S.'drain' . S.'asyncly' $ do
1127-- x <- S.'fromFoldable' [1,2]
1119-- x <- S.'fromFoldable' [1,2]
1128-- y <- S.'fromFoldable' [3,4]
1120-- y <- S.'fromFoldable' [3,4]
1129-- S.'yieldM' $ putStrLn $ show (x, y)
1121-- S.'yieldM' $ putStrLn $ show (x, y)
@@ -1145,10 +1137,9 @@ import Control.Monad.Trans.Class (MonadTrans (lift))
1145-- type of the stream as 'WSerial'.
1137-- type of the stream as 'WSerial'.
1146--
1138--
1147-- @
1139-- @
1148−-- import "Streamly"
1149-- import qualified "Streamly.Prelude" as S
1140-- import qualified "Streamly.Prelude" as S
1150--
1141--
1151−-- main = S.'drain' . 'wSerially' $ do
1142+-- main = S.'drain' . S.'wSerially' $ do
1152-- x <- S.'fromFoldable' [1,2]
1143-- x <- S.'fromFoldable' [1,2]
1153-- y <- S.'fromFoldable' [3,4]
1144-- y <- S.'fromFoldable' [3,4]
1154-- S.yieldM $ putStrLn $ show (x, y)
1145-- S.yieldM $ putStrLn $ show (x, y)
@@ -1173,10 +1164,9 @@ import Control.Monad.Trans.Class (MonadTrans (lift))
1173-- specify the type of the stream as 'WAsync'.
1164-- specify the type of the stream as 'WAsync'.
1174--
1165--
1175-- @
1166-- @
1176−-- import "Streamly"
1177-- import qualified "Streamly.Prelude" as S
1167-- import qualified "Streamly.Prelude" as S
1178--
1168--
1179−-- main = S.'drain' . 'wAsyncly' $ do
1169+-- main = S.'drain' . S.'wAsyncly' $ do
1180-- x <- S.'fromFoldable' [1,2]
1170-- x <- S.'fromFoldable' [1,2]
1181-- y <- S.'fromFoldable' [3,4]
1171-- y <- S.'fromFoldable' [3,4]
1182-- S.'yieldM' $ putStrLn $ show (x, y)
1172-- S.'yieldM' $ putStrLn $ show (x, y)
@@ -1199,10 +1189,9 @@ import Control.Monad.Trans.Class (MonadTrans (lift))
1199-- annotation can be used to specify the type of the stream as 'Parallel'.
1189-- annotation can be used to specify the type of the stream as 'Parallel'.
1200--
1190--
1201-- @
1191-- @
1202−-- import "Streamly"
1203-- import qualified "Streamly.Prelude" as S
1192-- import qualified "Streamly.Prelude" as S
1204--
1193--
1205−-- main = S.'drain' . 'parallely' $ do
1194+-- main = S.'drain' . S.'parallely' $ do
1206-- x <- S.'fromFoldable' [3,2,1]
1195-- x <- S.'fromFoldable' [3,2,1]
1207-- delay x
1196-- delay x
1208-- @
1197-- @
@@ -1220,10 +1209,9 @@ import Control.Monad.Trans.Class (MonadTrans (lift))
1220-- specific mode of composition. For example take a look at the following code.
1209-- specific mode of composition. For example take a look at the following code.
1221--
1210--
1222-- @
1211-- @
1223−-- import "Streamly"
1224-- import qualified "Streamly.Prelude" as S
1212-- import qualified "Streamly.Prelude" as S
1225--
1213--
1226−-- composed :: (IsStream t, Monad (t IO)) => t IO ()
1214+-- composed :: (S.IsStream t, Monad (t IO)) => t IO ()
1227-- composed = do
1215-- composed = do
1228-- sz <- sizes
1216-- sz <- sizes
1229-- cl <- colors
1217-- cl <- colors
@@ -1240,11 +1228,11 @@ import Control.Monad.Trans.Class (MonadTrans (lift))
1240-- Now we can interpret this in whatever way we want:
1228-- Now we can interpret this in whatever way we want:
1241--
1229--
1242-- @
1230-- @
1243−-- main = S.'drain' . 'serially' $ composed
1231+-- main = S.'drain' . S.'serially' $ composed
1244−-- main = S.'drain' . 'wSerially' $ composed
1232+-- main = S.'drain' . S.'wSerially' $ composed
1245−-- main = S.'drain' . 'asyncly' $ composed
1233+-- main = S.'drain' . S.'asyncly' $ composed
1246−-- main = S.'drain' . 'wAsyncly' $ composed
1234+-- main = S.'drain' . S.'wAsyncly' $ composed
1247−-- main = S.'drain' . 'parallely' $ composed
1235+-- main = S.'drain' . S.'parallely' $ composed
1248-- @
1236-- @
1249--
1237--
1250-- As an exercise try to figure out the output of this code for each mode of
1238-- As an exercise try to figure out the output of this code for each mode of
@@ -1257,7 +1245,6 @@ import Control.Monad.Trans.Class (MonadTrans (lift))
1257-- serial.
1245-- serial.
1258--
1246--
1259-- @
1247-- @
1260−-- import "Streamly"
1261-- import qualified "Streamly.Prelude" as S
1248-- import qualified "Streamly.Prelude" as S
1262--
1249--
1263-- main = (S.'toList' $ fmap show $ S.'fromFoldable' [1..10]) >>= print
1250-- main = (S.'toList' $ fmap show $ S.'fromFoldable' [1..10]) >>= print
@@ -1276,7 +1263,6 @@ import Control.Monad.Trans.Class (MonadTrans (lift))
1276-- serially and takes a total 17 seconds (1 + 3 + 4 + 2 + 3 + 4):
1263-- serially and takes a total 17 seconds (1 + 3 + 4 + 2 + 3 + 4):
1277--
1264--
1278-- @
1265-- @
1279−-- import "Streamly"
1280-- import qualified "Streamly.Prelude" as S
1266-- import qualified "Streamly.Prelude" as S
1281-- import Control.Concurrent
1267-- import Control.Concurrent
1282--
1268--
@@ -1284,7 +1270,7 @@ import Control.Monad.Trans.Class (MonadTrans (lift))
1284-- s2 = d 3 <> d 4
1270-- s2 = d 3 <> d 4
1285-- d n = delay n >> return n
1271-- d n = delay n >> return n
1286--
1272--
1287−-- main = (S.'toList' . 'serially' $ (,) \<$> s1 \<*> s2) >>= print
1273+-- main = (S.'toList' . S.'serially' $ (,) \<$> s1 \<*> s2) >>= print
1288-- @
1274-- @
1289-- @
1275-- @
1290-- ThreadId 36: Delay 1
1276-- ThreadId 36: Delay 1
@@ -1300,7 +1286,7 @@ import Control.Monad.Trans.Class (MonadTrans (lift))
1300-- order but since it is serial it takes a total of 17 seconds:
1286-- order but since it is serial it takes a total of 17 seconds:
1301--
1287--
1302-- @
1288-- @
1303−-- main = (S.'toList' . 'wSerially' $ (,) \<$> s1 \<*> s2) >>= print
1289+-- main = (S.'toList' . S.'wSerially' $ (,) \<$> s1 \<*> s2) >>= print
1304-- @
1290-- @
1305-- @
1291-- @
1306-- ThreadId 36: Delay 1
1292-- ThreadId 36: Delay 1
@@ -1316,7 +1302,7 @@ import Control.Monad.Trans.Class (MonadTrans (lift))
1316-- of 6 seconds which is max (1, 2) + max (3, 4):
1302-- of 6 seconds which is max (1, 2) + max (3, 4):
1317--
1303--
1318-- @
1304-- @
1319−-- main = (S.'toList' . 'asyncly' $ (,) \<$> s1 \<*> s2) >>= print
1305+-- main = (S.'toList' . S.'asyncly' $ (,) \<$> s1 \<*> s2) >>= print
1320-- @
1306-- @
1321-- @
1307-- @
1322-- ThreadId 34: Delay 1
1308-- ThreadId 34: Delay 1
@@ -1332,7 +1318,7 @@ import Control.Monad.Trans.Class (MonadTrans (lift))
1332-- therefore takes a total of 6 seconds (2 + 4):
1318-- therefore takes a total of 6 seconds (2 + 4):
1333--
1319--
1334-- @
1320-- @
1335−-- main = (S.'toList' . 'wAsyncly' $ (,) \<$> s1 \<*> s2) >>= print
1321+-- main = (S.'toList' . S.'wAsyncly' $ (,) \<$> s1 \<*> s2) >>= print
1336-- @
1322-- @
1337-- @
1323-- @
1338-- ThreadId 34: Delay 1
1324-- ThreadId 34: Delay 1
@@ -1360,15 +1346,14 @@ import Control.Monad.Trans.Class (MonadTrans (lift))
1360-- zip composition:
1346-- zip composition:
1361--
1347--
1362-- @
1348-- @
1363−-- import "Streamly"
1364-- import qualified "Streamly.Prelude" as S
1349-- import qualified "Streamly.Prelude" as S
1365-- import Control.Concurrent
1350-- import Control.Concurrent
1366--
1351--
1367-- d n = delay n >> return n
1352-- d n = delay n >> return n
1368−-- s1 = 'serially' $ d 1 <> d 2
1353+-- s1 = S.'serially' $ d 1 <> d 2
1369−-- s2 = 'serially' $ d 3 <> d 4
1354+-- s2 = S.'serially' $ d 3 <> d 4
1370--
1355--
1371−-- main = (S.'toList' . 'zipSerially' $ (,) \<$> s1 \<*> s2) >>= print
1356+-- main = (S.'toList' . S.'zipSerially' $ (,) \<$> s1 \<*> s2) >>= print
1372-- @
1357-- @
1373--
1358--
1374-- This takes total 10 seconds to zip, which is (1 + 2 + 3 + 4) since
1359-- This takes total 10 seconds to zip, which is (1 + 2 + 3 + 4) since
@@ -1390,18 +1375,17 @@ import Control.Monad.Trans.Class (MonadTrans (lift))
1390--
1375--
1391--
1376--
1392-- @
1377-- @
1393−-- import "Streamly"
1394-- import qualified "Streamly.Prelude" as S
1378-- import qualified "Streamly.Prelude" as S
1395-- import Control.Concurrent
1379-- import Control.Concurrent
1396-- import System.IO (stdout, hSetBuffering, BufferMode(LineBuffering))
1380-- import System.IO (stdout, hSetBuffering, BufferMode(LineBuffering))
1397--
1381--
1398-- d n = delay n >> return n
1382-- d n = delay n >> return n
1399−-- s1 = 'serially' $ d 1 <> d 2
1383+-- s1 = S.'serially' $ d 1 <> d 2
1400−-- s2 = 'serially' $ d 3 <> d 4
1384+-- s2 = S.'serially' $ d 3 <> d 4
1401--
1385--
1402-- main = do
1386-- main = do
1403-- hSetBuffering stdout LineBuffering
1387-- hSetBuffering stdout LineBuffering
1404−-- (S.'toList' . 'zipAsyncly' $ (,) \<$> s1 \<*> s2) >>= print
1388+-- (S.'toList' . S.'zipAsyncly' $ (,) \<$> s1 \<*> s2) >>= print
1405-- @
1389-- @
1406--
1390--
1407-- This takes 7 seconds to zip, which is max (1,3) + max (2,4) because 1 and 3
1391-- This takes 7 seconds to zip, which is max (1,3) + max (2,4) because 1 and 3
@@ -1432,17 +1416,16 @@ import Control.Monad.Trans.Class (MonadTrans (lift))
1432-- combinator instead of explicitly folding with 'async'.
1416-- combinator instead of explicitly folding with 'async'.
1433--
1417--
1434-- @
1418-- @
1435−-- import "Streamly"
1436-- import qualified "Streamly.Prelude" as S
1419-- import qualified "Streamly.Prelude" as S
1437-- import Data.List (sum)
1420-- import Data.List (sum)
1438--
1421--
1439-- main = do
1422-- main = do
1440-- z \<- S.'toList'
1423-- z \<- S.'toList'
1441−-- $ 'serially' -- Serial monadic processing (sqrt below)
1424+-- $ S.'serially' -- Serial monadic processing (sqrt below)
1442-- $ do
1425-- $ do
1443−-- x2 \<- 'forEachWith' 'async' [1..100] $ -- Concurrent @"for"@ loop
1426+-- x2 \<- S.'concatForFoldableWith' S.'async' [1..100] $ -- Concurrent @"for"@ loop
1444-- \\x -> return $ x * x -- body of the loop
1427-- \\x -> return $ x * x -- body of the loop
1445−-- y2 \<- 'forEachWith' 'async' [1..100] $
1428+-- y2 \<- S.'concatForFoldableWith' S.'async' [1..100] $
1446-- \\y -> return $ y * y
1429-- \\y -> return $ y * y
1447-- return $ sqrt (x2 + y2)
1430-- return $ sqrt (x2 + y2)
1448-- print $ sum z
1431-- print $ sum z
@@ -1477,11 +1460,11 @@ import Control.Monad.Trans.Class (MonadTrans (lift))
1477-- @
1460-- @
1478-- {-\# LANGUAGE FlexibleContexts #-}
1461-- {-\# LANGUAGE FlexibleContexts #-}
1479--
1462--
1480−-- import "Streamly"
1463+-- import "Streamly.Prelude" (MonadAsync, SerialT)
1481-- import "Streamly.Prelude" as S
1464-- import "Streamly.Prelude" as S
1482−-- import Control.Monad (void, when)
1465+-- import Control.Monad (void)
1483-- import Control.Monad.IO.Class (MonadIO(liftIO))
1466-- import Control.Monad.IO.Class (MonadIO(liftIO))
1484−-- import Control.Monad.State (MonadState, get, modify, runStateT, put)
1467+-- import Control.Monad.State (MonadState, get, modify, runStateT)
1485--
1468--
1486-- data Event = Quit | Harm Int | Heal Int deriving (Show)
1469-- data Event = Quit | Harm Int | Heal Int deriving (Show)
1487--
1470--
@@ -1497,13 +1480,13 @@ import Control.Monad.Trans.Class (MonadTrans (lift))
1497-- _ -> putStrLn "Type potion or harm or quit" >> askUser
1480-- _ -> putStrLn "Type potion or harm or quit" >> askUser
1498--
1481--
1499-- acidRain :: MonadAsync m => 'SerialT' m Event
1482-- acidRain :: MonadAsync m => 'SerialT' m Event
1500−-- acidRain = 'asyncly' $ 'constRate' 1 $ S.'repeatM' $ liftIO $ return $ Harm 1
1483+-- acidRain = S.'asyncly' $ S.'constRate' 1 $ S.'repeatM' $ liftIO $ return $ Harm 1
1501--
1484--
1502-- data Result = Check | Done
1485-- data Result = Check | Done
1503--
1486--
1504-- runEvents :: (MonadAsync m, MonadState Int m) => 'SerialT' m Result
1487-- runEvents :: (MonadAsync m, MonadState Int m) => 'SerialT' m Result
1505-- runEvents = do
1488-- runEvents = do
1506−-- event \<- userAction \`parallel` acidRain
1489+-- event \<- userAction \`S.'parallel'` acidRain
1507-- case event of
1490-- case event of
1508-- Harm n -> modify (\\h -> h - n) >> return Check
1491-- Harm n -> modify (\\h -> h - n) >> return Check
1509-- Heal n -> modify (\\h -> h + n) >> return Check
1492-- Heal n -> modify (\\h -> h + n) >> return Check
@@ -1556,12 +1539,12 @@ import Control.Monad.Trans.Class (MonadTrans (lift))
1556-- Interop with @vector@:
1539-- Interop with @vector@:
1557--
1540--
1558-- @
1541-- @
1559−-- import Streamly
1542+-- import "Streamly.Prelude" (SerialT)
1560−-- import qualified Streamly.Prelude as S
1543+-- import qualified "Streamly.Prelude" as S
1561-- import qualified Data.Vector.Fusion.Stream.Monadic as V
1544-- import qualified Data.Vector.Fusion.Stream.Monadic as V
1562--
1545--
1563-- -- | vector to streamly
1546-- -- | vector to streamly
1564−-- fromVector :: (IsStream t, Monad m) => V.Stream m a -> t m a
1547+-- fromVector :: (S.IsStream t, Monad m) => V.Stream m a -> t m a
1565-- fromVector = S.unfoldrM unconsV
1548-- fromVector = S.unfoldrM unconsV
1566-- where
1549-- where
1567-- unconsV v = do
1550-- unconsV v = do
@@ -1574,7 +1557,7 @@ import Control.Monad.Trans.Class (MonadTrans (lift))
1574--
1557--
1575-- -- | streamly to vector
1558-- -- | streamly to vector
1576-- toVector :: Monad m => SerialT m a -> V.Stream m a
1559-- toVector :: Monad m => SerialT m a -> V.Stream m a
1577−-- toVector = V.unfoldrM (S.uncons . adapt)
1560+-- toVector = V.unfoldrM (S.uncons . S.adapt)
1578--
1561--
1579-- main = do
1562-- main = do
1580-- S.toList (fromVector (V.fromList [1..3])) >>= print
1563-- S.toList (fromVector (V.fromList [1..3])) >>= print
@@ -1584,13 +1567,13 @@ import Control.Monad.Trans.Class (MonadTrans (lift))
1584-- Interop with @pipes@:
1567-- Interop with @pipes@:
1585--
1568--
1586-- @
1569-- @
1587−-- import "Streamly"
1570+-- import "Streamly.Prelude" (SerialT)
1588-- import qualified "Streamly.Prelude" as S
1571-- import qualified "Streamly.Prelude" as S
1589-- import qualified Pipes as P
1572-- import qualified Pipes as P
1590-- import qualified Pipes.Prelude as P
1573-- import qualified Pipes.Prelude as P
1591--
1574--
1592-- -- | pipes to streamly
1575-- -- | pipes to streamly
1593−-- fromPipes :: (IsStream t, Monad m) => P.Producer a m r -> t m a
1576+-- fromPipes :: (S.IsStream t, Monad m) => P.Producer a m r -> t m a
1594-- fromPipes = S.'unfoldrM' unconsP
1577-- fromPipes = S.'unfoldrM' unconsP
1595-- where
1578-- where
1596-- -- Adapt P.next to return a Maybe instead of Either
1579-- -- Adapt P.next to return a Maybe instead of Either
@@ -1611,7 +1594,7 @@ import Control.Monad.Trans.Class (MonadTrans (lift))
1611-- Interop with @streaming@:
1594-- Interop with @streaming@:
1612--
1595--
1613-- @
1596-- @
1614−-- import "Streamly"
1597+-- import "Streamly.Prelude" (SerialT, MonadAsync)
1615-- import qualified "Streamly.Prelude" as S
1598-- import qualified "Streamly.Prelude" as S
1616-- import qualified Streaming as SG
1599-- import qualified Streaming as SG
1617-- import qualified Streaming.Prelude as SG
1600-- import qualified Streaming.Prelude as SG
@@ -1635,7 +1618,7 @@ import Control.Monad.Trans.Class (MonadTrans (lift))
1635-- Interop with @conduit@:
1618-- Interop with @conduit@:
1636--
1619--
1637-- @
1620-- @
1638−-- import "Streamly"
1621+-- import "Streamly.Prelude" (SerialT)
1639-- import qualified "Streamly.Prelude" as S
1622-- import qualified "Streamly.Prelude" as S
1640-- import qualified Data.Conduit as C
1623-- import qualified Data.Conduit as C
1641-- import qualified Data.Conduit.List as C
1624-- import qualified Data.Conduit.List as C
test/Main.hs+38−34
@@ -13,14 +13,18 @@ import Data.Foldable (forM_, fold)
13import Data.Function ((&))
13import Data.Function ((&))
14import Data.List (sort)
14import Data.List (sort)
15import Data.Maybe (fromJust, isJust)
15import Data.Maybe (fromJust, isJust)
16+#if !(MIN_VERSION_base(4,11,0))
17+import Data.Semigroup (Semigroup(..))
18+#endif
16import System.Mem (performMajorGC)
19import System.Mem (performMajorGC)
17
20
18import Data.IORef
21import Data.IORef
19import Test.Hspec as H
22import Test.Hspec as H
20
23
21−import Streamly
24+import Streamly.Prelude
22−import Streamly.Prelude ((.:), nil)
25+ ( AsyncT, SerialT, WSerialT, MonadAsync, IsStream, (.:), nil, adapt
23−import qualified Streamly as S
26+ , ahead, async, aheadly, asyncly, serially, parallely, wAsync, wAsyncly
27+ , wSerially, maxBuffer)
24import qualified Streamly.Prelude as S
28import qualified Streamly.Prelude as S
25import qualified Streamly.Internal.Data.Stream.IsStream as IP
29import qualified Streamly.Internal.Data.Stream.IsStream as IP
26
30
@@ -478,7 +482,7 @@ parallelTests = H.parallel $ do
478 it "wAsync maintains independent states in concurrent tasks"
482 it "wAsync maintains independent states in concurrent tasks"
479 (monadicStateSnapshotOp wAsync)
483 (monadicStateSnapshotOp wAsync)
480 it "parallel maintains independent states in concurrent tasks"
484 it "parallel maintains independent states in concurrent tasks"
481− (monadicStateSnapshotOp Streamly.parallel)
485+ (monadicStateSnapshotOp S.parallel)
482
486
483 ---------------------------------------------------------------------------
487 ---------------------------------------------------------------------------
484 -- Slower tests are at the end
488 -- Slower tests are at the end
@@ -757,8 +761,8 @@ composeWithMonadThrow t = do
757
761
758 oneLevelNestedProduct desc t1 =
762 oneLevelNestedProduct desc t1 =
759 it ("One level nested product" <> desc) $ do
763 it ("One level nested product" <> desc) $ do
760− let s1 = t $ S.foldMapWith (<>) return [1..4]
764+ let s1 = t $ S.concatMapFoldableWith (<>) return [1..4]
761− s2 = t1 $ S.foldMapWith (<>) return [5..8]
765+ s2 = t1 $ S.concatMapFoldableWith (<>) return [5..8]
762 try $ tl (do
766 try $ tl (do
763 x <- adapt s1
767 x <- adapt s1
764 y <- s2
768 y <- s2
@@ -783,8 +787,8 @@ _composeWithMonadError t = do
783
787
784nestTwoSerial :: Expectation
788nestTwoSerial :: Expectation
785nestTwoSerial =
789nestTwoSerial =
786− let s1 = S.foldMapWith (<>) return [1..4]
790+ let s1 = S.concatMapFoldableWith (<>) return [1..4]
787− s2 = S.foldMapWith (<>) return [5..8]
791+ s2 = S.concatMapFoldableWith (<>) return [5..8]
788 in toListSerial (do
792 in toListSerial (do
789 x <- s1
793 x <- s1
790 y <- s2
794 y <- s2
@@ -793,8 +797,8 @@ nestTwoSerial =
793
797
794nestTwoAhead :: Expectation
798nestTwoAhead :: Expectation
795nestTwoAhead =
799nestTwoAhead =
796− let s1 = S.foldMapWith (<>) return [1..4]
800+ let s1 = S.concatMapFoldableWith (<>) return [1..4]
797− s2 = S.foldMapWith (<>) return [5..8]
801+ s2 = S.concatMapFoldableWith (<>) return [5..8]
798 in (S.toList . aheadly) (do
802 in (S.toList . aheadly) (do
799 x <- s1
803 x <- s1
800 y <- s2
804 y <- s2
@@ -803,22 +807,22 @@ nestTwoAhead =
803
807
804nestTwoSerialApp :: Expectation
808nestTwoSerialApp :: Expectation
805nestTwoSerialApp =
809nestTwoSerialApp =
806− let s1 = S.foldMapWith (<>) return [1..4]
810+ let s1 = S.concatMapFoldableWith (<>) return [1..4]
807− s2 = S.foldMapWith (<>) return [5..8]
811+ s2 = S.concatMapFoldableWith (<>) return [5..8]
808 in toListSerial ((+) <$> s1 <*> s2)
812 in toListSerial ((+) <$> s1 <*> s2)
809 `shouldReturn` ([6,7,8,9,7,8,9,10,8,9,10,11,9,10,11,12] :: [Int])
813 `shouldReturn` ([6,7,8,9,7,8,9,10,8,9,10,11,9,10,11,12] :: [Int])
810
814
811nestTwoAheadApp :: Expectation
815nestTwoAheadApp :: Expectation
812nestTwoAheadApp =
816nestTwoAheadApp =
813− let s1 = S.foldMapWith (<>) return [1..4]
817+ let s1 = S.concatMapFoldableWith (<>) return [1..4]
814− s2 = S.foldMapWith (<>) return [5..8]
818+ s2 = S.concatMapFoldableWith (<>) return [5..8]
815 in (S.toList . aheadly) ((+) <$> s1 <*> s2)
819 in (S.toList . aheadly) ((+) <$> s1 <*> s2)
816 `shouldReturn` ([6,7,8,9,7,8,9,10,8,9,10,11,9,10,11,12] :: [Int])
820 `shouldReturn` ([6,7,8,9,7,8,9,10,8,9,10,11,9,10,11,12] :: [Int])
817
821
818nestTwoInterleaved :: Expectation
822nestTwoInterleaved :: Expectation
819nestTwoInterleaved =
823nestTwoInterleaved =
820− let s1 = S.foldMapWith (<>) return [1..4]
824+ let s1 = S.concatMapFoldableWith (<>) return [1..4]
821− s2 = S.foldMapWith (<>) return [5..8]
825+ s2 = S.concatMapFoldableWith (<>) return [5..8]
822 in toListInterleaved (do
826 in toListInterleaved (do
823 x <- s1
827 x <- s1
824 y <- s2
828 y <- s2
@@ -827,15 +831,15 @@ nestTwoInterleaved =
827
831
828nestTwoInterleavedApp :: Expectation
832nestTwoInterleavedApp :: Expectation
829nestTwoInterleavedApp =
833nestTwoInterleavedApp =
830− let s1 = S.foldMapWith (<>) return [1..4]
834+ let s1 = S.concatMapFoldableWith (<>) return [1..4]
831− s2 = S.foldMapWith (<>) return [5..8]
835+ s2 = S.concatMapFoldableWith (<>) return [5..8]
832 in toListInterleaved ((+) <$> s1 <*> s2)
836 in toListInterleaved ((+) <$> s1 <*> s2)
833 `shouldReturn` ([6,7,7,8,8,8,9,9,9,9,10,10,10,11,11,12] :: [Int])
837 `shouldReturn` ([6,7,7,8,8,8,9,9,9,9,10,10,10,11,11,12] :: [Int])
834
838
835nestTwoAsync :: Expectation
839nestTwoAsync :: Expectation
836nestTwoAsync =
840nestTwoAsync =
837− let s1 = S.foldMapWith (<>) return [1..4]
841+ let s1 = S.concatMapFoldableWith (<>) return [1..4]
838− s2 = S.foldMapWith (<>) return [5..8]
842+ s2 = S.concatMapFoldableWith (<>) return [5..8]
839 in sort <$> toListAsync (do
843 in sort <$> toListAsync (do
840 x <- s1
844 x <- s1
841 y <- s2
845 y <- s2
@@ -844,15 +848,15 @@ nestTwoAsync =
844
848
845nestTwoAsyncApp :: Expectation
849nestTwoAsyncApp :: Expectation
846nestTwoAsyncApp =
850nestTwoAsyncApp =
847− let s1 = S.foldMapWith (<>) return [1..4]
851+ let s1 = S.concatMapFoldableWith (<>) return [1..4]
848− s2 = S.foldMapWith (<>) return [5..8]
852+ s2 = S.concatMapFoldableWith (<>) return [5..8]
849 in sort <$> toListAsync ((+) <$> s1 <*> s2)
853 in sort <$> toListAsync ((+) <$> s1 <*> s2)
850 `shouldReturn` sort ([6,7,8,9,7,8,9,10,8,9,10,11,9,10,11,12] :: [Int])
854 `shouldReturn` sort ([6,7,8,9,7,8,9,10,8,9,10,11,9,10,11,12] :: [Int])
851
855
852nestTwoWAsync :: Expectation
856nestTwoWAsync :: Expectation
853nestTwoWAsync =
857nestTwoWAsync =
854− let s1 = S.foldMapWith (<>) return [1..4]
858+ let s1 = S.concatMapFoldableWith (<>) return [1..4]
855− s2 = S.foldMapWith (<>) return [5..8]
859+ s2 = S.concatMapFoldableWith (<>) return [5..8]
856 in sort <$> (S.toList . wAsyncly) (do
860 in sort <$> (S.toList . wAsyncly) (do
857 x <- s1
861 x <- s1
858 y <- s2
862 y <- s2
@@ -861,8 +865,8 @@ nestTwoWAsync =
861
865
862nestTwoParallel :: Expectation
866nestTwoParallel :: Expectation
863nestTwoParallel =
867nestTwoParallel =
864− let s1 = S.foldMapWith (<>) return [1..4]
868+ let s1 = S.concatMapFoldableWith (<>) return [1..4]
865− s2 = S.foldMapWith (<>) return [5..8]
869+ s2 = S.concatMapFoldableWith (<>) return [5..8]
866 in sort <$> (S.toList . parallely) (do
870 in sort <$> (S.toList . parallely) (do
867 x <- s1
871 x <- s1
868 y <- s2
872 y <- s2
@@ -871,15 +875,15 @@ nestTwoParallel =
871
875
872nestTwoWAsyncApp :: Expectation
876nestTwoWAsyncApp :: Expectation
873nestTwoWAsyncApp =
877nestTwoWAsyncApp =
874− let s1 = S.foldMapWith (<>) return [1..4]
878+ let s1 = S.concatMapFoldableWith (<>) return [1..4]
875− s2 = S.foldMapWith (<>) return [5..8]
879+ s2 = S.concatMapFoldableWith (<>) return [5..8]
876 in sort <$> (S.toList . wAsyncly) ((+) <$> s1 <*> s2)
880 in sort <$> (S.toList . wAsyncly) ((+) <$> s1 <*> s2)
877 `shouldReturn` sort ([6,7,7,8,8,8,9,9,9,9,10,10,10,11,11,12] :: [Int])
881 `shouldReturn` sort ([6,7,7,8,8,8,9,9,9,9,10,10,10,11,11,12] :: [Int])
878
882
879nestTwoParallelApp :: Expectation
883nestTwoParallelApp :: Expectation
880nestTwoParallelApp =
884nestTwoParallelApp =
881− let s1 = S.foldMapWith (<>) return [1..4]
885+ let s1 = S.concatMapFoldableWith (<>) return [1..4]
882− s2 = S.foldMapWith (<>) return [5..8]
886+ s2 = S.concatMapFoldableWith (<>) return [5..8]
883 in sort <$> (S.toList . parallely) ((+) <$> s1 <*> s2)
887 in sort <$> (S.toList . parallely) ((+) <$> s1 <*> s2)
884 `shouldReturn` sort ([6,7,7,8,8,8,9,9,9,9,10,10,10,11,11,12] :: [Int])
888 `shouldReturn` sort ([6,7,7,8,8,8,9,9,9,9,10,10,10,11,11,12] :: [Int])
885
889
@@ -918,7 +922,7 @@ composeAndComposeSimple
918 -> (t2 IO Int -> t2 IO Int)
922 -> (t2 IO Int -> t2 IO Int)
919 -> [[Int]] -> Spec
923 -> [[Int]] -> Spec
920composeAndComposeSimple t1 t2 answer = do
924composeAndComposeSimple t1 t2 answer = do
921− let rfold = adapt . t2 . S.foldMapWith (<>) return
925+ let rfold = adapt . t2 . S.concatMapFoldableWith (<>) return
922 it "Compose right associated outer expr, right folded inner" $
926 it "Compose right associated outer expr, right folded inner" $
923 (S.toList . t1) (rfold [1,2,3] <> (rfold [4,5,6] <> rfold [7,8,9]))
927 (S.toList . t1) (rfold [1,2,3] <> (rfold [4,5,6] <> rfold [7,8,9]))
924 `shouldReturn` head answer
928 `shouldReturn` head answer
@@ -966,10 +970,10 @@ bindAndComposeSimple
966 -> (t2 IO Int -> t2 IO Int)
970 -> (t2 IO Int -> t2 IO Int)
967 -> Spec
971 -> Spec
968bindAndComposeSimple t1 t2 = do
972bindAndComposeSimple t1 t2 = do
969− -- XXX need a bind in the body of forEachWith instead of a simple return
973+ -- XXX need a bind in the body of concatForFoldableWith instead of a simple return
970 it "Compose many (right fold) with bind" $
974 it "Compose many (right fold) with bind" $
971 (sort <$> (S.toList . t1)
975 (sort <$> (S.toList . t1)
972− (adapt . t2 $ S.forEachWith (<>) [1..10 :: Int] return))
976+ (adapt . t2 $ S.concatForFoldableWith (<>) [1..10 :: Int] return))
973 `shouldReturn` [1..10]
977 `shouldReturn` [1..10]
974
978
975 it "Compose many (left fold) with bind" $
979 it "Compose many (left fold) with bind" $
@@ -1079,7 +1083,7 @@ testFromCallback :: IO Int
1079testFromCallback = do
1083testFromCallback = do
1080 ref <- newIORef Nothing
1084 ref <- newIORef Nothing
1081 let stream = S.map Just (IP.fromCallback (setCallback ref))
1085 let stream = S.map Just (IP.fromCallback (setCallback ref))
1082− `Streamly.parallel` runCallback ref
1086+ `S.parallel` runCallback ref
1083 S.sum $ S.map fromJust $ S.takeWhile isJust stream
1087 S.sum $ S.map fromJust $ S.takeWhile isJust stream
1084
1088
1085 where
1089 where
test/PureStreams.hs+4−2
@@ -4,15 +4,17 @@
4
4
5module Main (main) where
5module Main (main) where
6
6
7+#if !(MIN_VERSION_base(4,11,0))
8+import Data.Semigroup ((<>))
9+#endif
7import Test.Hspec
10import Test.Hspec
8import qualified GHC.Exts as GHC
11import qualified GHC.Exts as GHC
9
12
10−import Streamly
11−
12#ifdef USE_STREAMLY_LIST
13#ifdef USE_STREAMLY_LIST
13import Data.Functor.Identity
14import Data.Functor.Identity
14import Streamly.Internal.Data.List (List(..), pattern Cons, pattern Nil, ZipList(..),
15import Streamly.Internal.Data.List (List(..), pattern Cons, pattern Nil, ZipList(..),
15 fromZipList, toZipList)
16 fromZipList, toZipList)
17+import Streamly.Prelude (SerialT)
16import qualified Streamly.Prelude as S
18import qualified Streamly.Prelude as S
17#else
19#else
18import Prelude -- to suppress compiler warning
20import Prelude -- to suppress compiler warning
test/Streamly/Test/Array.hs+1−2
@@ -17,8 +17,7 @@ import Test.QuickCheck.Monadic (monadicIO, assert, run)
17
17
18import Test.Hspec as H
18import Test.Hspec as H
19
19
20−import Streamly (SerialT)
20+import Streamly.Prelude (SerialT)
21−
22import qualified Streamly.Prelude as S
21import qualified Streamly.Prelude as S
23
22
24#ifdef TEST_SMALL_ARRAY
23#ifdef TEST_SMALL_ARRAY
test/Streamly/Test/FileSystem/Event.hs+1−1
@@ -17,7 +17,7 @@ import Data.List.NonEmpty (NonEmpty)
17import Data.Word (Word8)
17import Data.Word (Word8)
18import Streamly.Internal.Data.Array.Storable.Foreign (Array)
18import Streamly.Internal.Data.Array.Storable.Foreign (Array)
19import System.Environment (getArgs)
19import System.Environment (getArgs)
20−import Streamly (SerialT)
20+import Streamly.Prelude (SerialT)
21
21
22import qualified Data.List.NonEmpty as NonEmpty
22import qualified Data.List.NonEmpty as NonEmpty
23import qualified Streamly.Unicode.Stream as Unicode
23import qualified Streamly.Unicode.Stream as Unicode
test/Streamly/Test/Prelude.hs+8−8
@@ -80,7 +80,7 @@ import Data.List
80 )
80 )
81import Data.Maybe (mapMaybe)
81import Data.Maybe (mapMaybe)
82#if __GLASGOW_HASKELL__ < 808
82#if __GLASGOW_HASKELL__ < 808
83−import Data.Semigroup ((<>))
83+import Data.Semigroup (Semigroup, (<>))
84#endif
84#endif
85import GHC.Word (Word8)
85import GHC.Word (Word8)
86import Test.Hspec.QuickCheck
86import Test.Hspec.QuickCheck
@@ -88,9 +88,9 @@ import Test.Hspec
88import Test.QuickCheck (Property, choose, forAll, withMaxSuccess)
88import Test.QuickCheck (Property, choose, forAll, withMaxSuccess)
89import Test.QuickCheck.Monadic (assert, monadicIO, run)
89import Test.QuickCheck.Monadic (assert, monadicIO, run)
90
90
91−import Streamly
91+import Streamly.Prelude
92−import Streamly.Prelude ((.:), nil)
92+ ( SerialT, IsStream, (.:), nil, (|&), serially, avgRate, rate, maxBuffer
93−import Streamly as S
93+ , maxThreads, maxBuffer)
94import qualified Streamly.Prelude as S
94import qualified Streamly.Prelude as S
95import qualified Streamly.Data.Fold as FL
95import qualified Streamly.Data.Fold as FL
96import qualified Streamly.Internal.Data.Fold as FL
96import qualified Streamly.Internal.Data.Fold as FL
@@ -502,7 +502,7 @@ monoidOps desc z eq t = do
502 prop (desc <> " Compose empty at the end") $ spec (singleton 1 <> z) [1]
502 prop (desc <> " Compose empty at the end") $ spec (singleton 1 <> z) [1]
503 prop (desc <> " Compose two") $ spec (singleton 0 <> singleton 1) [0, 1]
503 prop (desc <> " Compose two") $ spec (singleton 0 <> singleton 1) [0, 1]
504 prop (desc <> " Compose many") $
504 prop (desc <> " Compose many") $
505− spec (S.forEachWith (<>) [1 .. 100] singleton) [1 .. 100]
505+ spec (S.concatForFoldableWith (<>) [1 .. 100] singleton) [1 .. 100]
506
506
507 -- These are not covered by the property tests
507 -- These are not covered by the property tests
508 prop (desc <> " Compose three - empty in the middle") $
508 prop (desc <> " Compose three - empty in the middle") $
@@ -553,8 +553,8 @@ semigroupOps
553 -> (t IO Int -> SerialT IO Int)
553 -> (t IO Int -> SerialT IO Int)
554 -> Spec
554 -> Spec
555semigroupOps desc eq t = do
555semigroupOps desc eq t = do
556− prop (desc <> " <>") $ foldFromList (S.foldMapWith (<>) singleton) t eq
556+ prop (desc <> " <>") $ foldFromList (S.concatMapFoldableWith (<>) singleton) t eq
557− prop (desc <> " mappend") $ foldFromList (S.foldMapWith mappend singleton) t eq
557+ prop (desc <> " mappend") $ foldFromList (S.concatMapFoldableWith mappend singleton) t eq
558
558
559-------------------------------------------------------------------------------
559-------------------------------------------------------------------------------
560-- Transformation operations
560-- Transformation operations
@@ -850,7 +850,7 @@ folded =
850 (\xs ->
850 (\xs ->
851 case xs of
851 case xs of
852 [x] -> return x -- singleton stream case
852 [x] -> return x -- singleton stream case
853− _ -> S.foldMapWith (<>) return xs)
853+ _ -> S.concatMapFoldableWith (<>) return xs)
854
854
855makeCommonOps :: IsStream t => (t m a -> c) -> [(String, t m a -> c)]
855makeCommonOps :: IsStream t => (t m a -> c) -> [(String, t m a -> c)]
856makeCommonOps t =
856makeCommonOps t =
test/Streamly/Test/Prelude/Ahead.hs+1−1
@@ -17,7 +17,7 @@ import Test.Hspec.QuickCheck
17import Test.QuickCheck.Monadic (monadicIO, run)
17import Test.QuickCheck.Monadic (monadicIO, run)
18import Test.Hspec as H
18import Test.Hspec as H
19
19
20−import Streamly
20+import Streamly.Prelude
21import qualified Streamly.Prelude as S
21import qualified Streamly.Prelude as S
22
22
23import Streamly.Test.Common
23import Streamly.Test.Common
test/Streamly/Test/Prelude/Async.hs+1−1
@@ -15,7 +15,7 @@ import Data.Semigroup ((<>))
15import Test.Hspec.QuickCheck
15import Test.Hspec.QuickCheck
16import Test.Hspec as H
16import Test.Hspec as H
17
17
18−import Streamly
18+import Streamly.Prelude
19import qualified Streamly.Prelude as S
19import qualified Streamly.Prelude as S
20
20
21import Streamly.Test.Prelude
21import Streamly.Test.Prelude
test/Streamly/Test/Prelude/Concurrent.hs+1−1
@@ -27,7 +27,7 @@ import Test.QuickCheck
27 (Property, withMaxSuccess)
27 (Property, withMaxSuccess)
28import Test.QuickCheck.Monadic (monadicIO, run)
28import Test.QuickCheck.Monadic (monadicIO, run)
29
29
30−import Streamly
30+import Streamly.Prelude hiding (replicateM, reverse)
31import qualified Streamly.Prelude as S
31import qualified Streamly.Prelude as S
32
32
33import Streamly.Test.Common
33import Streamly.Test.Common
test/Streamly/Test/Prelude/Parallel.hs+1−1
@@ -15,7 +15,7 @@ import Data.Semigroup ((<>))
15import Test.Hspec.QuickCheck
15import Test.Hspec.QuickCheck
16import Test.Hspec as H
16import Test.Hspec as H
17
17
18−import Streamly
18+import Streamly.Prelude
19import qualified Streamly.Prelude as S
19import qualified Streamly.Prelude as S
20
20
21import Streamly.Test.Prelude
21import Streamly.Test.Prelude
test/Streamly/Test/Prelude/Serial.hs+2−1
@@ -29,7 +29,8 @@ import Test.QuickCheck
29import Test.QuickCheck.Monadic (assert, monadicIO, run)
29import Test.QuickCheck.Monadic (assert, monadicIO, run)
30import Test.Hspec as H
30import Test.Hspec as H
31
31
32−import Streamly
32+import Streamly.Prelude
33+ ( SerialT, IsStream, avgRate, maxBuffer, serial, serially)
33import qualified Streamly.Prelude as S
34import qualified Streamly.Prelude as S
34import qualified Streamly.Data.Fold as FL
35import qualified Streamly.Data.Fold as FL
35
36
test/Streamly/Test/Prelude/WAsync.hs+1−1
@@ -15,7 +15,7 @@ import Data.Semigroup ((<>))
15import Test.Hspec.QuickCheck
15import Test.Hspec.QuickCheck
16import Test.Hspec as H
16import Test.Hspec as H
17
17
18−import Streamly
18+import Streamly.Prelude
19import qualified Streamly.Prelude as S
19import qualified Streamly.Prelude as S
20
20
21import Streamly.Test.Prelude
21import Streamly.Test.Prelude
test/Streamly/Test/Prelude/WSerial.hs+1−1
@@ -17,7 +17,7 @@ import Test.Hspec.QuickCheck
17import Test.QuickCheck.Monadic (monadicIO, run)
17import Test.QuickCheck.Monadic (monadicIO, run)
18import Test.Hspec as H
18import Test.Hspec as H
19
19
20−import Streamly
20+import Streamly.Prelude
21import qualified Streamly.Prelude as S
21import qualified Streamly.Prelude as S
22
22
23import Streamly.Test.Common
23import Streamly.Test.Common
test/Streamly/Test/Prelude/ZipAsync.hs+1−1
@@ -12,7 +12,7 @@ module Streamly.Test.Prelude.ZipAsync where
12import Test.Hspec.QuickCheck
12import Test.Hspec.QuickCheck
13import Test.Hspec as H
13import Test.Hspec as H
14
14
15−import Streamly
15+import Streamly.Prelude
16import qualified Streamly.Prelude as S
16import qualified Streamly.Prelude as S
17
17
18import Streamly.Test.Prelude
18import Streamly.Test.Prelude
test/Streamly/Test/Prelude/ZipSerial.hs+1−1
@@ -15,7 +15,7 @@ import Data.Semigroup ((<>))
15import Test.Hspec.QuickCheck
15import Test.Hspec.QuickCheck
16import Test.Hspec as H
16import Test.Hspec as H
17
17
18−import Streamly
18+import Streamly.Prelude
19import qualified Streamly.Prelude as S
19import qualified Streamly.Prelude as S
20
20
21import Streamly.Test.Prelude
21import Streamly.Test.Prelude
test/loops.hs+4−2
@@ -1,6 +1,8 @@
1−import Streamly
1+#if !(MIN_VERSION_base(4,11,0))
2+import Data.Semigroup ((<>))
3+#endif
2import System.IO (stdout, hSetBuffering, BufferMode(LineBuffering))
4import System.IO (stdout, hSetBuffering, BufferMode(LineBuffering))
3−import Streamly.Prelude (nil, yieldM, drain)
5+import Streamly.Prelude
4
6
5main :: IO ()
7main :: IO ()
6main = do
8main = do
test/nested-loops.hs+4−2
@@ -1,8 +1,10 @@
1+#if !(MIN_VERSION_base(4,11,0))
2+import Data.Semigroup ((<>))
3+#endif
1import Control.Concurrent (myThreadId)
4import Control.Concurrent (myThreadId)
2import System.IO (stdout, hSetBuffering, BufferMode(LineBuffering))
5import System.IO (stdout, hSetBuffering, BufferMode(LineBuffering))
3import System.Random (randomIO)
6import System.Random (randomIO)
4−import Streamly
7+import Streamly.Prelude
5−import Streamly.Prelude (drain, nil, yieldM)
6
8
7main :: IO ()
9main :: IO ()
8main = drain $ do
10main = drain $ do
test/parallel-loops.hs+1−1
@@ -1,7 +1,7 @@
1import Control.Concurrent (myThreadId, threadDelay)
1import Control.Concurrent (myThreadId, threadDelay)
2import System.IO (stdout, hSetBuffering, BufferMode(LineBuffering))
2import System.IO (stdout, hSetBuffering, BufferMode(LineBuffering))
3import System.Random (randomIO)
3import System.Random (randomIO)
4−import Streamly
4+import Streamly.Prelude
5import qualified Streamly.Prelude as S
5import qualified Streamly.Prelude as S
6
6
7main :: IO ()
7main :: IO ()