on master help sign in
Move IsStream definition out of low level modules
70e7f94Harendra Kumar
.hlint.ignore+5
@@ -1,3 +1,5 @@
1+src/Streamly/Internal/Data/Stream/Prelude.hs
2+src/Streamly/Internal/Data/Stream/PreludeCommon.hs
1src/Streamly/Internal/Data/Stream/Serial.hs
3src/Streamly/Internal/Data/Stream/Serial.hs
2src/Streamly/Internal/Data/Stream/Zip.hs
4src/Streamly/Internal/Data/Stream/Zip.hs
3src/Streamly/Internal/Data/Stream/StreamK/Type.hs
5src/Streamly/Internal/Data/Stream/StreamK/Type.hs
@@ -6,7 +8,10 @@ src/Streamly/Internal/Data/Pipe/Type.hs
6src/Streamly/Internal/Data/SmallArray/Type.hs
8src/Streamly/Internal/Data/SmallArray/Type.hs
7src/Streamly/Internal/Unicode/Stream.hs
9src/Streamly/Internal/Unicode/Stream.hs
8src/Streamly/Internal/Data/Array/Prim/Type.hs
10src/Streamly/Internal/Data/Array/Prim/Type.hs
11+src/Streamly/Internal/Data/Array/Prim/Mut/Type.hs
9src/Streamly/Internal/Data/Array/Prim/MutTypesInclude.hs
12src/Streamly/Internal/Data/Array/Prim/MutTypesInclude.hs
13+src/Streamly/Internal/Data/Array/Prim/Pinned/Mut/Type.hs
14+src/Streamly/Internal/Data/Array/Prim/Pinned/Type.hs
10src/Streamly/Internal/Data/Array/Prim/TypesInclude.hs
15src/Streamly/Internal/Data/Array/Prim/TypesInclude.hs
11test/Streamly/Test/Common/Array.hs
16test/Streamly/Test/Common/Array.hs
12test/Streamly/Test/Data/Array.hs
17test/Streamly/Test/Data/Array.hs
benchmark/Streamly/Benchmark/Data/Stream/StreamK.hs+27−16
@@ -32,6 +32,7 @@ import qualified Prelude as P
32import qualified Data.List as List
32import qualified Data.List as List
33
33
34import qualified Streamly.Internal.Control.Concurrent as S
34import qualified Streamly.Internal.Control.Concurrent as S
35+import qualified Streamly.Internal.Data.Stream.StreamK.Type as S
35import qualified Streamly.Internal.Data.Stream.StreamK as S
36import qualified Streamly.Internal.Data.Stream.StreamK as S
36
37
37import Gauge (bench, nfIO, bgroup, Benchmark, defaultMain)
38import Gauge (bench, nfIO, bgroup, Benchmark, defaultMain)
@@ -127,7 +128,7 @@ unfoldr streamLen n = S.unfoldr step n
127
128
128{-# INLINE unfoldrM #-}
129{-# INLINE unfoldrM #-}
129unfoldrM :: S.MonadAsync m => Int -> Int -> Stream m Int
130unfoldrM :: S.MonadAsync m => Int -> Int -> Stream m Int
130−unfoldrM streamLen n = S.unfoldrM step n
131+unfoldrM streamLen n = S.unfoldrMWith S.consM step n
131 where
132 where
132 step cnt =
133 step cnt =
133 if cnt > n + streamLen
134 if cnt > n + streamLen
@@ -148,7 +149,7 @@ replicate = S.replicate
148
149
149{-# INLINE replicateM #-}
150{-# INLINE replicateM #-}
150replicateM :: S.MonadAsync m => Int -> Int -> Stream m Int
151replicateM :: S.MonadAsync m => Int -> Int -> Stream m Int
151−replicateM streamLen = S.replicateM streamLen . return
152+replicateM streamLen = S.replicateMWith S.consM streamLen . return
152
153
153{-# INLINE iterate #-}
154{-# INLINE iterate #-}
154iterate :: Int -> Int -> Stream m Int
155iterate :: Int -> Int -> Stream m Int
@@ -168,8 +169,11 @@ fromFoldableM streamLen n =
168 Prelude.foldr S.consM S.nil (Prelude.fmap return [n..n+streamLen])
169 Prelude.foldr S.consM S.nil (Prelude.fmap return [n..n+streamLen])
169
170
170{-# INLINABLE concatMapFoldableWith #-}
171{-# INLINABLE concatMapFoldableWith #-}
171−concatMapFoldableWith :: (S.IsStream t, Foldable f)
172+concatMapFoldableWith :: Foldable f
172− => (t m b -> t m b -> t m b) -> (a -> t m b) -> f a -> t m b
173+ => (Stream m b -> Stream m b -> Stream m b)
174+ -> (a -> Stream m b)
175+ -> f a
176+ -> Stream m b
173concatMapFoldableWith f g = Prelude.foldr (f . g) S.nil
177concatMapFoldableWith f g = Prelude.foldr (f . g) S.nil
174
178
175{-# INLINE concatMapFoldableSerial #-}
179{-# INLINE concatMapFoldableSerial #-}
@@ -202,13 +206,13 @@ uncons s = do
202 Just (_, t) -> uncons t
206 Just (_, t) -> uncons t
203
207
204{-# INLINE init #-}
208{-# INLINE init #-}
205−init :: (Monad m, S.IsStream t) => t m a -> m ()
209+init :: Monad m => Stream m a -> m ()
206init s = do
210init s = do
207 t <- S.init s
211 t <- S.init s
208 P.mapM_ S.drain t
212 P.mapM_ S.drain t
209
213
210{-# INLINE tail #-}
214{-# INLINE tail #-}
211−tail :: (Monad m, S.IsStream t) => t m a -> m ()
215+tail :: Monad m => Stream m a -> m ()
212tail s = S.tail s >>= P.mapM_ tail
216tail s = S.tail s >>= P.mapM_ tail
213
217
214{-# INLINE nullTail #-}
218{-# INLINE nullTail #-}
@@ -265,7 +269,7 @@ fmapK n = composeN n $ P.fmap (+ 1)
265
269
266{-# INLINE mapM #-}
270{-# INLINE mapM #-}
267mapM :: S.MonadAsync m => Int -> Stream m Int -> m ()
271mapM :: S.MonadAsync m => Int -> Stream m Int -> m ()
268−mapM n = composeN n $ S.mapM return
272+mapM n = composeN n $ S.mapMWith S.consM return
269
273
270{-# INLINE mapMSerial #-}
274{-# INLINE mapMSerial #-}
271mapMSerial :: S.MonadAsync m => Int -> Stream m Int -> m ()
275mapMSerial :: S.MonadAsync m => Int -> Stream m Int -> m ()
@@ -339,7 +343,8 @@ iterateSource iterStreamLen g i n = f i (unfoldrM iterStreamLen n)
339-- this is quadratic
343-- this is quadratic
340{-# INLINE iterateScan #-}
344{-# INLINE iterateScan #-}
341iterateScan :: S.MonadAsync m => Int -> Int -> Int -> Stream m Int
345iterateScan :: S.MonadAsync m => Int -> Int -> Int -> Stream m Int
346+iterateScan iterStreamLen maxIters =
342−iterateScan iterStreamLen maxIters = iterateSource iterStreamLen (S.scanl' (+) 0) (maxIters `div` 10)
347+ iterateSource iterStreamLen (S.scanl' (+) 0) (maxIters `div` 10)
343
348
344-- this is quadratic
349-- this is quadratic
345{-# INLINE iterateDropWhileFalse #-}
350{-# INLINE iterateDropWhileFalse #-}
@@ -349,23 +354,27 @@ iterateDropWhileFalse streamLen iterStreamLen maxIters =
349
354
350{-# INLINE iterateMapM #-}
355{-# INLINE iterateMapM #-}
351iterateMapM :: S.MonadAsync m => Int -> Int -> Int -> Stream m Int
356iterateMapM :: S.MonadAsync m => Int -> Int -> Int -> Stream m Int
357+iterateMapM iterStreamLen =
352−iterateMapM iterStreamLen maxIters = iterateSource iterStreamLen (S.mapM return) maxIters
358+ iterateSource iterStreamLen (S.mapMWith S.consM return)
353
359
354{-# INLINE iterateFilterEven #-}
360{-# INLINE iterateFilterEven #-}
355iterateFilterEven :: S.MonadAsync m => Int -> Int -> Int -> Stream m Int
361iterateFilterEven :: S.MonadAsync m => Int -> Int -> Int -> Stream m Int
356−iterateFilterEven iterStreamLen maxIters = iterateSource iterStreamLen (S.filter even) maxIters
362+iterateFilterEven iterStreamLen = iterateSource iterStreamLen (S.filter even)
357
363
358{-# INLINE iterateTakeAll #-}
364{-# INLINE iterateTakeAll #-}
359iterateTakeAll :: S.MonadAsync m => Int -> Int -> Int -> Int -> Stream m Int
365iterateTakeAll :: S.MonadAsync m => Int -> Int -> Int -> Int -> Stream m Int
366+iterateTakeAll streamLen iterStreamLen =
360−iterateTakeAll streamLen iterStreamLen maxIters = iterateSource iterStreamLen (S.take streamLen) maxIters
367+ iterateSource iterStreamLen (S.take streamLen)
361
368
362{-# INLINE iterateDropOne #-}
369{-# INLINE iterateDropOne #-}
363iterateDropOne :: S.MonadAsync m => Int -> Int -> Int -> Stream m Int
370iterateDropOne :: S.MonadAsync m => Int -> Int -> Int -> Stream m Int
364−iterateDropOne iterStreamLen maxIters = iterateSource iterStreamLen (S.drop 1) maxIters
371+iterateDropOne iterStreamLen = iterateSource iterStreamLen (S.drop 1)
365
372
366{-# INLINE iterateDropWhileTrue #-}
373{-# INLINE iterateDropWhileTrue #-}
367−iterateDropWhileTrue :: S.MonadAsync m => Int -> Int -> Int -> Int -> Stream m Int
374+iterateDropWhileTrue :: S.MonadAsync m =>
375+ Int -> Int -> Int -> Int -> Stream m Int
376+iterateDropWhileTrue streamLen iterStreamLen =
368−iterateDropWhileTrue streamLen iterStreamLen maxIters = iterateSource iterStreamLen (S.dropWhile (<= streamLen)) maxIters
377+ iterateSource iterStreamLen (S.dropWhile (<= streamLen))
369
378
370-------------------------------------------------------------------------------
379-------------------------------------------------------------------------------
371-- Zipping
380-- Zipping
@@ -471,7 +480,7 @@ sourceConcatMapId val n =
471{-# INLINE concatMapBySerial #-}
480{-# INLINE concatMapBySerial #-}
472concatMapBySerial :: Int -> Int -> Int -> IO ()
481concatMapBySerial :: Int -> Int -> Int -> IO ()
473concatMapBySerial outer inner n =
482concatMapBySerial outer inner n =
474− S.drain $ S.concatMapBy S.serial
483+ S.drain $ S.concatMapWith S.serial
475 (unfoldrM inner)
484 (unfoldrM inner)
476 (unfoldrM outer n)
485 (unfoldrM outer n)
477
486
@@ -681,7 +690,9 @@ o_1_space_concat streamLen =
681
690
682 -- This is for comparison with concatMapFoldableWith
691 -- This is for comparison with concatMapFoldableWith
683 , benchIOSrc1 "concatMapWithId (n of 1) (fromFoldable)"
692 , benchIOSrc1 "concatMapWithId (n of 1) (fromFoldable)"
693+ (S.drain
694+ . S.concatMapWith S.serial id
684− (S.drain . S.concatMapBy S.serial id . sourceConcatMapId streamLen)
695+ . sourceConcatMapId streamLen)
685
696
686 , benchIOSrc1 "concatMapBy serial (n of 1)"
697 , benchIOSrc1 "concatMapBy serial (n of 1)"
687 (concatMapBySerial streamLen 1)
698 (concatMapBySerial streamLen 1)
benchmark/Streamly/Benchmark/Prelude/Async.hs+2−2
@@ -9,7 +9,7 @@ import Prelude hiding (mapM)
9
9
10import Streamly.Prelude (fromAsync, async, maxBuffer, maxThreads, fromSerial)
10import Streamly.Prelude (fromAsync, async, maxBuffer, maxThreads, fromSerial)
11import qualified Streamly.Prelude as S
11import qualified Streamly.Prelude as S
12−import qualified Streamly.Internal.Data.Stream.StreamK.Type as Internal
12+import qualified Streamly.Internal.Data.Stream.IsStream.Transform as Transform
13
13
14import Streamly.Benchmark.Common
14import Streamly.Benchmark.Common
15import Streamly.Benchmark.Prelude
15import Streamly.Benchmark.Prelude
@@ -48,7 +48,7 @@ foldrSShared :: Int -> Int -> IO ()
48foldrSShared count n =
48foldrSShared count n =
49 S.drain
49 S.drain
50 $ fromAsync
50 $ fromAsync
51− $ Internal.foldrSShared (\x xs -> S.consM (return x) xs) S.nil
51+ $ Transform.foldrSShared (\x xs -> S.consM (return x) xs) S.nil
52 $ fromSerial
52 $ fromSerial
53 $ sourceUnfoldrM count n
53 $ sourceUnfoldrM count n
54
54
benchmark/Streamly/Benchmark/Prelude/Parallel.hs+1−2
@@ -15,7 +15,6 @@ import Streamly.Prelude
15
15
16import qualified Streamly.Prelude as S
16import qualified Streamly.Prelude as S
17import qualified Streamly.Internal.Data.Fold as FL
17import qualified Streamly.Internal.Data.Fold as FL
18−import qualified Streamly.Internal.Data.Stream.Parallel as Par
19import qualified Streamly.Internal.Data.Stream.IsStream as Internal
18import qualified Streamly.Internal.Data.Stream.IsStream as Internal
20
19
21import Streamly.Benchmark.Common
20import Streamly.Benchmark.Common
@@ -72,7 +71,7 @@ parAppSum src = (S.sum S.|$. src) >>= \x -> seq x (return ())
72
71
73{-# INLINE tapAsyncS #-}
72{-# INLINE tapAsyncS #-}
74tapAsyncS :: S.MonadAsync m => Int -> SerialT m Int -> m ()
73tapAsyncS :: S.MonadAsync m => Int -> SerialT m Int -> m ()
75−tapAsyncS n = composeN n $ Par.tapAsync S.sum
74+tapAsyncS n = composeN n $ Internal.tapAsyncK S.sum
76
75
77{-# INLINE tapAsync #-}
76{-# INLINE tapAsync #-}
78tapAsync :: S.MonadAsync m => Int -> SerialT m Int -> m ()
77tapAsync :: S.MonadAsync m => Int -> SerialT m Int -> m ()
benchmark/Streamly/Benchmark/Prelude/Serial/Transformation3.hs+1
@@ -84,6 +84,7 @@ iterateStateT n = do
84 else return x
84 else return x
85
85
86{-# INLINE iterateState #-}
86{-# INLINE iterateState #-}
87+{-# SPECIALIZE iterateState :: Int -> SerialT (StateT Int IO) Int #-}
87iterateState ::
88iterateState ::
88 (S.MonadAsync m, MonadState Int m)
89 (S.MonadAsync m, MonadState Int m)
89 => Int
90 => Int
benchmark/lib/Streamly/Benchmark/Prelude.hs+3−1
@@ -26,6 +26,7 @@ import qualified Data.Foldable as F
26import qualified Data.List as List
26import qualified Data.List as List
27import qualified Streamly.Prelude as S
27import qualified Streamly.Prelude as S
28import qualified Streamly.Internal.Data.Stream.IsStream as Internal
28import qualified Streamly.Internal.Data.Stream.IsStream as Internal
29+import qualified Streamly.Internal.Data.Stream.IsStream.Type as IsStream
29import qualified Streamly.Internal.Data.Pipe as Pipe
30import qualified Streamly.Internal.Data.Pipe as Pipe
30import qualified Streamly.Internal.Data.Stream.Serial as Serial
31import qualified Streamly.Internal.Data.Stream.Serial as Serial
31
32
@@ -89,7 +90,8 @@ sourceUnfoldrM count start = S.unfoldrM step start
89
90
90{-# INLINE sourceUnfoldrMSerial #-}
91{-# INLINE sourceUnfoldrMSerial #-}
91sourceUnfoldrMSerial :: (S.IsStream t, Monad m) => Int -> Int -> t m Int
92sourceUnfoldrMSerial :: (S.IsStream t, Monad m) => Int -> Int -> t m Int
92−sourceUnfoldrMSerial count start = Serial.unfoldrM step start
93+sourceUnfoldrMSerial count start =
94+ IsStream.fromSerial $ Serial.unfoldrM step start
93 where
95 where
94 step cnt =
96 step cnt =
95 if cnt > start + count
97 if cnt > start + count
hie.yaml+8
@@ -14,10 +14,18 @@ cradle:
14 component: "bench:Data.Parser.ParserD"
14 component: "bench:Data.Parser.ParserD"
15 - path: "./benchmark/Streamly/Benchmark/Data/Parser/ParserK.hs"
15 - path: "./benchmark/Streamly/Benchmark/Data/Parser/ParserK.hs"
16 component: "bench:Data.Parser.ParserK"
16 component: "bench:Data.Parser.ParserK"
17+ - path: "./benchmark/Streamly/Benchmark/Data/Stream/StreamK.hs"
18+ component: "bench:Data.Stream.StreamK"
17 - path: "./benchmark/Streamly/Benchmark/FileSystem/Handle/Read.hs"
19 - path: "./benchmark/Streamly/Benchmark/FileSystem/Handle/Read.hs"
18 component: "bench:FileSystem.Handle"
20 component: "bench:FileSystem.Handle"
19 - path: "./benchmark/Streamly/Benchmark/FileSystem/Handle/ReadWrite.hs"
21 - path: "./benchmark/Streamly/Benchmark/FileSystem/Handle/ReadWrite.hs"
20 component: "bench:FileSystem.Handle"
22 component: "bench:FileSystem.Handle"
23+ - path: "./benchmark/Streamly/Benchmark/Prelude/Ahead.hs"
24+ component: "bench:Prelude.Ahead"
25+ - path: "./benchmark/Streamly/Benchmark/Prelude/Async.hs"
26+ component: "bench:Prelude.Async"
27+ - path: "./benchmark/Streamly/Benchmark/Prelude/Parallel.hs"
28+ component: "bench:Prelude.Parallel"
21 - path: "./benchmark/Streamly/Benchmark/Prelude/Serial.hs"
29 - path: "./benchmark/Streamly/Benchmark/Prelude/Serial.hs"
22 component: "bench:Prelude.Serial"
30 component: "bench:Prelude.Serial"
23 - path: "./benchmark/Streamly/Benchmark/Prelude/Serial/Elimination.hs"
31 - path: "./benchmark/Streamly/Benchmark/Prelude/Serial/Elimination.hs"
src/Streamly.hs+12−13
@@ -213,17 +213,16 @@ import Data.Semigroup (Semigroup(..))
213import Streamly.Internal.Control.Concurrent (MonadAsync)
213import Streamly.Internal.Control.Concurrent (MonadAsync)
214import Streamly.Internal.Data.SVar (Rate(..))
214import Streamly.Internal.Data.SVar (Rate(..))
215import Streamly.Internal.Data.Stream.Ahead
215import Streamly.Internal.Data.Stream.Ahead
216−import Streamly.Internal.Data.Stream.Async hiding (mkAsync)
216+import Streamly.Internal.Data.Stream.Async
217import Streamly.Internal.Data.Stream.IsStream.Combinators
217import Streamly.Internal.Data.Stream.IsStream.Combinators
218−import Streamly.Internal.Data.Stream.Parallel
218+import Streamly.Internal.Data.Stream.IsStream.Expand
219+import Streamly.Internal.Data.Stream.IsStream.Type
219−import Streamly.Internal.Data.Stream.Serial
220+import Streamly.Internal.Data.Stream.Serial (StreamT, InterleavedT)
220−import Streamly.Internal.Data.Stream.StreamK hiding (serial)
221import Streamly.Internal.Data.Stream.Zip
221import Streamly.Internal.Data.Stream.Zip
222
222
223import qualified Streamly.Prelude as P
223import qualified Streamly.Prelude as P
224import qualified Streamly.Internal.Data.Stream.IsStream as IP
224import qualified Streamly.Internal.Data.Stream.IsStream as IP
225−import qualified Streamly.Internal.Data.Stream.StreamK as K
225+import qualified Streamly.Internal.Data.Stream.IsStream.Transform as Transform
226−import qualified Streamly.Internal.Data.Stream.Async as Async
227
226
228-- XXX provide good succinct examples of pipelining, merging, splitting etc.
227-- XXX provide good succinct examples of pipelining, merging, splitting etc.
229-- below.
228-- below.
@@ -364,7 +363,7 @@ import qualified Streamly.Internal.Data.Stream.Async as Async
364-- @since 0.1.0
363-- @since 0.1.0
365{-# DEPRECATED runStreaming "Please use runStream instead." #-}
364{-# DEPRECATED runStreaming "Please use runStream instead." #-}
366runStreaming :: (Monad m, IsStream t) => t m a -> m ()
365runStreaming :: (Monad m, IsStream t) => t m a -> m ()
367−runStreaming = P.drain . K.adapt
366+runStreaming = P.drain . adapt
368
367
369-- | Same as @runStream@.
368-- | Same as @runStream@.
370--
369--
@@ -384,35 +383,35 @@ runStream = P.drain
384-- @since 0.1.0
383-- @since 0.1.0
385{-# DEPRECATED runInterleavedT "Please use 'drain . interleaving' instead." #-}
384{-# DEPRECATED runInterleavedT "Please use 'drain . interleaving' instead." #-}
386runInterleavedT :: Monad m => WSerialT m a -> m ()
385runInterleavedT :: Monad m => WSerialT m a -> m ()
387−runInterleavedT = P.drain . K.adapt
386+runInterleavedT = P.drain . adapt
388
387
389-- | Same as @drain . fromParallel@.
388-- | Same as @drain . fromParallel@.
390--
389--
391-- @since 0.1.0
390-- @since 0.1.0
392{-# DEPRECATED runParallelT "Please use 'drain . fromParallel' instead." #-}
391{-# DEPRECATED runParallelT "Please use 'drain . fromParallel' instead." #-}
393runParallelT :: Monad m => ParallelT m a -> m ()
392runParallelT :: Monad m => ParallelT m a -> m ()
394−runParallelT = P.drain . K.adapt
393+runParallelT = P.drain . adapt
395
394
396-- | Same as @drain . fromAsync@.
395-- | Same as @drain . fromAsync@.
397--
396--
398-- @since 0.1.0
397-- @since 0.1.0
399{-# DEPRECATED runAsyncT "Please use 'drain . fromAsync' instead." #-}
398{-# DEPRECATED runAsyncT "Please use 'drain . fromAsync' instead." #-}
400runAsyncT :: Monad m => AsyncT m a -> m ()
399runAsyncT :: Monad m => AsyncT m a -> m ()
401−runAsyncT = P.drain . K.adapt
400+runAsyncT = P.drain . adapt
402
401
403-- | Same as @drain . zipping@.
402-- | Same as @drain . zipping@.
404--
403--
405-- @since 0.1.0
404-- @since 0.1.0
406{-# DEPRECATED runZipStream "Please use 'drain . fromZipSerial instead." #-}
405{-# DEPRECATED runZipStream "Please use 'drain . fromZipSerial instead." #-}
407runZipStream :: Monad m => ZipSerialM m a -> m ()
406runZipStream :: Monad m => ZipSerialM m a -> m ()
408−runZipStream = P.drain . K.adapt
407+runZipStream = P.drain . adapt
409
408
410-- | Same as @drain . zippingAsync@.
409-- | Same as @drain . zippingAsync@.
411--
410--
412-- @since 0.1.0
411-- @since 0.1.0
413{-# DEPRECATED runZipAsync "Please use 'drain . fromZipAsync instead." #-}
412{-# DEPRECATED runZipAsync "Please use 'drain . fromZipAsync instead." #-}
414runZipAsync :: Monad m => ZipAsyncM m a -> m ()
413runZipAsync :: Monad m => ZipAsyncM m a -> m ()
415−runZipAsync = P.drain . K.adapt
414+runZipAsync = P.drain . adapt
416
415
417{-
416{-
418-- | Same as "Streamly.Prelude.foldWith".
417-- | Same as "Streamly.Prelude.foldWith".
@@ -451,7 +450,7 @@ forEachWith = P.forEachWith
451-- @since 0.2.0
450-- @since 0.2.0
452{-# INLINABLE mkAsync #-}
451{-# INLINABLE mkAsync #-}
453mkAsync :: (IsStream t, MonadAsync m) => t m a -> m (t m a)
452mkAsync :: (IsStream t, MonadAsync m) => t m a -> m (t m a)
454−mkAsync = return . Async.mkAsync
453+mkAsync = return . Transform.mkAsync
455
454
456------------------------------------------------------------------------------
455------------------------------------------------------------------------------
457-- Documentation
456-- Documentation
src/Streamly/Internal/Data/Array.hs+8−9
@@ -56,8 +56,7 @@ import GHC.Base (Int(..))
56import GHC.IO (unsafePerformIO)
56import GHC.IO (unsafePerformIO)
57
57
58import Streamly.Internal.Data.Fold.Type (Fold(..))
58import Streamly.Internal.Data.Fold.Type (Fold(..))
59−import Streamly.Internal.Data.Stream.StreamK.Type (IsStream)
59+import Streamly.Internal.Data.Stream.Serial (SerialT(..))
60−import Streamly.Internal.Data.Stream.Serial (SerialT)
61import Streamly.Internal.Data.Tuple.Strict (Tuple'(..), Tuple3'(..))
60import Streamly.Internal.Data.Tuple.Strict (Tuple'(..), Tuple3'(..))
62import Streamly.Internal.Data.Unfold.Type (Unfold(..))
61import Streamly.Internal.Data.Unfold.Type (Unfold(..))
63
62
@@ -131,13 +130,13 @@ fromStreamD = D.fold write
131
130
132{-# INLINE fromStreamN #-}
131{-# INLINE fromStreamN #-}
133fromStreamN :: MonadIO m => Int -> SerialT m a -> m (Array a)
132fromStreamN :: MonadIO m => Int -> SerialT m a -> m (Array a)
134−fromStreamN n m = do
133+fromStreamN n (SerialT m) = do
135 when (n < 0) $ error "fromStreamN: negative write count specified"
134 when (n < 0) $ error "fromStreamN: negative write count specified"
136− fromStreamDN n $ D.toStreamD m
135+ fromStreamDN n $ D.fromStreamK m
137
136
138{-# INLINE fromStream #-}
137{-# INLINE fromStream #-}
139fromStream :: MonadIO m => SerialT m a -> m (Array a)
138fromStream :: MonadIO m => SerialT m a -> m (Array a)
140−fromStream m = fromStreamD $ D.toStreamD m
139+fromStream (SerialT m) = fromStreamD $ D.fromStreamK m
141
140
142{-# INLINABLE fromListN #-}
141{-# INLINABLE fromListN #-}
143fromListN :: Int -> [a] -> Array a
142fromListN :: Int -> [a] -> Array a
@@ -196,12 +195,12 @@ toStreamDRev arr = D.Stream step (length arr - 1)
196 (# x #) -> D.Yield x (I# i - 1)
195 (# x #) -> D.Yield x (I# i - 1)
197
196
198{-# INLINE_EARLY toStream #-}
197{-# INLINE_EARLY toStream #-}
199−toStream :: (Monad m, IsStream t) => Array a -> t m a
198+toStream :: Monad m => Array a -> SerialT m a
200−toStream = D.fromStreamD . toStreamD
199+toStream = SerialT . D.toStreamK . toStreamD
201
200
202{-# INLINE_EARLY toStreamRev #-}
201{-# INLINE_EARLY toStreamRev #-}
203−toStreamRev :: (Monad m, IsStream t) => Array a -> t m a
202+toStreamRev :: Monad m => Array a -> SerialT m a
204−toStreamRev = D.fromStreamD . toStreamDRev
203+toStreamRev = SerialT . D.toStreamK . toStreamDRev
205
204
206-------------------------------------------------------------------------------
205-------------------------------------------------------------------------------
207-- Elimination - using Folds
206-- Elimination - using Folds
src/Streamly/Internal/Data/Array/Foreign.hs+7−8
@@ -141,7 +141,7 @@ import Streamly.Internal.BaseCompat
141import Streamly.Internal.Data.Array.Foreign.Type (Array(..), length)
141import Streamly.Internal.Data.Array.Foreign.Type (Array(..), length)
142import Streamly.Internal.Data.Fold.Type (Fold(..))
142import Streamly.Internal.Data.Fold.Type (Fold(..))
143import Streamly.Internal.Data.Producer.Type (Producer)
143import Streamly.Internal.Data.Producer.Type (Producer)
144−import Streamly.Internal.Data.Stream.Serial (SerialT)
144+import Streamly.Internal.Data.Stream.Serial (SerialT(..))
145import Streamly.Internal.Data.Tuple.Strict (Tuple3'(..))
145import Streamly.Internal.Data.Tuple.Strict (Tuple3'(..))
146import Streamly.Internal.Data.Unfold.Type (Unfold(..))
146import Streamly.Internal.Data.Unfold.Type (Unfold(..))
147import Streamly.Internal.System.IO (unsafeInlineIO)
147import Streamly.Internal.System.IO (unsafeInlineIO)
@@ -150,7 +150,6 @@ import qualified Streamly.Internal.Data.Array.Foreign.Mut.Type as MA
150import qualified Streamly.Internal.Data.Array.Foreign.Type as A
150import qualified Streamly.Internal.Data.Array.Foreign.Type as A
151import qualified Streamly.Internal.Data.Fold as FL
151import qualified Streamly.Internal.Data.Fold as FL
152import qualified Streamly.Internal.Data.Stream.Prelude as P
152import qualified Streamly.Internal.Data.Stream.Prelude as P
153−import qualified Streamly.Internal.Data.Stream.Serial as Serial
154import qualified Streamly.Internal.Data.Stream.StreamD as D
153import qualified Streamly.Internal.Data.Stream.StreamD as D
155import qualified Streamly.Internal.Data.Unfold as Unfold
154import qualified Streamly.Internal.Data.Unfold as Unfold
156import qualified Streamly.Internal.Data.Producer.Type as Producer
155import qualified Streamly.Internal.Data.Producer.Type as Producer
@@ -176,9 +175,9 @@ plusForeignPtr (ForeignPtr addr c) (I# d) = ForeignPtr (plusAddr# addr d) c
176-- /Pre-release/
175-- /Pre-release/
177{-# INLINE fromStreamN #-}
176{-# INLINE fromStreamN #-}
178fromStreamN :: (MonadIO m, Storable a) => Int -> SerialT m a -> m (Array a)
177fromStreamN :: (MonadIO m, Storable a) => Int -> SerialT m a -> m (Array a)
179−fromStreamN n m = do
178+fromStreamN n (SerialT m) = do
180 when (n < 0) $ error "writeN: negative write count specified"
179 when (n < 0) $ error "writeN: negative write count specified"
181− A.fromStreamDN n $ D.toStreamD m
180+ A.fromStreamDN n $ D.fromStreamK m
182
181
183-- | Create an 'Array' from a stream. This is useful when we want to create a
182-- | Create an 'Array' from a stream. This is useful when we want to create a
184-- single array from a stream of unknown size. 'writeN' is at least twice
183-- single array from a stream of unknown size. 'writeN' is at least twice
@@ -191,8 +190,8 @@ fromStreamN n m = do
191-- /Pre-release/
190-- /Pre-release/
192{-# INLINE fromStream #-}
191{-# INLINE fromStream #-}
193fromStream :: (MonadIO m, Storable a) => SerialT m a -> m (Array a)
192fromStream :: (MonadIO m, Storable a) => SerialT m a -> m (Array a)
194−fromStream = P.fold A.write
193+fromStream (SerialT m) = P.fold A.write m
195−-- write m = A.fromStreamD $ D.toStreamD m
194+-- write m = A.fromStreamD $ D.fromStreamK m
196
195
197-------------------------------------------------------------------------------
196-------------------------------------------------------------------------------
198-- Elimination
197-- Elimination
@@ -454,7 +453,7 @@ streamTransform :: forall m a b. (MonadIO m, Storable a, Storable b)
454 => (SerialT m a -> SerialT m b) -> Array a -> m (Array b)
453 => (SerialT m a -> SerialT m b) -> Array a -> m (Array b)
455streamTransform f arr =
454streamTransform f arr =
456 P.fold (A.toArrayMinChunk (alignment (undefined :: a)) (length arr))
455 P.fold (A.toArrayMinChunk (alignment (undefined :: a)) (length arr))
457− $ f (A.toStream arr)
456+ $ getSerialT $ f (A.toStream arr)
458
457
459-------------------------------------------------------------------------------
458-------------------------------------------------------------------------------
460-- Casts
459-- Casts
@@ -527,7 +526,7 @@ unsafeAsCString arr act = do
527-- /Pre-release/
526-- /Pre-release/
528{-# INLINE fold #-}
527{-# INLINE fold #-}
529fold :: forall m a b. (MonadIO m, Storable a) => Fold m a b -> Array a -> m b
528fold :: forall m a b. (MonadIO m, Storable a) => Fold m a b -> Array a -> m b
530−fold f arr = P.fold f (A.toStream arr :: Serial.SerialT m a)
529+fold f arr = P.fold f (getSerialT (A.toStream arr))
531
530
532-- | Fold an array using a stream fold operation.
531-- | Fold an array using a stream fold operation.
533--
532--
src/Streamly/Internal/Data/Array/Foreign/Mut/Type.hs+2−2
@@ -686,7 +686,7 @@ toStreamD Array{..} =
686 return $ D.Yield x (p `plusPtr` sizeOf (undefined :: a))
686 return $ D.Yield x (p `plusPtr` sizeOf (undefined :: a))
687
687
688{-# INLINE toStreamK #-}
688{-# INLINE toStreamK #-}
689−toStreamK :: forall t m a. (K.IsStream t, Storable a) => Array a -> t m a
689+toStreamK :: forall m a. Storable a => Array a -> K.Stream m a
690toStreamK Array{..} =
690toStreamK Array{..} =
691 let p = unsafeForeignPtrToPtr aStart
691 let p = unsafeForeignPtrToPtr aStart
692 in go p
692 in go p
@@ -726,7 +726,7 @@ toStreamDRev Array{..} =
726 return $ D.Yield x (p `plusPtr` negate (sizeOf (undefined :: a)))
726 return $ D.Yield x (p `plusPtr` negate (sizeOf (undefined :: a)))
727
727
728{-# INLINE toStreamKRev #-}
728{-# INLINE toStreamKRev #-}
729−toStreamKRev :: forall t m a. (K.IsStream t, Storable a) => Array a -> t m a
729+toStreamKRev :: forall m a. Storable a => Array a -> K.Stream m a
730toStreamKRev Array {..} =
730toStreamKRev Array {..} =
731 let p = aEnd `plusPtr` negate (sizeOf (undefined :: a))
731 let p = aEnd `plusPtr` negate (sizeOf (undefined :: a))
732 in go p
732 in go p
src/Streamly/Internal/Data/Array/Foreign/Type.hs+7−6
@@ -91,6 +91,7 @@ import GHC.ForeignPtr (touchForeignPtr, unsafeForeignPtrToPtr)
91import GHC.IO (unsafePerformIO)
91import GHC.IO (unsafePerformIO)
92import GHC.Ptr (Ptr(..))
92import GHC.Ptr (Ptr(..))
93import Streamly.Internal.Data.Fold.Type (Fold(..))
93import Streamly.Internal.Data.Fold.Type (Fold(..))
94+import Streamly.Internal.Data.Stream.Serial (SerialT(..))
94import Streamly.Internal.Data.Unfold.Type (Unfold(..))
95import Streamly.Internal.Data.Unfold.Type (Unfold(..))
95import Text.Read (readPrec, readListPrec, readListPrecDefault)
96import Text.Read (readPrec, readListPrec, readListPrecDefault)
96
97
@@ -429,7 +430,7 @@ toStreamD :: forall m a. (Monad m, Storable a) => Array a -> D.Stream m a
429toStreamD arr = MA.toStreamD (unsafeThaw arr)
430toStreamD arr = MA.toStreamD (unsafeThaw arr)
430
431
431{-# INLINE toStreamK #-}
432{-# INLINE toStreamK #-}
432−toStreamK :: forall t m a. (K.IsStream t, Storable a) => Array a -> t m a
433+toStreamK :: forall m a. Storable a => Array a -> K.Stream m a
433toStreamK arr = MA.toStreamK (unsafeThaw arr)
434toStreamK arr = MA.toStreamK (unsafeThaw arr)
434
435
435{-# INLINE_NORMAL toStreamDRev #-}
436{-# INLINE_NORMAL toStreamDRev #-}
@@ -437,15 +438,15 @@ toStreamDRev :: forall m a. (Monad m, Storable a) => Array a -> D.Stream m a
437toStreamDRev arr = MA.toStreamDRev (unsafeThaw arr)
438toStreamDRev arr = MA.toStreamDRev (unsafeThaw arr)
438
439
439{-# INLINE toStreamKRev #-}
440{-# INLINE toStreamKRev #-}
440−toStreamKRev :: forall t m a. (K.IsStream t, Storable a) => Array a -> t m a
441+toStreamKRev :: forall m a. Storable a => Array a -> K.Stream m a
441toStreamKRev arr = MA.toStreamKRev (unsafeThaw arr)
442toStreamKRev arr = MA.toStreamKRev (unsafeThaw arr)
442
443
443-- | Convert an 'Array' into a stream.
444-- | Convert an 'Array' into a stream.
444--
445--
445-- /Pre-release/
446-- /Pre-release/
446{-# INLINE_EARLY toStream #-}
447{-# INLINE_EARLY toStream #-}
447−toStream :: (Monad m, K.IsStream t, Storable a) => Array a -> t m a
448+toStream :: (Monad m, Storable a) => Array a -> SerialT m a
448−toStream = D.fromStreamD . toStreamD
449+toStream = SerialT . D.toStreamK . toStreamD
449-- XXX add fallback to StreamK rule
450-- XXX add fallback to StreamK rule
450-- {-# RULES "Streamly.Array.read fallback to StreamK" [1]
451-- {-# RULES "Streamly.Array.read fallback to StreamK" [1]
451-- forall a. S.readK (read a) = K.fromArray a #-}
452-- forall a. S.readK (read a) = K.fromArray a #-}
@@ -454,8 +455,8 @@ toStream = D.fromStreamD . toStreamD
454--
455--
455-- /Pre-release/
456-- /Pre-release/
456{-# INLINE_EARLY toStreamRev #-}
457{-# INLINE_EARLY toStreamRev #-}
457−toStreamRev :: (Monad m, K.IsStream t, Storable a) => Array a -> t m a
458+toStreamRev :: (Monad m, Storable a) => Array a -> SerialT m a
458−toStreamRev = D.fromStreamD . toStreamDRev
459+toStreamRev = SerialT . D.toStreamK . toStreamDRev
459
460
460-- XXX add fallback to StreamK rule
461-- XXX add fallback to StreamK rule
461-- {-# RULES "Streamly.Array.readRev fallback to StreamK" [1]
462-- {-# RULES "Streamly.Array.readRev fallback to StreamK" [1]
src/Streamly/Internal/Data/Array/Prim/TypesInclude.hs+3−3
@@ -25,7 +25,7 @@ import qualified GHC.Exts as Exts
25import qualified Prelude as P
25import qualified Prelude as P
26import qualified Streamly.Internal.Data.Fold as FL
26import qualified Streamly.Internal.Data.Fold as FL
27import qualified Streamly.Internal.Data.Stream.StreamD.Type as D
27import qualified Streamly.Internal.Data.Stream.StreamD.Type as D
28−import qualified Streamly.Internal.Data.Stream.StreamK as K
28+import qualified Streamly.Internal.Data.Stream.StreamK.Type as K
29
29
30import GHC.Exts hiding (fromListN, fromList, toList)
30import GHC.Exts hiding (fromListN, fromList, toList)
31import Prelude hiding (length, unlines, foldr)
31import Prelude hiding (length, unlines, foldr)
@@ -398,7 +398,7 @@ toStreamD arr = D.Stream step 0
398 step _ i = return $ D.Yield (unsafeIndex arr i) (i + 1)
398 step _ i = return $ D.Yield (unsafeIndex arr i) (i + 1)
399
399
400{-# INLINE toStreamK #-}
400{-# INLINE toStreamK #-}
401−toStreamK :: (K.IsStream t, Prim a) => Array a -> t m a
401+toStreamK :: Prim a => Array a -> K.Stream m a
402toStreamK arr = go 0
402toStreamK arr = go 0
403
403
404 where
404 where
@@ -423,7 +423,7 @@ toStreamDRev arr = D.Stream step (length arr - 1)
423 step _ i = return $ D.Yield (unsafeIndex arr i) (i - 1)
423 step _ i = return $ D.Yield (unsafeIndex arr i) (i - 1)
424
424
425{-# INLINE toStreamKRev #-}
425{-# INLINE toStreamKRev #-}
426−toStreamKRev :: (K.IsStream t, Prim a) => Array a -> t m a
426+toStreamKRev :: Prim a => Array a -> K.Stream m a
427toStreamKRev arr = go (length arr - 1)
427toStreamKRev arr = go (length arr - 1)
428
428
429 where
429 where
src/Streamly/Internal/Data/Array/PrimInclude.hs+14−15
@@ -9,13 +9,10 @@ import Control.Monad.IO.Class (MonadIO(..))
9import Data.Primitive.Types (Prim(..))
9import Data.Primitive.Types (Prim(..))
10import Streamly.Internal.Data.Fold.Type (Fold(..))
10import Streamly.Internal.Data.Fold.Type (Fold(..))
11import Streamly.Internal.Data.Unfold.Type (Unfold(..))
11import Streamly.Internal.Data.Unfold.Type (Unfold(..))
12−import Streamly.Internal.Data.Stream.Serial (SerialT)
12+import Streamly.Internal.Data.Stream.Serial (SerialT(..))
13−import Streamly.Internal.Data.Stream.StreamK.Type (IsStream)
14
13
15import qualified Streamly.Internal.Data.Stream.Prelude as P
14import qualified Streamly.Internal.Data.Stream.Prelude as P
16−import qualified Streamly.Internal.Data.Stream.Serial as Serial
17import qualified Streamly.Internal.Data.Stream.StreamD as D
15import qualified Streamly.Internal.Data.Stream.StreamD as D
18−import qualified Streamly.Internal.Data.Stream.StreamK as K
19
16
20import Prelude hiding (length, null, last, map, (!!), read, concat)
17import Prelude hiding (length, null, last, map, (!!), read, concat)
21
18
@@ -30,9 +27,9 @@ import Prelude hiding (length, null, last, map, (!!), read, concat)
30-- /Pre-release/
27-- /Pre-release/
31{-# INLINE fromStreamN #-}
28{-# INLINE fromStreamN #-}
32fromStreamN :: (MonadIO m, Prim a) => Int -> SerialT m a -> m (Array a)
29fromStreamN :: (MonadIO m, Prim a) => Int -> SerialT m a -> m (Array a)
33−fromStreamN n m = do
30+fromStreamN n (SerialT m) = do
34 when (n < 0) $ error "writeN: negative write count specified"
31 when (n < 0) $ error "writeN: negative write count specified"
35− A.fromStreamDN n $ D.toStreamD m
32+ A.fromStreamDN n $ D.fromStreamK m
36
33
37-- | Create an 'Array' from a stream. This is useful when we want to create a
34-- | Create an 'Array' from a stream. This is useful when we want to create a
38-- single array from a stream of unknown size. 'writeN' is at least twice
35-- single array from a stream of unknown size. 'writeN' is at least twice
@@ -45,7 +42,7 @@ fromStreamN n m = do
45-- /Pre-release/
42-- /Pre-release/
46{-# INLINE fromStream #-}
43{-# INLINE fromStream #-}
47fromStream :: (MonadIO m, Prim a) => SerialT m a -> m (Array a)
44fromStream :: (MonadIO m, Prim a) => SerialT m a -> m (Array a)
48−fromStream = P.fold A.write
45+fromStream (SerialT m) = P.fold A.write m
49-- write m = A.fromStreamD $ D.toStreamD m
46-- write m = A.fromStreamD $ D.toStreamD m
50
47
51-------------------------------------------------------------------------------
48-------------------------------------------------------------------------------
@@ -56,8 +53,8 @@ fromStream = P.fold A.write
56--
53--
57-- /Pre-release/
54-- /Pre-release/
58{-# INLINE_EARLY toStream #-}
55{-# INLINE_EARLY toStream #-}
59−toStream :: (MonadIO m, K.IsStream t, Prim a) => Array a -> t m a
56+toStream :: (MonadIO m, Prim a) => Array a -> SerialT m a
60−toStream = D.fromStreamD . A.toStreamD
57+toStream = SerialT . D.toStreamK . A.toStreamD
61-- XXX add fallback to StreamK rule
58-- XXX add fallback to StreamK rule
62-- {-# RULES "Streamly.Array.read fallback to StreamK" [1]
59-- {-# RULES "Streamly.Array.read fallback to StreamK" [1]
63-- forall a. S.readK (read a) = K.fromArray a #-}
60-- forall a. S.readK (read a) = K.fromArray a #-}
@@ -66,8 +63,8 @@ toStream = D.fromStreamD . A.toStreamD
66--
63--
67-- /Pre-release/
64-- /Pre-release/
68{-# INLINE_EARLY toStreamRev #-}
65{-# INLINE_EARLY toStreamRev #-}
69−toStreamRev :: (MonadIO m, IsStream t, Prim a) => Array a -> t m a
66+toStreamRev :: (MonadIO m, Prim a) => Array a -> SerialT m a
70−toStreamRev = D.fromStreamD . A.toStreamDRev
67+toStreamRev = SerialT . D.toStreamK . A.toStreamDRev
71-- XXX add fallback to StreamK rule
68-- XXX add fallback to StreamK rule
72-- {-# RULES "Streamly.Array.readRev fallback to StreamK" [1]
69-- {-# RULES "Streamly.Array.readRev fallback to StreamK" [1]
73-- forall a. S.toStreamK (readRev a) = K.revFromArray a #-}
70-- forall a. S.toStreamK (readRev a) = K.revFromArray a #-}
@@ -128,7 +125,7 @@ null arr = length arr == 0
128-- /Pre-release/
125-- /Pre-release/
129{-# INLINE fold #-}
126{-# INLINE fold #-}
130fold :: forall m a b. (MonadIO m, Prim a) => Fold m a b -> Array a -> m b
127fold :: forall m a b. (MonadIO m, Prim a) => Fold m a b -> Array a -> m b
131−fold f arr = P.fold f (toStream arr :: Serial.SerialT m a)
128+fold f arr = P.fold f (getSerialT (toStream arr))
132
129
133-- | Fold an array using a stream fold operation.
130-- | Fold an array using a stream fold operation.
134--
131--
@@ -170,10 +167,11 @@ last arr = readIndex arr (length arr - 1)
170--
167--
171-- /Pre-release/
168-- /Pre-release/
172{-# INLINE concat #-}
169{-# INLINE concat #-}
173−concat :: (IsStream t, MonadIO m, Prim a) => t m (Array a) -> t m a
170+concat :: (MonadIO m, Prim a) => SerialT m (Array a) -> SerialT m a
174-- concat m = D.fromStreamD $ A.flattenArrays (D.toStreamD m)
171-- concat m = D.fromStreamD $ A.flattenArrays (D.toStreamD m)
175-- concat m = D.fromStreamD $ D.concatMap A.toStreamD (D.toStreamD m)
172-- concat m = D.fromStreamD $ D.concatMap A.toStreamD (D.toStreamD m)
173+concat (SerialT m) =
176−concat m = D.fromStreamD $ D.unfoldMany read (D.toStreamD m)
174+ SerialT $ D.toStreamK $ D.unfoldMany read (D.fromStreamK m)
177
175
178-- | Coalesce adjacent arrays in incoming stream to form bigger arrays of a
176-- | Coalesce adjacent arrays in incoming stream to form bigger arrays of a
179-- maximum specified size in bytes.
177-- maximum specified size in bytes.
@@ -182,4 +180,5 @@ concat m = D.fromStreamD $ D.unfoldMany read (D.toStreamD m)
182{-# INLINE compact #-}
180{-# INLINE compact #-}
183compact ::
181compact ::
184 (MonadIO m, Prim a) => Int -> SerialT m (Array a) -> SerialT m (Array a)
182 (MonadIO m, Prim a) => Int -> SerialT m (Array a) -> SerialT m (Array a)
183+compact n (SerialT xs) =
185−compact n xs = D.fromStreamD $ A.packArraysChunksOf n (D.toStreamD xs)
184+ SerialT $ D.toStreamK $ A.packArraysChunksOf n (D.fromStreamK xs)
src/Streamly/Internal/Data/Array/Stream/Foreign.hs+18−17
@@ -72,7 +72,8 @@ import Streamly.Internal.Data.Array.Foreign.Type (Array(..))
72import Streamly.Internal.Data.Fold.Type (Fold(..))
72import Streamly.Internal.Data.Fold.Type (Fold(..))
73import Streamly.Internal.Data.Parser (ParseError(..))
73import Streamly.Internal.Data.Parser (ParseError(..))
74import Streamly.Internal.Data.Stream.Serial (SerialT)
74import Streamly.Internal.Data.Stream.Serial (SerialT)
75−import Streamly.Internal.Data.Stream.StreamK.Type (IsStream)
75+import Streamly.Internal.Data.Stream.IsStream.Type
76+ (IsStream, fromStreamD, toStreamD)
76import Streamly.Internal.Data.SVar (adaptState, defState)
77import Streamly.Internal.Data.SVar (adaptState, defState)
77import Streamly.Internal.Data.Array.Foreign.Mut.Type (memcpy, bytesToElemCount)
78import Streamly.Internal.Data.Array.Foreign.Mut.Type (memcpy, bytesToElemCount)
78import Streamly.Internal.System.IO (mkChunkSizeKB)
79import Streamly.Internal.System.IO (mkChunkSizeKB)
@@ -102,7 +103,7 @@ import qualified Streamly.Internal.Data.Stream.StreamD as D
102{-# INLINE arraysOf #-}
103{-# INLINE arraysOf #-}
103arraysOf :: (IsStream t, MonadIO m, Storable a)
104arraysOf :: (IsStream t, MonadIO m, Storable a)
104 => Int -> t m a -> t m (Array a)
105 => Int -> t m a -> t m (Array a)
105−arraysOf n str = D.fromStreamD $ A.arraysOf n (D.toStreamD str)
106+arraysOf n str = fromStreamD $ A.arraysOf n (toStreamD str)
106
107
107-------------------------------------------------------------------------------
108-------------------------------------------------------------------------------
108-- Append
109-- Append
@@ -121,9 +122,9 @@ arraysOf n str = D.fromStreamD $ A.arraysOf n (D.toStreamD str)
121-- @since 0.7.0
122-- @since 0.7.0
122{-# INLINE concat #-}
123{-# INLINE concat #-}
123concat :: (IsStream t, MonadIO m, Storable a) => t m (Array a) -> t m a
124concat :: (IsStream t, MonadIO m, Storable a) => t m (Array a) -> t m a
124−-- concat m = D.fromStreamD $ A.flattenArrays (D.toStreamD m)
125+-- concat m = fromStreamD $ A.flattenArrays (toStreamD m)
125−-- concat m = D.fromStreamD $ D.concatMap A.toStreamD (D.toStreamD m)
126+-- concat m = fromStreamD $ D.concatMap A.toStreamD (toStreamD m)
126−concat m = D.fromStreamD $ D.unfoldMany A.read (D.toStreamD m)
127+concat m = fromStreamD $ D.unfoldMany A.read (toStreamD m)
127
128
128-- | Convert a stream of arrays into a stream of their elements reversing the
129-- | Convert a stream of arrays into a stream of their elements reversing the
129-- contents of each array before flattening.
130-- contents of each array before flattening.
@@ -133,7 +134,7 @@ concat m = D.fromStreamD $ D.unfoldMany A.read (D.toStreamD m)
133-- @since 0.7.0
134-- @since 0.7.0
134{-# INLINE concatRev #-}
135{-# INLINE concatRev #-}
135concatRev :: (IsStream t, MonadIO m, Storable a) => t m (Array a) -> t m a
136concatRev :: (IsStream t, MonadIO m, Storable a) => t m (Array a) -> t m a
136−concatRev m = D.fromStreamD $ A.flattenArraysRev (D.toStreamD m)
137+concatRev m = fromStreamD $ A.flattenArraysRev (toStreamD m)
137
138
138-------------------------------------------------------------------------------
139-------------------------------------------------------------------------------
139-- Intersperse and append
140-- Intersperse and append
@@ -159,7 +160,7 @@ intercalateSuffix = S.intercalateSuffix A.read
159{-# INLINE interposeSuffix #-}
160{-# INLINE interposeSuffix #-}
160interposeSuffix :: (MonadIO m, IsStream t, Storable a)
161interposeSuffix :: (MonadIO m, IsStream t, Storable a)
161 => a -> t m (Array a) -> t m a
162 => a -> t m (Array a) -> t m a
162−-- interposeSuffix x = D.fromStreamD . A.unlines x . D.toStreamD
163+-- interposeSuffix x = fromStreamD . A.unlines x . toStreamD
163interposeSuffix x = S.interposeSuffix x A.read
164interposeSuffix x = S.interposeSuffix x A.read
164
165
165data FlattenState s a =
166data FlattenState s a =
@@ -220,7 +221,7 @@ lpackArraysChunksOf n fld =
220{-# INLINE compact #-}
221{-# INLINE compact #-}
221compact :: (MonadIO m, Storable a)
222compact :: (MonadIO m, Storable a)
222 => Int -> SerialT m (Array a) -> SerialT m (Array a)
223 => Int -> SerialT m (Array a) -> SerialT m (Array a)
223−compact n xs = D.fromStreamD $ packArraysChunksOf n (D.toStreamD xs)
224+compact n xs = fromStreamD $ packArraysChunksOf n (toStreamD xs)
224
225
225-------------------------------------------------------------------------------
226-------------------------------------------------------------------------------
226-- Split
227-- Split
@@ -294,7 +295,7 @@ splitOn
294 -> t m (Array Word8)
295 -> t m (Array Word8)
295 -> t m (Array Word8)
296 -> t m (Array Word8)
296splitOn byte s =
297splitOn byte s =
297− D.fromStreamD $ D.splitInnerBy (A.breakOn byte) A.spliceTwo $ D.toStreamD s
298+ fromStreamD $ D.splitInnerBy (A.breakOn byte) A.spliceTwo $ toStreamD s
298
299
299{-# INLINE splitOnSuffix #-}
300{-# INLINE splitOnSuffix #-}
300splitOnSuffix
301splitOnSuffix
@@ -302,9 +303,9 @@ splitOnSuffix
302 => Word8
303 => Word8
303 -> t m (Array Word8)
304 -> t m (Array Word8)
304 -> t m (Array Word8)
305 -> t m (Array Word8)
305−-- splitOn byte s = D.fromStreamD $ A.splitOn byte $ D.toStreamD s
306+-- splitOn byte s = fromStreamD $ A.splitOn byte $ toStreamD s
306splitOnSuffix byte s =
307splitOnSuffix byte s =
307− D.fromStreamD $ D.splitInnerBySuffix (A.breakOn byte) A.spliceTwo $ D.toStreamD s
308+ fromStreamD $ D.splitInnerBySuffix (A.breakOn byte) A.spliceTwo $ toStreamD s
308
309
309-------------------------------------------------------------------------------
310-------------------------------------------------------------------------------
310-- Elimination - Running folds
311-- Elimination - Running folds
@@ -362,7 +363,7 @@ fold ::
362 => FL.Fold m a b
363 => FL.Fold m a b
363 -> SerialT m (A.Array a)
364 -> SerialT m (A.Array a)
364 -> m (b, SerialT m (A.Array a))
365 -> m (b, SerialT m (A.Array a))
365−fold f s = fmap D.fromStreamD <$> foldD f (D.toStreamD s)
366+fold f s = fmap fromStreamD <$> foldD f (toStreamD s)
366
367
367-------------------------------------------------------------------------------
368-------------------------------------------------------------------------------
368-- Fold to a single Array
369-- Fold to a single Array
@@ -613,7 +614,7 @@ parse ::
613 => PRD.Parser m a b
614 => PRD.Parser m a b
614 -> SerialT m (A.Array a)
615 -> SerialT m (A.Array a)
615 -> m (b, SerialT m (A.Array a))
616 -> m (b, SerialT m (A.Array a))
616−parse p s = fmap D.fromStreamD <$> parseD p (D.toStreamD s)
617+parse p s = fmap fromStreamD <$> parseD p (toStreamD s)
617
618
618-------------------------------------------------------------------------------
619-------------------------------------------------------------------------------
619-- Elimination - Running Array Folds and parsers
620-- Elimination - Running Array Folds and parsers
@@ -695,7 +696,7 @@ parseArr ::
695 => ASF.Parser m a b
696 => ASF.Parser m a b
696 -> SerialT m (A.Array a)
697 -> SerialT m (A.Array a)
697 -> m (b, SerialT m (A.Array a))
698 -> m (b, SerialT m (A.Array a))
698−parseArr p s = fmap D.fromStreamD <$> parseD p (D.toStreamD s)
699+parseArr p s = fmap fromStreamD <$> parseD p (toStreamD s)
699-}
700-}
700
701
701-- | Fold an array stream using the supplied array stream 'Fold'.
702-- | Fold an array stream using the supplied array stream 'Fold'.
@@ -705,7 +706,7 @@ parseArr p s = fmap D.fromStreamD <$> parseD p (D.toStreamD s)
705{-# INLINE foldArr #-}
706{-# INLINE foldArr #-}
706foldArr :: (MonadIO m, MonadThrow m, Storable a) =>
707foldArr :: (MonadIO m, MonadThrow m, Storable a) =>
707 ASF.Fold m a b -> SerialT m (A.Array a) -> m b
708 ASF.Fold m a b -> SerialT m (A.Array a) -> m b
708−foldArr (ASF.Fold p) s = fst <$> parseArrD p (D.toStreamD s)
709+foldArr (ASF.Fold p) s = fst <$> parseArrD p (toStreamD s)
709
710
710-- | Like 'fold' but also returns the remaining stream.
711-- | Like 'fold' but also returns the remaining stream.
711--
712--
@@ -714,7 +715,7 @@ foldArr (ASF.Fold p) s = fst <$> parseArrD p (D.toStreamD s)
714{-# INLINE foldArr_ #-}
715{-# INLINE foldArr_ #-}
715foldArr_ :: (MonadIO m, MonadThrow m, Storable a) =>
716foldArr_ :: (MonadIO m, MonadThrow m, Storable a) =>
716 ASF.Fold m a b -> SerialT m (A.Array a) -> m (b, SerialT m (A.Array a))
717 ASF.Fold m a b -> SerialT m (A.Array a) -> m (b, SerialT m (A.Array a))
717−foldArr_ (ASF.Fold p) s = second D.fromStreamD <$> parseArrD p (D.toStreamD s)
718+foldArr_ (ASF.Fold p) s = second fromStreamD <$> parseArrD p (toStreamD s)
718
719
719{-# ANN type ParseChunksState Fuse #-}
720{-# ANN type ParseChunksState Fuse #-}
720data ParseChunksState x inpBuf st pst =
721data ParseChunksState x inpBuf st pst =
@@ -856,4 +857,4 @@ foldArrMany
856 => ASF.Fold m a b
857 => ASF.Fold m a b
857 -> t m (Array a)
858 -> t m (Array a)
858 -> t m b
859 -> t m b
859−foldArrMany p m = D.fromStreamD $ foldArrManyD p (D.toStreamD m)
860+foldArrMany p m = fromStreamD $ foldArrManyD p (toStreamD m)
src/Streamly/Internal/Data/Array/Stream/Mut/Foreign.hs+10−7
@@ -32,8 +32,9 @@ import Data.Bifunctor (first)
32import Foreign.Storable (Storable(..))
32import Foreign.Storable (Storable(..))
33import Streamly.Internal.Data.Array.Foreign.Mut.Type (Array(..))
33import Streamly.Internal.Data.Array.Foreign.Mut.Type (Array(..))
34import Streamly.Internal.Data.Fold.Type (Fold(..))
34import Streamly.Internal.Data.Fold.Type (Fold(..))
35−import Streamly.Internal.Data.Stream.Serial (SerialT)
35+import Streamly.Internal.Data.Stream.Serial (SerialT(..))
36−import Streamly.Internal.Data.Stream.StreamK.Type (IsStream)
36+import Streamly.Internal.Data.Stream.IsStream.Type
37+ (IsStream, fromStreamD, toStreamD)
37import Streamly.Internal.Data.Tuple.Strict (Tuple'(..))
38import Streamly.Internal.Data.Tuple.Strict (Tuple'(..))
38
39
39import qualified Streamly.Internal.Data.Array.Foreign.Mut.Type as MArray
40import qualified Streamly.Internal.Data.Array.Foreign.Mut.Type as MArray
@@ -51,7 +52,7 @@ import qualified Streamly.Internal.Data.Stream.StreamD as D
51{-# INLINE arraysOf #-}
52{-# INLINE arraysOf #-}
52arraysOf :: (IsStream t, MonadIO m, Storable a)
53arraysOf :: (IsStream t, MonadIO m, Storable a)
53 => Int -> t m a -> t m (Array a)
54 => Int -> t m a -> t m (Array a)
54−arraysOf n = D.fromStreamD . MArray.arraysOf n . D.toStreamD
55+arraysOf n = fromStreamD . MArray.arraysOf n . toStreamD
55
56
56-------------------------------------------------------------------------------
57-------------------------------------------------------------------------------
57-- Compact
58-- Compact
@@ -190,7 +191,8 @@ lpackArraysChunksOf n (Fold step1 initial1 extract1) =
190{-# INLINE compact #-}
191{-# INLINE compact #-}
191compact :: (MonadIO m, Storable a)
192compact :: (MonadIO m, Storable a)
192 => Int -> SerialT m (Array a) -> SerialT m (Array a)
193 => Int -> SerialT m (Array a) -> SerialT m (Array a)
194+compact n (SerialT xs) =
193−compact n xs = D.fromStreamD $ packArraysChunksOf n (D.toStreamD xs)
195+ SerialT $ D.toStreamK $ packArraysChunksOf n (D.fromStreamK xs)
194
196
195-- See lpackArraysChunksOf/packArraysChunksOf to implement this.
197-- See lpackArraysChunksOf/packArraysChunksOf to implement this.
196--
198--
@@ -212,7 +214,8 @@ compactLEFold = undefined
212-- /Internal/
214-- /Internal/
213compactLE :: (MonadIO m {-, Storable a-}) =>
215compactLE :: (MonadIO m {-, Storable a-}) =>
214 Int -> SerialT m (Array a) -> SerialT m (Array a)
216 Int -> SerialT m (Array a) -> SerialT m (Array a)
217+compactLE n (SerialT xs) =
215−compactLE n xs = D.fromStreamD $ D.foldMany (compactLEFold n) (D.toStreamD xs)
218+ SerialT $ D.toStreamK $ D.foldMany (compactLEFold n) (D.fromStreamK xs)
216
219
217-- | Like 'compactLE' but generates arrays of exactly equal to the size
220-- | Like 'compactLE' but generates arrays of exactly equal to the size
218-- specified except for the last array in the stream which could be shorter.
221-- specified except for the last array in the stream which could be shorter.
@@ -222,7 +225,7 @@ compactLE n xs = D.fromStreamD $ D.foldMany (compactLEFold n) (D.toStreamD xs)
222compactEQ :: -- (MonadIO m, Storable a) =>
225compactEQ :: -- (MonadIO m, Storable a) =>
223 Int -> SerialT m (Array a) -> SerialT m (Array a)
226 Int -> SerialT m (Array a) -> SerialT m (Array a)
224compactEQ _n _xs = undefined
227compactEQ _n _xs = undefined
225− -- D.fromStreamD $ D.foldMany (compactEQFold n) (D.toStreamD xs)
228+ -- IsStream.fromStreamD $ D.foldMany (compactEQFold n) (IsStream.toStreamD xs)
226
229
227-- | Like 'compactLE' but generates arrays of size greater than or equal to the
230-- | Like 'compactLE' but generates arrays of size greater than or equal to the
228-- specified except for the last array in the stream which could be shorter.
231-- specified except for the last array in the stream which could be shorter.
@@ -232,4 +235,4 @@ compactEQ _n _xs = undefined
232compactGE :: -- (MonadIO m, Storable a) =>
235compactGE :: -- (MonadIO m, Storable a) =>
233 Int -> SerialT m (Array a) -> SerialT m (Array a)
236 Int -> SerialT m (Array a) -> SerialT m (Array a)
234compactGE _n _xs = undefined
237compactGE _n _xs = undefined
235− -- D.fromStreamD $ D.foldMany (compactGEFold n) (D.toStreamD xs)
238+ -- IsStream.fromStreamD $ D.foldMany (compactGEFold n) (IsStream.toStreamD xs)
src/Streamly/Internal/Data/Fold.hs+4−6
@@ -143,7 +143,6 @@ module Streamly.Internal.Data.Fold
143
143
144 -- ** Trimming
144 -- ** Trimming
145 , take
145 , take
146− , takeInterval
147
146
148 -- By elements
147 -- By elements
149 , takeEndBy
148 , takeEndBy
@@ -215,7 +214,6 @@ module Streamly.Internal.Data.Fold
215
214
216 -- ** Splitting
215 -- ** Splitting
217 , many
216 , many
218− , intervalsOf
219 , chunksOf
217 , chunksOf
220 , chunksBetween
218 , chunksBetween
221
219
@@ -252,12 +250,12 @@ import Streamly.Internal.Data.Either.Strict
252 (Either'(..), fromLeft', fromRight', isLeft', isRight')
250 (Either'(..), fromLeft', fromRight', isLeft', isRight')
253import Streamly.Internal.Data.Pipe.Type (Pipe (..), PipeState(..))
251import Streamly.Internal.Data.Pipe.Type (Pipe (..), PipeState(..))
254import Streamly.Internal.Data.Tuple.Strict (Tuple'(..), Tuple3'(..))
252import Streamly.Internal.Data.Tuple.Strict (Tuple'(..), Tuple3'(..))
255−import Streamly.Internal.Data.Stream.Serial (SerialT)
253+import Streamly.Internal.Data.Stream.Serial (SerialT(..))
256
254
257import qualified Data.Map.Strict as Map
255import qualified Data.Map.Strict as Map
258import qualified Streamly.Internal.Data.Pipe.Type as Pipe
256import qualified Streamly.Internal.Data.Pipe.Type as Pipe
259-- import qualified Streamly.Internal.Data.Stream.IsStream.Enumeration as Stream
257-- import qualified Streamly.Internal.Data.Stream.IsStream.Enumeration as Stream
260−import qualified Streamly.Internal.Data.Stream.StreamK as K
258+import qualified Streamly.Internal.Data.Stream.StreamK.Type as K
261import qualified Prelude
259import qualified Prelude
262
260
263import Prelude hiding
261import Prelude hiding
@@ -1690,7 +1688,7 @@ chunksBetween _low _high _f1 _f2 = undefined
1690-- /Pre-release/
1688-- /Pre-release/
1691{-# INLINE toStream #-}
1689{-# INLINE toStream #-}
1692toStream :: Monad m => Fold m a (SerialT Identity a)
1690toStream :: Monad m => Fold m a (SerialT Identity a)
1693−toStream = foldr K.cons K.nil
1691+toStream = fmap SerialT $ foldr K.cons K.nil
1694
1692
1695-- This is more efficient than 'toStream'. toStream is exactly the same as
1693-- This is more efficient than 'toStream'. toStream is exactly the same as
1696-- reversing the stream after toStreamRev.
1694-- reversing the stream after toStreamRev.
@@ -1708,4 +1706,4 @@ toStream = foldr K.cons K.nil
1708-- xn : ... : x2 : x1 : []
1706-- xn : ... : x2 : x1 : []
1709{-# INLINABLE toStreamRev #-}
1707{-# INLINABLE toStreamRev #-}
1710toStreamRev :: Monad m => Fold m a (SerialT Identity a)
1708toStreamRev :: Monad m => Fold m a (SerialT Identity a)
1711−toStreamRev = foldl' (flip K.cons) K.nil
1709+toStreamRev = fmap SerialT $ foldl' (flip K.cons) K.nil
src/Streamly/Internal/Data/Fold/Async.hsnew file+120
@@ -0,0 +1,120 @@
1+-- |
2+-- Module : Streamly.Internal.Data.Fold.Async
3+-- Copyright : (c) 2019 Composewell Technologies
4+-- License : BSD-3-Clause
5+-- Maintainer : streamly@composewell.com
6+-- Stability : experimental
7+-- Portability : GHC
8+--
9+module Streamly.Internal.Data.Fold.Async
10+ (
11+ -- * Trimming
12+ takeInterval
13+
14+ -- * Splitting
15+ , intervalsOf
16+ )
17+where
18+
19+import Control.Concurrent (threadDelay, forkIO, killThread)
20+import Control.Concurrent.MVar (MVar, newMVar, swapMVar, readMVar)
21+import Control.Exception (SomeException(..), catch, mask)
22+import Control.Monad (void)
23+import Control.Monad.IO.Class (MonadIO(..))
24+import Control.Monad.Trans.Control (control)
25+import Streamly.Internal.Control.Concurrent (MonadAsync)
26+import Streamly.Internal.Data.Tuple.Strict (Tuple3'(..))
27+
28+import Streamly.Internal.Data.Fold.Type
29+
30+-- $setup
31+-- >>> :m
32+-- >>> import qualified Streamly.Prelude as Stream
33+-- >>> import qualified Streamly.Data.Fold as Fold
34+-- >>> import qualified Streamly.Internal.Data.Fold.Async as Fold
35+
36+-- XXX We can use asyncClock here. A parser can be used to return an input that
37+-- arrives after the timeout.
38+-- XXX If n is 0 return immediately in initial.
39+-- XXX we should probably discard the input received after the timeout like
40+-- takeEndBy_.
41+--
42+-- | @takeInterval n fold@ uses @fold@ to fold the input items arriving within
43+-- a window of first @n@ seconds.
44+--
45+-- >>> input = Stream.delay 0.1 $ Stream.fromList [1..]
46+-- >>> Stream.fold (Fold.takeInterval 1.0 Fold.toList) input
47+-- [1,2,3,4,5,6,7,8,9,10,11]
48+--
49+-- Stops when @fold@ stops or when the timeout occurs. Note that the fold needs
50+-- an input after the timeout to stop. For example, if no input is pushed to
51+-- the fold until one hour after the timeout had occurred, then the fold will
52+-- be done only after consuming that input.
53+--
54+-- /Pre-release/
55+--
56+{-# INLINE takeInterval #-}
57+takeInterval :: MonadAsync m => Double -> Fold m a b -> Fold m a b
58+takeInterval n (Fold step initial done) = Fold step' initial' done'
59+
60+ where
61+
62+ initial' = do
63+ res <- initial
64+ case res of
65+ Partial s -> do
66+ mv <- liftIO $ newMVar False
67+ t <-
68+ control $ \run ->
69+ mask $ \restore -> do
70+ tid <-
71+ forkIO
72+ $ catch
73+ (restore $ void $ run (timerThread mv))
74+ (handleChildException mv)
75+ run (return tid)
76+ return $ Partial $ Tuple3' s mv t
77+ Done b -> return $ Done b
78+
79+ step' (Tuple3' s mv t) a = do
80+ val <- liftIO $ readMVar mv
81+ if val
82+ then do
83+ res <- step s a
84+ case res of
85+ Partial sres -> Done <$> done sres
86+ Done bres -> return $ Done bres
87+ else do
88+ res <- step s a
89+ case res of
90+ Partial fs -> return $ Partial $ Tuple3' fs mv t
91+ Done b -> liftIO (killThread t) >> return (Done b)
92+
93+ done' (Tuple3' s _ _) = done s
94+
95+ timerThread mv = do
96+ liftIO $ threadDelay (round $ n * 1000000)
97+ -- Use IORef + CAS? instead of MVar since its a Bool?
98+ liftIO $ void $ swapMVar mv True
99+
100+ handleChildException :: MVar Bool -> SomeException -> IO ()
101+ handleChildException mv _ = void $ swapMVar mv True
102+
103+-- For example, we can copy and distribute a stream to multiple folds where
104+-- each fold can group the input differently e.g. by one second, one minute and
105+-- one hour windows respectively and fold each resulting stream of folds.
106+
107+-- | Group the input stream into windows of n second each using the first fold
108+-- and then fold the resulting groups using the second fold.
109+--
110+-- >>> intervals = Fold.intervalsOf 0.5 Fold.toList Fold.toList
111+-- >>> Stream.fold intervals $ Stream.delay 0.2 $ Stream.fromList [1..10]
112+-- [[1,2,3,4],[5,6,7],[8,9,10]]
113+--
114+-- > intervalsOf n split = many (takeInterval n split)
115+--
116+-- /Pre-release/
117+--
118+{-# INLINE intervalsOf #-}
119+intervalsOf :: MonadAsync m => Double -> Fold m a b -> Fold m b c -> Fold m a c
120+intervalsOf n split = many (takeInterval n split)
src/Streamly/Internal/Data/Fold/Type.hs+1−94
@@ -228,7 +228,6 @@ module Streamly.Internal.Data.Fold.Type
228
228
229 -- ** Trimming
229 -- ** Trimming
230 , take
230 , take
231− , takeInterval
232
231
233 -- ** Serial Append
232 -- ** Serial Append
234 , serialWith
233 , serialWith
@@ -248,7 +247,6 @@ module Streamly.Internal.Data.Fold.Type
248 , many
247 , many
249 , manyPost
248 , manyPost
250 , chunksOf
249 , chunksOf
251− , intervalsOf
252
250
253 -- ** Nesting
251 -- ** Nesting
254 , concatMap
252 , concatMap
@@ -265,18 +263,12 @@ module Streamly.Internal.Data.Fold.Type
265 )
263 )
266where
264where
267
265
268−import Control.Monad (void, (>=>))
266+import Control.Monad ((>=>))
269−import Control.Concurrent (threadDelay, forkIO, killThread)
270−import Control.Concurrent.MVar (MVar, newMVar, swapMVar, readMVar)
271−import Control.Exception (SomeException(..), catch, mask)
272−import Control.Monad.IO.Class (MonadIO(..))
273−import Control.Monad.Trans.Control (control)
274import Data.Bifunctor (Bifunctor(..))
267import Data.Bifunctor (Bifunctor(..))
275import Data.Maybe (isJust, fromJust)
268import Data.Maybe (isJust, fromJust)
276import Fusion.Plugin.Types (Fuse(..))
269import Fusion.Plugin.Types (Fuse(..))
277import Streamly.Internal.Data.Maybe.Strict (Maybe'(..), toMaybe)
270import Streamly.Internal.Data.Maybe.Strict (Maybe'(..), toMaybe)
278import Streamly.Internal.Data.Tuple.Strict (Tuple'(..), Tuple3'(..))
271import Streamly.Internal.Data.Tuple.Strict (Tuple'(..), Tuple3'(..))
279−import Streamly.Internal.Control.Concurrent (MonadAsync)
280
272
281import Prelude hiding (concatMap, filter, foldr, map, take)
273import Prelude hiding (concatMap, filter, foldr, map, take)
282
274
@@ -1358,88 +1350,3 @@ chunksOf2 n (Fold step1 initial1 extract1) (Fold2 step2 inject2 extract2) =
1358 else extract1 r1 >>= step2 r2 >>= loopUntilPartial
1350 else extract1 r1 >>= step2 r2 >>= loopUntilPartial
1359
1351
1360 extract' (Tuple3' _ r1 r2) = extract1 r1 >>= step2 r2 >>= extract2
1352 extract' (Tuple3' _ r1 r2) = extract1 r1 >>= step2 r2 >>= extract2
1361−
1362−-- XXX We can use asyncClock here. A parser can be used to return an input that
1363−-- arrives after the timeout.
1364−-- XXX If n is 0 return immediately in initial.
1365−-- XXX we should probably discard the input received after the timeout like
1366−-- takeEndBy_.
1367−--
1368−-- | @takeInterval n fold@ uses @fold@ to fold the input items arriving within
1369−-- a window of first @n@ seconds.
1370−--
1371−-- >>> Stream.fold (Fold.takeInterval 1.0 Fold.toList) $ Stream.delay 0.1 $ Stream.fromList [1..]
1372−-- [1,2,3,4,5,6,7,8,9,10,11]
1373−--
1374−-- Stops when @fold@ stops or when the timeout occurs. Note that the fold needs
1375−-- an input after the timeout to stop. For example, if no input is pushed to
1376−-- the fold until one hour after the timeout had occurred, then the fold will
1377−-- be done only after consuming that input.
1378−--
1379−-- /Pre-release/
1380−--
1381−{-# INLINE takeInterval #-}
1382−takeInterval :: MonadAsync m => Double -> Fold m a b -> Fold m a b
1383−takeInterval n (Fold step initial done) = Fold step' initial' done'
1384−
1385− where
1386−
1387− initial' = do
1388− res <- initial
1389− case res of
1390− Partial s -> do
1391− mv <- liftIO $ newMVar False
1392− t <-
1393− control $ \run ->
1394− mask $ \restore -> do
1395− tid <-
1396− forkIO
1397− $ catch
1398− (restore $ void $ run (timerThread mv))
1399− (handleChildException mv)
1400− run (return tid)
1401− return $ Partial $ Tuple3' s mv t
1402− Done b -> return $ Done b
1403−
1404− step' (Tuple3' s mv t) a = do
1405− val <- liftIO $ readMVar mv
1406− if val
1407− then do
1408− res <- step s a
1409− case res of
1410− Partial sres -> Done <$> done sres
1411− Done bres -> return $ Done bres
1412− else do
1413− res <- step s a
1414− case res of
1415− Partial fs -> return $ Partial $ Tuple3' fs mv t
1416− Done b -> liftIO (killThread t) >> return (Done b)
1417−
1418− done' (Tuple3' s _ _) = done s
1419−
1420− timerThread mv = do
1421− liftIO $ threadDelay (round $ n * 1000000)
1422− -- Use IORef + CAS? instead of MVar since its a Bool?
1423− liftIO $ void $ swapMVar mv True
1424−
1425− handleChildException :: MVar Bool -> SomeException -> IO ()
1426− handleChildException mv _ = void $ swapMVar mv True
1427−
1428−-- For example, we can copy and distribute a stream to multiple folds where
1429−-- each fold can group the input differently e.g. by one second, one minute and
1430−-- one hour windows respectively and fold each resulting stream of folds.
1431−
1432−-- | Group the input stream into windows of n second each using the first fold
1433−-- and then fold the resulting groups using the second fold.
1434−--
1435−-- >>> intervals = Fold.intervalsOf 0.5 Fold.toList Fold.toList
1436−-- >>> Stream.fold intervals $ Stream.delay 0.2 $ Stream.fromList [1..10]
1437−-- [[1,2,3,4],[5,6,7],[8,9,10]]
1438−--
1439−-- > intervalsOf n split = many (takeInterval n split)
1440−--
1441−-- /Pre-release/
1442−--
1443−{-# INLINE intervalsOf #-}
1444−intervalsOf :: MonadAsync m => Double -> Fold m a b -> Fold m b c -> Fold m a c
1445−intervalsOf n split = many (takeInterval n split)
src/Streamly/Internal/Data/IORef/Prim.hs−10
@@ -35,7 +35,6 @@ module Streamly.Internal.Data.IORef.Prim
35
35
36 -- * Read
36 -- * Read
37 , readIORef
37 , readIORef
38− , toStream
39 , toStreamD
38 , toStreamD
40 )
39 )
41where
40where
@@ -48,7 +47,6 @@ import Data.Primitive.Types (Prim, sizeOf#, readByteArray#, writeByteArray#)
48import GHC.Exts (MutableByteArray#, newByteArray#, RealWorld)
47import GHC.Exts (MutableByteArray#, newByteArray#, RealWorld)
49import GHC.IO (IO(..))
48import GHC.IO (IO(..))
50
49
51−import qualified Streamly.Internal.Data.Stream.StreamK.Type as K
52import qualified Streamly.Internal.Data.Stream.StreamD.Type as D
50import qualified Streamly.Internal.Data.Stream.StreamD.Type as D
53
51
54-- | An 'IORef' holds a single 'Prim' value.
52-- | An 'IORef' holds a single 'Prim' value.
@@ -100,11 +98,3 @@ toStreamD var = D.Stream step ()
100
98
101 {-# INLINE_LATE step #-}
99 {-# INLINE_LATE step #-}
102 step _ () = liftIO (readIORef var) >>= \x -> return $ D.Yield x ()
100 step _ () = liftIO (readIORef var) >>= \x -> return $ D.Yield x ()
103−
104−-- | Construct a stream by reading a 'Prim' 'IORef' repeatedly.
105−--
106−-- /Pre-release/
107−--
108−{-# INLINE toStream #-}
109−toStream :: (K.IsStream t, MonadIO m, Prim a) => IORef a -> t m a
110−toStream = D.fromStreamD . toStreamD
src/Streamly/Internal/Data/List.hs+22−17
@@ -72,11 +72,11 @@ import Data.Semigroup (Semigroup(..))
72#endif
72#endif
73import GHC.Exts (IsList(..), IsString(..))
73import GHC.Exts (IsList(..), IsString(..))
74
74
75−import Streamly.Internal.Data.Stream.Serial (SerialT)
75+import Streamly.Internal.Data.Stream.Serial (SerialT(..))
76−import Streamly.Internal.Data.Stream.Zip (ZipSerialM)
76+import Streamly.Internal.Data.Stream.Zip (ZipSerialM(..))
77
77
78−import qualified Streamly.Internal.Data.Stream.IsStream as Stream
78+import qualified Streamly.Internal.Data.Stream.Serial as Serial
79−import qualified Streamly.Internal.Data.Stream.StreamK as K
79+import qualified Streamly.Internal.Data.Stream.StreamK.Type as K
80
80
81-- We implement list as a newtype instead of a type synonym to make type
81-- We implement list as a newtype instead of a type synonym to make type
82-- inference easier when using -XOverloadedLists and -XOverloadedStrings. When
82-- inference easier when using -XOverloadedLists and -XOverloadedStrings. When
@@ -103,15 +103,15 @@ newtype List a = List { toSerial :: SerialT Identity a }
103
103
104instance (a ~ Char) => IsString (List a) where
104instance (a ~ Char) => IsString (List a) where
105 {-# INLINE fromString #-}
105 {-# INLINE fromString #-}
106− fromString = List . Stream.fromList
106+ fromString = List . fromList
107
107
108-- GHC versions 8.0 and below cannot derive IsList
108-- GHC versions 8.0 and below cannot derive IsList
109instance IsList (List a) where
109instance IsList (List a) where
110 type (Item (List a)) = a
110 type (Item (List a)) = a
111 {-# INLINE fromList #-}
111 {-# INLINE fromList #-}
112− fromList = List . Stream.fromList
112+ fromList = List . fromList
113 {-# INLINE toList #-}
113 {-# INLINE toList #-}
114− toList = runIdentity . Stream.toList . toSerial
114+ toList = toList . toSerial
115
115
116------------------------------------------------------------------------------
116------------------------------------------------------------------------------
117-- Patterns
117-- Patterns
@@ -128,8 +128,8 @@ instance IsList (List a) where
128--
128--
129-- @since 0.6.0
129-- @since 0.6.0
130pattern Nil :: List a
130pattern Nil :: List a
131−pattern Nil <- (runIdentity . K.null . toSerial -> True) where
131+pattern Nil <- (runIdentity . K.null . getSerialT . toSerial -> True) where
132− Nil = List K.nil
132+ Nil = List $ SerialT K.nil
133
133
134infixr 5 `Cons`
134infixr 5 `Cons`
135
135
@@ -139,9 +139,14 @@ infixr 5 `Cons`
139-- @since 0.6.0
139-- @since 0.6.0
140pattern Cons :: a -> List a -> List a
140pattern Cons :: a -> List a -> List a
141pattern Cons x xs <-
141pattern Cons x xs <-
142+ (fmap (second (List . SerialT))
142− (fmap (second List) . runIdentity . K.uncons . toSerial
143+ . runIdentity . K.uncons . getSerialT . toSerial
143− -> Just (x, xs)) where
144+ -> Just (x, xs)
145+ )
146+
147+ where
148+
144− Cons x xs = List $ K.cons x (toSerial xs)
149+ Cons x xs = List $ Serial.cons x (toSerial xs)
145
150
146#if __GLASGOW_HASKELL__ >= 802
151#if __GLASGOW_HASKELL__ >= 802
147{-# COMPLETE Nil, Cons #-}
152{-# COMPLETE Nil, Cons #-}
@@ -165,24 +170,24 @@ newtype ZipList a = ZipList { toZipSerial :: ZipSerialM Identity a }
165
170
166instance (a ~ Char) => IsString (ZipList a) where
171instance (a ~ Char) => IsString (ZipList a) where
167 {-# INLINE fromString #-}
172 {-# INLINE fromString #-}
168− fromString = ZipList . Stream.fromList
173+ fromString = ZipList . fromList
169
174
170-- GHC versions 8.0 and below cannot derive IsList
175-- GHC versions 8.0 and below cannot derive IsList
171instance IsList (ZipList a) where
176instance IsList (ZipList a) where
172 type (Item (ZipList a)) = a
177 type (Item (ZipList a)) = a
173 {-# INLINE fromList #-}
178 {-# INLINE fromList #-}
174− fromList = ZipList . Stream.fromList
179+ fromList = ZipList . fromList
175 {-# INLINE toList #-}
180 {-# INLINE toList #-}
176− toList = runIdentity . Stream.toList . K.adapt . toZipSerial
181+ toList = toList . toZipSerial
177
182
178-- | Convert a 'ZipList' to a regular 'List'
183-- | Convert a 'ZipList' to a regular 'List'
179--
184--
180-- @since 0.6.0
185-- @since 0.6.0
181fromZipList :: ZipList a -> List a
186fromZipList :: ZipList a -> List a
182−fromZipList = List . K.adapt . toZipSerial
187+fromZipList (ZipList zs) = List $ SerialT $ getZipSerialM zs
183
188
184-- | Convert a regular 'List' to a 'ZipList'
189-- | Convert a regular 'List' to a 'ZipList'
185--
190--
186-- @since 0.6.0
191-- @since 0.6.0
187toZipList :: List a -> ZipList a
192toZipList :: List a -> ZipList a
188−toZipList = ZipList . K.adapt . toSerial
193+toZipList = ZipList . ZipSerialM . getSerialT . toSerial
src/Streamly/Internal/Data/SmallArray.hs+7−8
@@ -53,8 +53,7 @@ import Streamly.Internal.Data.SmallArray.Type
53import Streamly.Internal.Data.Tuple.Strict (Tuple'(..))
53import Streamly.Internal.Data.Tuple.Strict (Tuple'(..))
54import Streamly.Internal.Data.Unfold.Type (Unfold(..))
54import Streamly.Internal.Data.Unfold.Type (Unfold(..))
55import Streamly.Internal.Data.Fold.Type (Fold(..))
55import Streamly.Internal.Data.Fold.Type (Fold(..))
56−import Streamly.Internal.Data.Stream.StreamK.Type (IsStream)
56+import Streamly.Internal.Data.Stream.Serial (SerialT(..))
57−import Streamly.Internal.Data.Stream.Serial (SerialT)
58
57
59import qualified Streamly.Internal.Data.Stream.StreamD as D
58import qualified Streamly.Internal.Data.Stream.StreamD as D
60import qualified Streamly.Internal.Data.Fold.Type as FL
59import qualified Streamly.Internal.Data.Fold.Type as FL
@@ -155,17 +154,17 @@ instance NFData a => NFData (SmallArray a) where
155-- For optimal performance use this with @n@ <= 128.
154-- For optimal performance use this with @n@ <= 128.
156{-# INLINE fromStreamN #-}
155{-# INLINE fromStreamN #-}
157fromStreamN :: MonadIO m => Int -> SerialT m a -> m (SmallArray a)
156fromStreamN :: MonadIO m => Int -> SerialT m a -> m (SmallArray a)
158−fromStreamN n m = do
157+fromStreamN n (SerialT m) = do
159 when (n < 0) $ error "fromStreamN: negative write count specified"
158 when (n < 0) $ error "fromStreamN: negative write count specified"
160− fromStreamDN n $ D.toStreamD m
159+ fromStreamDN n $ D.fromStreamK m
161
160
162{-# INLINE_EARLY toStream #-}
161{-# INLINE_EARLY toStream #-}
163−toStream :: (Monad m, IsStream t) => SmallArray a -> t m a
162+toStream :: Monad m => SmallArray a -> SerialT m a
164−toStream = D.fromStreamD . toStreamD
163+toStream = SerialT . D.toStreamK . toStreamD
165
164
166{-# INLINE_EARLY toStreamRev #-}
165{-# INLINE_EARLY toStreamRev #-}
167−toStreamRev :: (Monad m, IsStream t) => SmallArray a -> t m a
166+toStreamRev :: Monad m => SmallArray a -> SerialT m a
168−toStreamRev = D.fromStreamD . toStreamDRev
167+toStreamRev = SerialT . D.toStreamK . toStreamDRev
169
168
170{-# INLINE fold #-}
169{-# INLINE fold #-}
171fold :: Monad m => Fold m a b -> SmallArray a -> m b
170fold :: Monad m => Fold m a b -> SmallArray a -> m b
src/Streamly/Internal/Data/Stream/Ahead.hs+48−101
@@ -22,10 +22,10 @@
22--
22--
23module Streamly.Internal.Data.Stream.Ahead
23module Streamly.Internal.Data.Stream.Ahead
24 (
24 (
25− AheadT
25+ AheadT(..)
26 , Ahead
26 , Ahead
27− , fromAhead
27+ , aheadK
28− , ahead
28+ , consM
29 )
29 )
30where
30where
31
31
@@ -52,10 +52,9 @@ import qualified Data.Heap as H
52
52
53import Streamly.Internal.Control.Concurrent
53import Streamly.Internal.Control.Concurrent
54 (MonadAsync, RunInIO(..), captureMonadState)
54 (MonadAsync, RunInIO(..), captureMonadState)
55−import Streamly.Internal.Data.Stream.StreamK.Type
55+import Streamly.Internal.Data.Stream.Serial (SerialT(..))
56− (IsStream(..), Stream, mkStream, foldStream, foldStreamShared)
56+import Streamly.Internal.Data.Stream.StreamK.Type (Stream)
57
57
58−import qualified Streamly.Internal.Data.Stream.StreamK as K (withLocal)
59import qualified Streamly.Internal.Data.Stream.StreamK.Type as K
58import qualified Streamly.Internal.Data.Stream.StreamK.Type as K
60import qualified Streamly.Internal.Data.Stream.StreamD.Type as D
59import qualified Streamly.Internal.Data.Stream.StreamD.Type as D
61
60
@@ -321,7 +320,7 @@ processHeap q heap st sv winfo entry sno stopping = loopHeap sno entry
321 let stop = do
320 let stop = do
322 liftIO (incrementYieldLimit sv)
321 liftIO (incrementYieldLimit sv)
323 nextHeap seqNo
322 nextHeap seqNo
324− foldStreamShared st
323+ K.foldStreamShared st
325 (yieldStreamFromHeap seqNo)
324 (yieldStreamFromHeap seqNo)
326 (singleStreamFromHeap seqNo)
325 (singleStreamFromHeap seqNo)
327 stop
326 stop
@@ -380,7 +379,7 @@ processWithoutToken q heap st sv winfo m seqNo = do
380 mrun = runInIO $ svarMrun sv
379 mrun = runInIO $ svarMrun sv
381
380
382 r <- liftIO $ mrun $
381 r <- liftIO $ mrun $
383− foldStreamShared st
382+ K.foldStreamShared st
384 (\a r -> do
383 (\a r -> do
385 runIn <- captureMonadState
384 runIn <- captureMonadState
386 toHeap $ AheadEntryStream (runIn, K.cons a r))
385 toHeap $ AheadEntryStream (runIn, K.cons a r))
@@ -451,7 +450,7 @@ processWithToken q heap st sv winfo action sno = do
451 mrun = runInIO $ svarMrun sv
450 mrun = runInIO $ svarMrun sv
452
451
453 r <- liftIO $ mrun $
452 r <- liftIO $ mrun $
454− foldStreamShared st (yieldOutput sno) (singleOutput sno) stop action
453+ K.foldStreamShared st (yieldOutput sno) (singleOutput sno) stop action
455
454
456 res <- restoreM r
455 res <- restoreM r
457 case res of
456 case res of
@@ -479,7 +478,7 @@ processWithToken q heap st sv winfo action sno = do
479 let stop = do
478 let stop = do
480 liftIO (incrementYieldLimit sv)
479 liftIO (incrementYieldLimit sv)
481 return $ TokenContinue (seqNo + 1)
480 return $ TokenContinue (seqNo + 1)
482− foldStreamShared st
481+ K.foldStreamShared st
483 (yieldOutput seqNo)
482 (yieldOutput seqNo)
484 (singleOutput seqNo)
483 (singleOutput seqNo)
485 stop
484 stop
@@ -513,7 +512,7 @@ processWithToken q heap st sv winfo action sno = do
513 return $ TokenContinue (seqNo + 1)
512 return $ TokenContinue (seqNo + 1)
514 mrun = runInIO $ svarMrun sv
513 mrun = runInIO $ svarMrun sv
515 r <- liftIO $ mrun $
514 r <- liftIO $ mrun $
516− foldStreamShared st
515+ K.foldStreamShared st
517 (yieldOutput seqNo)
516 (yieldOutput seqNo)
518 (singleOutput seqNo)
517 (singleOutput seqNo)
519 stop
518 stop
@@ -604,80 +603,36 @@ workLoopAhead q heap st sv winfo = do
604
603
605-- The only difference between forkSVarAsync and this is that we run the left
604-- The only difference between forkSVarAsync and this is that we run the left
606-- computation without a shared SVar.
605-- computation without a shared SVar.
607−forkSVarAhead :: (IsStream t, MonadAsync m) => t m a -> t m a -> t m a
606+forkSVarAhead :: MonadAsync m => Stream m a -> Stream m a -> Stream m a
608−forkSVarAhead m1 m2 = mkStream $ \st yld sng stp -> do
607+forkSVarAhead m1 m2 = K.mkStream $ \st yld sng stp -> do
609− sv <- newAheadVar st (concurrently (toStream m1) (toStream m2))
608+ sv <- newAheadVar st (concurrently m1 m2)
610 workLoopAhead
609 workLoopAhead
611− foldStream st yld sng stp (fromSVar sv)
610+ K.foldStream st yld sng stp $ getSerialT (fromSVar sv)
612 where
611 where
613− concurrently ma mb = mkStream $ \st yld sng stp -> do
612+ concurrently ma mb = K.mkStream $ \st yld sng stp -> do
614 runInIO <- captureMonadState
613 runInIO <- captureMonadState
615 liftIO $ enqueue (fromJust $ streamVar st) (runInIO, mb)
614 liftIO $ enqueue (fromJust $ streamVar st) (runInIO, mb)
616− foldStream st yld sng stp ma
615+ K.foldStream st yld sng stp ma
617
616
618−infixr 6 `ahead`
619−
620−-- | Appends two streams, both the streams may be evaluated concurrently but
621−-- the outputs are used in the same order as the corresponding actions in the
622−-- original streams, side effects will happen in the order in which the streams
623−-- are evaluated:
624−--
625−-- >>> import Streamly.Prelude (ahead, SerialT)
626−-- >>> stream1 = Stream.fromEffect (delay 4) :: SerialT IO Int
627−-- >>> stream2 = Stream.fromEffect (delay 2) :: SerialT IO Int
628−-- >>> Stream.toList $ stream1 `ahead` stream2 :: IO [Int]
629−-- 2 sec
630−-- 4 sec
631−-- [4,2]
632−--
633−-- Multiple streams can be combined. With enough threads, all of them can be
634−-- scheduled simultaneously:
635−--
636−-- >>> stream3 = Stream.fromEffect (delay 1)
637−-- >>> Stream.toList $ stream1 `ahead` stream2 `ahead` stream3
638−-- 1 sec
639−-- 2 sec
640−-- 4 sec
641−-- [4,2,1]
642−--
643−-- With 2 threads, only two can be scheduled at a time, when one of those
644−-- finishes, the third one gets scheduled:
645−--
646−-- >>> Stream.toList $ Stream.maxThreads 2 $ stream1 `ahead` stream2 `ahead` stream3
647−-- 2 sec
648−-- 1 sec
649−-- 4 sec
650−-- [4,2,1]
651−--
652−-- Only streams are scheduled for ahead evaluation, how actions within a stream
653−-- are evaluated depends on the stream type. If it is a concurrent stream they
654−-- will be evaluated concurrently. It may not make much sense combining serial
655−-- streams using 'ahead'.
656−--
657−-- 'ahead' can be safely used to fold an infinite lazy container of streams.
658−--
659−-- /Since: 0.3.0 ("Streamly")/
660−--
661−-- @since 0.8.0
662−{-# INLINE ahead #-}
617+{-# INLINE aheadK #-}
663−ahead :: (IsStream t, MonadAsync m) => t m a -> t m a -> t m a
618+aheadK :: MonadAsync m => Stream m a -> Stream m a -> Stream m a
664−ahead m1 m2 = mkStream $ \st yld sng stp ->
619+aheadK m1 m2 = K.mkStream $ \st yld sng stp ->
665 case streamVar st of
620 case streamVar st of
666 Just sv | svarStyle sv == AheadVar -> do
621 Just sv | svarStyle sv == AheadVar -> do
667 runInIO <- captureMonadState
622 runInIO <- captureMonadState
668− liftIO $ enqueue sv (runInIO, toStream m2)
623+ liftIO $ enqueue sv (runInIO, m2)
669 -- Always run the left side on a new SVar to avoid complexity in
624 -- Always run the left side on a new SVar to avoid complexity in
670 -- sequencing results. This means the left side cannot further
625 -- sequencing results. This means the left side cannot further
671 -- split into more ahead computations on the same SVar.
626 -- split into more ahead computations on the same SVar.
672− foldStream st yld sng stp m1
627+ K.foldStream st yld sng stp m1
673− _ -> foldStreamShared st yld sng stp (forkSVarAhead m1 m2)
628+ _ -> K.foldStreamShared st yld sng stp (forkSVarAhead m1 m2)
674
629
675-- | XXX we can implement it more efficienty by directly implementing instead
630-- | XXX we can implement it more efficienty by directly implementing instead
676-- of combining streams using ahead.
631-- of combining streams using ahead.
677−{-# INLINE consMAhead #-}
632+{-# INLINE consM #-}
678−{-# SPECIALIZE consMAhead :: IO a -> AheadT IO a -> AheadT IO a #-}
633+{-# SPECIALIZE consM :: IO a -> AheadT IO a -> AheadT IO a #-}
679−consMAhead :: MonadAsync m => m a -> AheadT m a -> AheadT m a
634+consM :: MonadAsync m => m a -> AheadT m a -> AheadT m a
680−consMAhead m r = fromStream $ K.fromEffect m `ahead` toStream r
635+consM m (AheadT r) = AheadT $ aheadK (K.fromEffect m) r
681
636
682------------------------------------------------------------------------------
637------------------------------------------------------------------------------
683-- AheadT
638-- AheadT
@@ -737,66 +692,58 @@ newtype AheadT m a = AheadT {getAheadT :: Stream m a}
737-- @since 0.8.0
692-- @since 0.8.0
738type Ahead = AheadT IO
693type Ahead = AheadT IO
739
694
740−-- | Fix the type of a polymorphic stream as 'AheadT'.
741−--
742−-- /Since: 0.3.0 ("Streamly")/
743−--
744−-- @since 0.8.0
745−fromAhead :: IsStream t => AheadT m a -> t m a
746−fromAhead = K.adapt
747−
748−instance IsStream AheadT where
749− toStream = getAheadT
750− fromStream = AheadT
751− consM = consMAhead
752− (|:) = consMAhead
753−
754------------------------------------------------------------------------------
695------------------------------------------------------------------------------
755-- Semigroup
696-- Semigroup
756------------------------------------------------------------------------------
697------------------------------------------------------------------------------
757
698
758−{-# INLINE mappendAhead #-}
699+{-# INLINE append #-}
759−{-# SPECIALIZE mappendAhead :: AheadT IO a -> AheadT IO a -> AheadT IO a #-}
700+{-# SPECIALIZE append :: AheadT IO a -> AheadT IO a -> AheadT IO a #-}
760−mappendAhead :: MonadAsync m => AheadT m a -> AheadT m a -> AheadT m a
701+append :: MonadAsync m => AheadT m a -> AheadT m a -> AheadT m a
761−mappendAhead m1 m2 = fromStream $ ahead (toStream m1) (toStream m2)
702+append (AheadT m1) (AheadT m2) = AheadT $ aheadK m1 m2
762
703
763instance MonadAsync m => Semigroup (AheadT m a) where
704instance MonadAsync m => Semigroup (AheadT m a) where
764− (<>) = mappendAhead
705+ (<>) = append
765
706
766------------------------------------------------------------------------------
707------------------------------------------------------------------------------
767-- Monoid
708-- Monoid
768------------------------------------------------------------------------------
709------------------------------------------------------------------------------
769
710
770instance MonadAsync m => Monoid (AheadT m a) where
711instance MonadAsync m => Monoid (AheadT m a) where
771− mempty = K.nil
712+ mempty = AheadT K.nil
772 mappend = (<>)
713 mappend = (<>)
773
714
774------------------------------------------------------------------------------
715------------------------------------------------------------------------------
775−-- Monad
716+-- Applicative
776------------------------------------------------------------------------------
717------------------------------------------------------------------------------
777
718
778−{-# INLINE concatMapAhead #-}
779−{-# SPECIALIZE concatMapAhead :: (a -> AheadT IO b) -> AheadT IO a -> AheadT IO b #-}
780−concatMapAhead :: MonadAsync m => (a -> AheadT m b) -> AheadT m a -> AheadT m b
781−concatMapAhead f m = fromStream $
782− K.concatMapBy ahead (K.adapt . f) (K.adapt m)
783−
784{-# INLINE apAhead #-}
719{-# INLINE apAhead #-}
785apAhead :: MonadAsync m => AheadT m (a -> b) -> AheadT m a -> AheadT m b
720apAhead :: MonadAsync m => AheadT m (a -> b) -> AheadT m a -> AheadT m b
786apAhead (AheadT m1) (AheadT m2) =
721apAhead (AheadT m1) (AheadT m2) =
787− let f x1 = K.concatMapBy ahead (pure . x1) m2
722+ let f x1 = K.concatMapWith aheadK (pure . x1) m2
788− in AheadT $ K.concatMapBy ahead f m1
723+ in AheadT $ K.concatMapWith aheadK f m1
789
724
790instance (Monad m, MonadAsync m) => Applicative (AheadT m) where
725instance (Monad m, MonadAsync m) => Applicative (AheadT m) where
791 {-# INLINE pure #-}
726 {-# INLINE pure #-}
792 pure = AheadT . K.fromPure
727 pure = AheadT . K.fromPure
728+
793 {-# INLINE (<*>) #-}
729 {-# INLINE (<*>) #-}
794 (<*>) = apAhead
730 (<*>) = apAhead
795
731
732+------------------------------------------------------------------------------
733+-- Monad
734+------------------------------------------------------------------------------
735+
736+{-# INLINE bindAhead #-}
737+{-# SPECIALIZE bindAhead ::
738+ AheadT IO a -> (a -> AheadT IO b) -> AheadT IO b #-}
739+bindAhead :: MonadAsync m => AheadT m a -> (a -> AheadT m b) -> AheadT m b
740+bindAhead (AheadT m) f = AheadT $ K.bindWith aheadK m (getAheadT . f)
741+
796instance MonadAsync m => Monad (AheadT m) where
742instance MonadAsync m => Monad (AheadT m) where
797 return = pure
743 return = pure
744+
798 {-# INLINE (>>=) #-}
745 {-# INLINE (>>=) #-}
799− (>>=) = flip concatMapAhead
746+ (>>=) = bindAhead
800
747
801------------------------------------------------------------------------------
748------------------------------------------------------------------------------
802-- Other instances
749-- Other instances
src/Streamly/Internal/Data/Stream/Async.hs+74−250
@@ -24,18 +24,17 @@
24--
24--
25module Streamly.Internal.Data.Stream.Async
25module Streamly.Internal.Data.Stream.Async
26 (
26 (
27− AsyncT
27+ AsyncT(..)
28 , Async
28 , Async
29− , fromAsync
29+ , consMAsync
30− , async
30+ , asyncK
31− , (<|) --deprecated
32− , mkAsync
33 , mkAsyncK
31 , mkAsyncK
32+ , mkAsyncD
34
33
35− , WAsyncT
34+ , WAsyncT(..)
36 , WAsync
35 , WAsync
37− , fromWAsync
36+ , consMWAsync
38− , wAsync
37+ , wAsyncK
39 )
38 )
40where
39where
41
40
@@ -63,11 +62,10 @@ import Streamly.Internal.Control.Concurrent
63 (MonadAsync, RunInIO(..), captureMonadState)
62 (MonadAsync, RunInIO(..), captureMonadState)
64import Streamly.Internal.Data.Atomics
63import Streamly.Internal.Data.Atomics
65 (atomicModifyIORefCAS, atomicModifyIORefCAS_)
64 (atomicModifyIORefCAS, atomicModifyIORefCAS_)
65+import Streamly.Internal.Data.Stream.Serial (SerialT (..))
66+import Streamly.Internal.Data.Stream.StreamK.Type (Stream)
66import Streamly.Internal.Data.Stream.SVar.Generate (fromSVar, fromSVarD)
67import Streamly.Internal.Data.Stream.SVar.Generate (fromSVar, fromSVarD)
67−import Streamly.Internal.Data.Stream.StreamK.Type
68− (IsStream(..), Stream, mkStream, foldStream, adapt, foldStreamShared)
69
68
70−import qualified Streamly.Internal.Data.Stream.StreamK as K (withLocal)
71import qualified Streamly.Internal.Data.Stream.StreamK.Type as K
69import qualified Streamly.Internal.Data.Stream.StreamK.Type as K
72import qualified Streamly.Internal.Data.Stream.StreamD.Type as D
70import qualified Streamly.Internal.Data.Stream.StreamD.Type as D
73
71
@@ -130,7 +128,7 @@ workLoopLIFO q st sv winfo = run
130 -- monad state here. That way it can work easily for
128 -- monad state here. That way it can work easily for
131 -- distributed case as well.
129 -- distributed case as well.
132 r <- liftIO $ runin $
130 r <- liftIO $ runin $
133− foldStreamShared st yieldk single (return Continue) m
131+ K.foldStreamShared st yieldk single (return Continue) m
134 res <- restoreM r
132 res <- restoreM r
135 case res of
133 case res of
136 Continue -> run
134 Continue -> run
@@ -143,7 +141,7 @@ workLoopLIFO q st sv winfo = run
143 yieldk a r = do
141 yieldk a r = do
144 res <- liftIO $ sendYield sv winfo (ChildYield a)
142 res <- liftIO $ sendYield sv winfo (ChildYield a)
145 if res
143 if res
146− then foldStreamShared st yieldk single (return Continue) r
144+ then K.foldStreamShared st yieldk single (return Continue) r
147 else do
145 else do
148 runInIO <- captureMonadState
146 runInIO <- captureMonadState
149 liftIO $ enqueueLIFO sv q (runInIO, r)
147 liftIO $ enqueueLIFO sv q (runInIO, r)
@@ -187,7 +185,7 @@ workLoopLIFOLimited q st sv winfo = run
187 if yieldLimitOk
185 if yieldLimitOk
188 then do
186 then do
189 r <- liftIO $ runin $
187 r <- liftIO $ runin $
190− foldStreamShared st yieldk single incrContinue m
188+ K.foldStreamShared st yieldk single incrContinue m
191 res <- restoreM r
189 res <- restoreM r
192 case res of
190 case res of
193 Continue -> run
191 Continue -> run
@@ -209,7 +207,7 @@ workLoopLIFOLimited q st sv winfo = run
209 res <- liftIO $ sendYield sv winfo (ChildYield a)
207 res <- liftIO $ sendYield sv winfo (ChildYield a)
210 yieldLimitOk <- liftIO $ decrementYieldLimit sv
208 yieldLimitOk <- liftIO $ decrementYieldLimit sv
211 if res && yieldLimitOk
209 if res && yieldLimitOk
212− then foldStreamShared st yieldk single incrContinue r
210+ then K.foldStreamShared st yieldk single incrContinue r
213 else do
211 else do
214 runInIO <- captureMonadState
212 runInIO <- captureMonadState
215 liftIO $ incrementYieldLimit sv
213 liftIO $ incrementYieldLimit sv
@@ -259,7 +257,7 @@ workLoopFIFO q st sv winfo = run
259 Nothing -> stop
257 Nothing -> stop
260 Just (RunInIO runin, m) -> do
258 Just (RunInIO runin, m) -> do
261 r <- liftIO $ runin $
259 r <- liftIO $ runin $
262− foldStreamShared st yieldk single (return Continue) m
260+ K.foldStreamShared st yieldk single (return Continue) m
263 res <- restoreM r
261 res <- restoreM r
264 case res of
262 case res of
265 Continue -> run
263 Continue -> run
@@ -302,7 +300,7 @@ workLoopFIFOLimited q st sv winfo = run
302 if yieldLimitOk
300 if yieldLimitOk
303 then do
301 then do
304 r <- liftIO $ runin $
302 r <- liftIO $ runin $
305− foldStreamShared st yieldk single incrContinue m
303+ K.foldStreamShared st yieldk single incrContinue m
306 res <- restoreM r
304 res <- restoreM r
307 case res of
305 case res of
308 Continue -> run
306 Continue -> run
@@ -545,18 +543,21 @@ newAsyncVar st m = do
545-- /Pre-release/
543-- /Pre-release/
546--
544--
547{-# INLINABLE mkAsyncK #-}
545{-# INLINABLE mkAsyncK #-}
548−mkAsyncK :: (IsStream t, MonadAsync m) => t m a -> t m a
546+mkAsyncK :: MonadAsync m => Stream m a -> Stream m a
549−mkAsyncK m = mkStream $ \st yld sng stp -> do
547+mkAsyncK m = K.mkStream $ \st yld sng stp -> do
550− sv <- newAsyncVar (adaptState st) (toStream m)
548+ sv <- newAsyncVar (adaptState st) m
551− foldStream st yld sng stp $ fromSVar sv
549+ K.foldStream st yld sng stp $ getSerialT $ fromSVar sv
552
550
551+--
552+-- This is slightly faster than the CPS version above
553+--
553{-# INLINE_NORMAL mkAsyncD #-}
554{-# INLINE_NORMAL mkAsyncD #-}
554mkAsyncD :: MonadAsync m => D.Stream m a -> D.Stream m a
555mkAsyncD :: MonadAsync m => D.Stream m a -> D.Stream m a
555mkAsyncD m = D.Stream step Nothing
556mkAsyncD m = D.Stream step Nothing
556 where
557 where
557
558
558 step gst Nothing = do
559 step gst Nothing = do
559− sv <- newAsyncVar gst (D.fromStreamD m)
560+ sv <- newAsyncVar gst (D.toStreamK m)
560 return $ D.Skip $ Just $ fromSVarD sv
561 return $ D.Skip $ Just $ fromSVarD sv
561
562
562 step gst (Just (D.UnStream step1 st)) = do
563 step gst (Just (D.UnStream step1 st)) = do
@@ -566,23 +567,7 @@ mkAsyncD m = D.Stream step Nothing
566 D.Skip s -> D.Skip (Just $ D.Stream step1 s)
567 D.Skip s -> D.Skip (Just $ D.Stream step1 s)
567 D.Stop -> D.Stop
568 D.Stop -> D.Stop
568
569
569−--
570+-- XXX We can pass captureMonadState instead of using MonadAsync
570−-- This is slightly faster than the CPS version above
571−--
572−-- | Make the stream producer and consumer run concurrently by introducing a
573−-- buffer between them. The producer thread evaluates the input stream until
574−-- the buffer fills, it terminates if the buffer is full and a worker thread is
575−-- kicked off again to evaluate the remaining stream when there is space in the
576−-- buffer. The consumer consumes the stream lazily from the buffer.
577−--
578−-- /Since: 0.2.0 (Streamly)/
579−--
580−-- @since 0.8.0
581−--
582−{-# INLINE_NORMAL mkAsync #-}
583−mkAsync :: (K.IsStream t, MonadAsync m) => t m a -> t m a
584−mkAsync = D.fromStreamD . mkAsyncD . D.toStreamD
585−
586-- | Create a new SVar and enqueue one stream computation on it.
571-- | Create a new SVar and enqueue one stream computation on it.
587{-# INLINABLE newWAsyncVar #-}
572{-# INLINABLE newWAsyncVar #-}
588newWAsyncVar :: MonadAsync m
573newWAsyncVar :: MonadAsync m
@@ -590,6 +575,8 @@ newWAsyncVar :: MonadAsync m
590newWAsyncVar st m = do
575newWAsyncVar st m = do
591 mrun <- captureMonadState
576 mrun <- captureMonadState
592 sv <- liftIO $ getFifoSVar st mrun
577 sv <- liftIO $ getFifoSVar st mrun
578+ -- XXX Use just Stream and IO in all the functions below
579+ -- XXX pass mrun instead of calling captureMonadState again inside it
593 sendFirstWorker sv m
580 sendFirstWorker sv m
594
581
595------------------------------------------------------------------------------
582------------------------------------------------------------------------------
@@ -656,109 +643,38 @@ newWAsyncVar st m = do
656-- composition and vice-versa we create a new SVar to isolate the scheduling
643-- composition and vice-versa we create a new SVar to isolate the scheduling
657-- of the two.
644-- of the two.
658
645
659−forkSVarAsync :: (IsStream t, MonadAsync m)
646+forkSVarAsync :: MonadAsync m
660− => SVarStyle -> t m a -> t m a -> t m a
647+ => SVarStyle -> Stream m a -> Stream m a -> Stream m a
661−forkSVarAsync style m1 m2 = mkStream $ \st yld sng stp -> do
648+forkSVarAsync style m1 m2 = K.mkStream $ \st yld sng stp -> do
662 sv <- case style of
649 sv <- case style of
663− AsyncVar -> newAsyncVar st (concurrently (toStream m1) (toStream m2))
650+ AsyncVar -> newAsyncVar st (concurrently m1 m2)
664− WAsyncVar -> newWAsyncVar st (concurrently (toStream m1) (toStream m2))
651+ WAsyncVar -> newWAsyncVar st (concurrently m1 m2)
665 _ -> error "illegal svar type"
652 _ -> error "illegal svar type"
666− foldStream st yld sng stp $ fromSVar sv
653+ K.foldStream st yld sng stp $ getSerialT $ fromSVar sv
667 where
654 where
668− concurrently ma mb = mkStream $ \st yld sng stp -> do
655+ concurrently ma mb = K.mkStream $ \st yld sng stp -> do
669 runInIO <- captureMonadState
656 runInIO <- captureMonadState
670 liftIO $ enqueue (fromJust $ streamVar st) (runInIO, mb)
657 liftIO $ enqueue (fromJust $ streamVar st) (runInIO, mb)
671− foldStreamShared st yld sng stp ma
658+ K.foldStreamShared st yld sng stp ma
672
659
673{-# INLINE joinStreamVarAsync #-}
660{-# INLINE joinStreamVarAsync #-}
674−joinStreamVarAsync :: (IsStream t, MonadAsync m)
661+joinStreamVarAsync :: MonadAsync m
675− => SVarStyle -> t m a -> t m a -> t m a
662+ => SVarStyle -> Stream m a -> Stream m a -> Stream m a
676−joinStreamVarAsync style m1 m2 = mkStream $ \st yld sng stp ->
663+joinStreamVarAsync style m1 m2 = K.mkStream $ \st yld sng stp ->
677 case streamVar st of
664 case streamVar st of
678 Just sv | svarStyle sv == style -> do
665 Just sv | svarStyle sv == style -> do
679 runInIO <- captureMonadState
666 runInIO <- captureMonadState
680− liftIO $ enqueue sv (runInIO, toStream m2)
667+ liftIO $ enqueue sv (runInIO, m2)
681− foldStreamShared st yld sng stp m1
668+ K.foldStreamShared st yld sng stp m1
682− _ -> foldStreamShared st yld sng stp (forkSVarAsync style m1 m2)
669+ _ -> K.foldStreamShared st yld sng stp (forkSVarAsync style m1 m2)
683
670
684------------------------------------------------------------------------------
671------------------------------------------------------------------------------
685-- Semigroup and Monoid style compositions for parallel actions
672-- Semigroup and Monoid style compositions for parallel actions
686------------------------------------------------------------------------------
673------------------------------------------------------------------------------
687
674
688−infixr 6 `async`
689−
690−-- | Merges two streams, both the streams may be evaluated concurrently,
691−-- outputs from both are used as they arrive:
692−--
693−-- >>> import Streamly.Prelude (async)
694−-- >>> stream1 = Stream.fromEffect (delay 4)
695−-- >>> stream2 = Stream.fromEffect (delay 2)
696−-- >>> Stream.toList $ stream1 `async` stream2
697−-- 2 sec
698−-- 4 sec
699−-- [2,4]
700−--
701−-- Multiple streams can be combined. With enough threads, all of them can be
702−-- scheduled simultaneously:
703−--
704−-- >>> stream3 = Stream.fromEffect (delay 1)
705−-- >>> Stream.toList $ stream1 `async` stream2 `async` stream3
706−-- ...
707−-- [1,2,4]
708−--
709−-- With 2 threads, only two can be scheduled at a time, when one of those
710−-- finishes, the third one gets scheduled:
711−--
712−-- >>> Stream.toList $ Stream.maxThreads 2 $ stream1 `async` stream2 `async` stream3
713−-- ...
714−-- [2,1,4]
715−--
716−-- With a single thread, it becomes serial:
717−--
718−-- >>> Stream.toList $ Stream.maxThreads 1 $ stream1 `async` stream2 `async` stream3
719−-- ...
720−-- [4,2,1]
721−--
722−-- Only streams are scheduled for async evaluation, how actions within a
723−-- stream are evaluated depends on the stream type. If it is a concurrent
724−-- stream they will be evaluated concurrently.
725−--
726−-- In the following example, both the streams are scheduled for concurrent
727−-- evaluation but each individual stream is evaluated serially:
728−--
729−-- >>> stream1 = Stream.fromListM $ Prelude.map delay [3,3] -- SerialT IO Int
730−-- >>> stream2 = Stream.fromListM $ Prelude.map delay [1,1] -- SerialT IO Int
731−-- >>> Stream.toList $ stream1 `async` stream2 -- IO [Int]
732−-- ...
733−-- [1,1,3,3]
734−--
735−-- If total threads are 2, the third stream is scheduled only after one of the
736−-- first two has finished:
737−--
738−-- > stream3 = Stream.fromListM $ Prelude.map delay [2,2] -- SerialT IO Int
739−-- > Stream.toList $ Stream.maxThreads 2 $ stream1 `async` stream2 `async` stream3 -- IO [Int]
740−-- ...
741−-- [1,1,3,2,3,2]
742−--
743−-- Thus 'async' goes deep in first few streams rather than going wide in all
744−-- streams. It prefers to evaluate the leftmost streams as much as possible.
745−-- Because of this behavior, 'async' can be safely used to fold an infinite
746−-- lazy container of streams.
747−--
748−-- /Since: 0.2.0 ("Streamly")/
749−--
750−-- @since 0.8.0
751−{-# INLINE async #-}
675+{-# INLINE asyncK #-}
752−async :: (IsStream t, MonadAsync m) => t m a -> t m a -> t m a
676+asyncK :: MonadAsync m => Stream m a -> Stream m a -> Stream m a
753−async = joinStreamVarAsync AsyncVar
677+asyncK = joinStreamVarAsync AsyncVar
754−
755−-- | Same as 'async'.
756−--
757−-- @since 0.1.0
758−{-# DEPRECATED (<|) "Please use 'async' instead." #-}
759−{-# INLINE (<|) #-}
760−(<|) :: (IsStream t, MonadAsync m) => t m a -> t m a -> t m a
761−(<|) = async
762
678
763-- IMPORTANT: using a monomorphically typed and SPECIALIZED consMAsync makes a
679-- IMPORTANT: using a monomorphically typed and SPECIALIZED consMAsync makes a
764-- huge difference in the performance of consM in IsStream instance even we
680-- huge difference in the performance of consM in IsStream instance even we
@@ -769,7 +685,7 @@ async = joinStreamVarAsync AsyncVar
769{-# INLINE consMAsync #-}
685{-# INLINE consMAsync #-}
770{-# SPECIALIZE consMAsync :: IO a -> AsyncT IO a -> AsyncT IO a #-}
686{-# SPECIALIZE consMAsync :: IO a -> AsyncT IO a -> AsyncT IO a #-}
771consMAsync :: MonadAsync m => m a -> AsyncT m a -> AsyncT m a
687consMAsync :: MonadAsync m => m a -> AsyncT m a -> AsyncT m a
772−consMAsync m r = fromStream $ K.fromEffect m `async` toStream r
688+consMAsync m (AsyncT r) = AsyncT $ asyncK (K.fromEffect m) r
773
689
774------------------------------------------------------------------------------
690------------------------------------------------------------------------------
775-- AsyncT
691-- AsyncT
@@ -829,40 +745,26 @@ newtype AsyncT m a = AsyncT {getAsyncT :: Stream m a}
829-- @since 0.8.0
745-- @since 0.8.0
830type Async = AsyncT IO
746type Async = AsyncT IO
831
747
832−-- | Fix the type of a polymorphic stream as 'AsyncT'.
833−--
834−-- /Since: 0.1.0 ("Streamly")/
835−--
836−-- @since 0.8.0
837−fromAsync :: IsStream t => AsyncT m a -> t m a
838−fromAsync = adapt
839−
840−instance IsStream AsyncT where
841− toStream = getAsyncT
842− fromStream = AsyncT
843− consM = consMAsync
844− (|:) = consMAsync
845−
846------------------------------------------------------------------------------
748------------------------------------------------------------------------------
847-- Semigroup
749-- Semigroup
848------------------------------------------------------------------------------
750------------------------------------------------------------------------------
849
751
850-- Monomorphically typed version of "async" for better performance of Semigroup
752-- Monomorphically typed version of "async" for better performance of Semigroup
851-- instance.
753-- instance.
852−{-# INLINE mappendAsync #-}
754+{-# INLINE append #-}
853−{-# SPECIALIZE mappendAsync :: AsyncT IO a -> AsyncT IO a -> AsyncT IO a #-}
755+{-# SPECIALIZE append :: AsyncT IO a -> AsyncT IO a -> AsyncT IO a #-}
854−mappendAsync :: MonadAsync m => AsyncT m a -> AsyncT m a -> AsyncT m a
756+append :: MonadAsync m => AsyncT m a -> AsyncT m a -> AsyncT m a
855−mappendAsync m1 m2 = fromStream $ async (toStream m1) (toStream m2)
757+append (AsyncT m1) (AsyncT m2) = AsyncT $ asyncK m1 m2
856
758
857instance MonadAsync m => Semigroup (AsyncT m a) where
759instance MonadAsync m => Semigroup (AsyncT m a) where
858− (<>) = mappendAsync
760+ (<>) = append
859
761
860------------------------------------------------------------------------------
762------------------------------------------------------------------------------
861-- Monoid
763-- Monoid
862------------------------------------------------------------------------------
764------------------------------------------------------------------------------
863
765
864instance MonadAsync m => Monoid (AsyncT m a) where
766instance MonadAsync m => Monoid (AsyncT m a) where
865− mempty = K.nil
767+ mempty = AsyncT K.nil
866 mappend = (<>)
768 mappend = (<>)
867
769
868------------------------------------------------------------------------------
770------------------------------------------------------------------------------
@@ -873,12 +775,13 @@ instance MonadAsync m => Monoid (AsyncT m a) where
873{-# SPECIALIZE apAsync :: AsyncT IO (a -> b) -> AsyncT IO a -> AsyncT IO b #-}
775{-# SPECIALIZE apAsync :: AsyncT IO (a -> b) -> AsyncT IO a -> AsyncT IO b #-}
874apAsync :: MonadAsync m => AsyncT m (a -> b) -> AsyncT m a -> AsyncT m b
776apAsync :: MonadAsync m => AsyncT m (a -> b) -> AsyncT m a -> AsyncT m b
875apAsync (AsyncT m1) (AsyncT m2) =
777apAsync (AsyncT m1) (AsyncT m2) =
876− let f x1 = K.concatMapBy async (pure . x1) m2
778+ let f x1 = K.concatMapWith asyncK (pure . x1) m2
877− in AsyncT $ K.concatMapBy async f m1
779+ in AsyncT $ K.concatMapWith asyncK f m1
878
780
879instance (Monad m, MonadAsync m) => Applicative (AsyncT m) where
781instance (Monad m, MonadAsync m) => Applicative (AsyncT m) where
880 {-# INLINE pure #-}
782 {-# INLINE pure #-}
881 pure = AsyncT . K.fromPure
783 pure = AsyncT . K.fromPure
784+
882 {-# INLINE (<*>) #-}
785 {-# INLINE (<*>) #-}
883 (<*>) = apAsync
786 (<*>) = apAsync
884
787
@@ -889,9 +792,10 @@ instance (Monad m, MonadAsync m) => Applicative (AsyncT m) where
889-- GHC: if we change the implementation of bindWith with arguments in a
792-- GHC: if we change the implementation of bindWith with arguments in a
890-- different order we see a significant performance degradation (~2x).
793-- different order we see a significant performance degradation (~2x).
891{-# INLINE bindAsync #-}
794{-# INLINE bindAsync #-}
795+{-# SPECIALIZE bindAsync ::
892−{-# SPECIALIZE bindAsync :: AsyncT IO a -> (a -> AsyncT IO b) -> AsyncT IO b #-}
796+ AsyncT IO a -> (a -> AsyncT IO b) -> AsyncT IO b #-}
893bindAsync :: MonadAsync m => AsyncT m a -> (a -> AsyncT m b) -> AsyncT m b
797bindAsync :: MonadAsync m => AsyncT m a -> (a -> AsyncT m b) -> AsyncT m b
894−bindAsync m f = fromStream $ K.bindWith async (adapt m) (adapt . f)
798+bindAsync (AsyncT m) f = AsyncT $ K.bindWith asyncK m (getAsyncT . f)
895
799
896-- GHC: if we specify arguments in the definition of (>>=) we see a significant
800-- GHC: if we specify arguments in the definition of (>>=) we see a significant
897-- performance degradation (~2x).
801-- performance degradation (~2x).
@@ -909,84 +813,16 @@ MONAD_COMMON_INSTANCES(AsyncT, MONADPARALLEL)
909-- WAsyncT
813-- WAsyncT
910------------------------------------------------------------------------------
814------------------------------------------------------------------------------
911
815
816+{-# INLINE wAsyncK #-}
817+wAsyncK :: MonadAsync m => Stream m a -> Stream m a -> Stream m a
818+wAsyncK = joinStreamVarAsync WAsyncVar
819+
912-- | XXX we can implement it more efficienty by directly implementing instead
820-- | XXX we can implement it more efficienty by directly implementing instead
913-- of combining streams using wAsync.
821-- of combining streams using wAsync.
914{-# INLINE consMWAsync #-}
822{-# INLINE consMWAsync #-}
915{-# SPECIALIZE consMWAsync :: IO a -> WAsyncT IO a -> WAsyncT IO a #-}
823{-# SPECIALIZE consMWAsync :: IO a -> WAsyncT IO a -> WAsyncT IO a #-}
916consMWAsync :: MonadAsync m => m a -> WAsyncT m a -> WAsyncT m a
824consMWAsync :: MonadAsync m => m a -> WAsyncT m a -> WAsyncT m a
917−consMWAsync m r = fromStream $ K.fromEffect m `wAsync` toStream r
825+consMWAsync m (WAsyncT r) = WAsyncT $ wAsyncK (K.fromEffect m) r
918−
919−infixr 6 `wAsync`
920−
921−-- | For singleton streams, 'wAsync' is the same as 'async'. See 'async' for
922−-- singleton stream behavior. For multi-element streams, while 'async' is left
923−-- biased i.e. it tries to evaluate the left side stream as much as possible,
924−-- 'wAsync' tries to schedule them both fairly. In other words, 'async' goes
925−-- deep while 'wAsync' goes wide. However, outputs are always used as they
926−-- arrive.
927−--
928−-- With a single thread, 'async' starts behaving like 'serial' while 'wAsync'
929−-- starts behaving like 'wSerial'.
930−--
931−-- >>> import Streamly.Prelude (wAsync)
932−-- >>> stream1 = Stream.fromList [1,2,3]
933−-- >>> stream2 = Stream.fromList [4,5,6]
934−-- >>> Stream.toList $ Stream.fromAsync $ Stream.maxThreads 1 $ stream1 `async` stream2
935−-- [1,2,3,4,5,6]
936−--
937−-- >>> Stream.toList $ Stream.fromWAsync $ Stream.maxThreads 1 $ stream1 `wAsync` stream2
938−-- [1,4,2,5,3,6]
939−--
940−-- With two threads available, and combining three streams:
941−--
942−-- >>> stream3 = Stream.fromList [7,8,9]
943−-- >>> Stream.toList $ Stream.fromAsync $ Stream.maxThreads 2 $ stream1 `async` stream2 `async` stream3
944−-- [1,2,3,4,5,6,7,8,9]
945−--
946−-- >>> Stream.toList $ Stream.fromWAsync $ Stream.maxThreads 2 $ stream1 `wAsync` stream2 `wAsync` stream3
947−-- [1,4,2,7,5,3,8,6,9]
948−--
949−-- This operation cannot be used to fold an infinite lazy container of streams,
950−-- because it schedules all the streams in a round robin manner.
951−--
952−-- Note that 'WSerialT' and single threaded 'WAsyncT' both interleave streams
953−-- but the exact scheduling is slightly different in both cases.
954−--
955−-- @since 0.8.0
956−--
957−-- /Since: 0.2.0 ("Streamly")/
958−
959−-- Scheduling details:
960−--
961−-- This is how the execution of the above example proceeds:
962−--
963−-- 1. The scheduler queue is initialized with @[S.fromList [1,2,3],
964−-- (S.fromList [4,5,6]) \<> (S.fromList [7,8,9])]@ assuming the head of the
965−-- queue is represented by the rightmost item.
966−-- 2. @S.fromList [1,2,3]@ is executed, yielding the element @1@ and putting
967−-- @[2,3]@ at the back of the scheduler queue. The scheduler queue now looks
968−-- like @[(S.fromList [4,5,6]) \<> (S.fromList [7,8,9]), S.fromList [2,3]]@.
969−-- 3. Now @(S.fromList [4,5,6]) \<> (S.fromList [7,8,9])@ is picked up for
970−-- execution, @S.fromList [7,8,9]@ is added at the back of the queue and
971−-- @S.fromList [4,5,6]@ is executed, yielding the element @4@ and adding
972−-- @S.fromList [5,6]@ at the back of the queue. The queue now looks like
973−-- @[S.fromList [2,3], S.fromList [7,8,9], S.fromList [5,6]]@.
974−-- 4. Note that the scheduler queue expands by one more stream component in
975−-- every pass because one more @<>@ is broken down into two components. At this
976−-- point there are no more @<>@ operations to be broken down further and the
977−-- queue has reached its maximum size. Now these streams are scheduled in
978−-- round-robin fashion yielding @[2,7,5,3,8,6,9]@.
979−--
980−-- As we see above, in a right associated expression composed with @<>@, only
981−-- one @<>@ operation is broken down into two components in one execution,
982−-- therefore, if we have @n@ streams composed using @<>@ it will take @n@
983−-- scheduler passes to expand the whole expression. By the time @n-th@
984−-- component is added to the scheduler queue, the first component would have
985−-- received @n@ scheduler passes.
986−--
987−{-# INLINE wAsync #-}
988−wAsync :: (IsStream t, MonadAsync m) => t m a -> t m a -> t m a
989−wAsync = joinStreamVarAsync WAsyncVar
990
826
991-- | For 'WAsyncT' streams:
827-- | For 'WAsyncT' streams:
992--
828--
@@ -1132,38 +968,24 @@ newtype WAsyncT m a = WAsyncT {getWAsyncT :: Stream m a}
1132-- @since 0.8.0
968-- @since 0.8.0
1133type WAsync = WAsyncT IO
969type WAsync = WAsyncT IO
1134
970
1135−-- | Fix the type of a polymorphic stream as 'WAsyncT'.
1136−--
1137−-- /Since: 0.2.0 ("Streamly")/
1138−--
1139−-- @since 0.8.0
1140−fromWAsync :: IsStream t => WAsyncT m a -> t m a
1141−fromWAsync = adapt
1142−
1143−instance IsStream WAsyncT where
1144− toStream = getWAsyncT
1145− fromStream = WAsyncT
1146− consM = consMWAsync
1147− (|:) = consMWAsync
1148−
1149------------------------------------------------------------------------------
971------------------------------------------------------------------------------
1150-- Semigroup
972-- Semigroup
1151------------------------------------------------------------------------------
973------------------------------------------------------------------------------
1152
974
1153−{-# INLINE mappendWAsync #-}
975+{-# INLINE wAppend #-}
1154−{-# SPECIALIZE mappendWAsync :: WAsyncT IO a -> WAsyncT IO a -> WAsyncT IO a #-}
976+{-# SPECIALIZE wAppend :: WAsyncT IO a -> WAsyncT IO a -> WAsyncT IO a #-}
1155−mappendWAsync :: MonadAsync m => WAsyncT m a -> WAsyncT m a -> WAsyncT m a
977+wAppend :: MonadAsync m => WAsyncT m a -> WAsyncT m a -> WAsyncT m a
1156−mappendWAsync m1 m2 = fromStream $ wAsync (toStream m1) (toStream m2)
978+wAppend (WAsyncT m1) (WAsyncT m2) = WAsyncT $ wAsyncK m1 m2
1157
979
1158instance MonadAsync m => Semigroup (WAsyncT m a) where
980instance MonadAsync m => Semigroup (WAsyncT m a) where
1159− (<>) = mappendWAsync
981+ (<>) = wAppend
1160
982
1161------------------------------------------------------------------------------
983------------------------------------------------------------------------------
1162-- Monoid
984-- Monoid
1163------------------------------------------------------------------------------
985------------------------------------------------------------------------------
1164
986
1165instance MonadAsync m => Monoid (WAsyncT m a) where
987instance MonadAsync m => Monoid (WAsyncT m a) where
1166− mempty = K.nil
988+ mempty = WAsyncT K.nil
1167 mappend = (<>)
989 mappend = (<>)
1168
990
1169------------------------------------------------------------------------------
991------------------------------------------------------------------------------
@@ -1171,11 +993,12 @@ instance MonadAsync m => Monoid (WAsyncT m a) where
1171------------------------------------------------------------------------------
993------------------------------------------------------------------------------
1172
994
1173{-# INLINE apWAsync #-}
995{-# INLINE apWAsync #-}
996+{-# SPECIALIZE apWAsync ::
1174−{-# SPECIALIZE apWAsync :: WAsyncT IO (a -> b) -> WAsyncT IO a -> WAsyncT IO b #-}
997+ WAsyncT IO (a -> b) -> WAsyncT IO a -> WAsyncT IO b #-}
1175apWAsync :: MonadAsync m => WAsyncT m (a -> b) -> WAsyncT m a -> WAsyncT m b
998apWAsync :: MonadAsync m => WAsyncT m (a -> b) -> WAsyncT m a -> WAsyncT m b
1176apWAsync (WAsyncT m1) (WAsyncT m2) =
999apWAsync (WAsyncT m1) (WAsyncT m2) =
1177− let f x1 = K.concatMapBy wAsync (pure . x1) m2
1000+ let f x1 = K.concatMapWith wAsyncK (pure . x1) m2
1178− in WAsyncT $ K.concatMapBy wAsync f m1
1001+ in WAsyncT $ K.concatMapWith wAsyncK f m1
1179
1002
1180-- GHC: if we specify arguments in the definition of (<*>) we see a significant
1003-- GHC: if we specify arguments in the definition of (<*>) we see a significant
1181-- performance degradation (~2x).
1004-- performance degradation (~2x).
@@ -1190,9 +1013,10 @@ instance (Monad m, MonadAsync m) => Applicative (WAsyncT m) where
1190-- GHC: if we change the implementation of bindWith with arguments in a
1013-- GHC: if we change the implementation of bindWith with arguments in a
1191-- different order we see a significant performance degradation (~2x).
1014-- different order we see a significant performance degradation (~2x).
1192{-# INLINE bindWAsync #-}
1015{-# INLINE bindWAsync #-}
1016+{-# SPECIALIZE bindWAsync ::
1193−{-# SPECIALIZE bindWAsync :: WAsyncT IO a -> (a -> WAsyncT IO b) -> WAsyncT IO b #-}
1017+ WAsyncT IO a -> (a -> WAsyncT IO b) -> WAsyncT IO b #-}
1194bindWAsync :: MonadAsync m => WAsyncT m a -> (a -> WAsyncT m b) -> WAsyncT m b
1018bindWAsync :: MonadAsync m => WAsyncT m a -> (a -> WAsyncT m b) -> WAsyncT m b
1195−bindWAsync m f = fromStream $ K.bindWith wAsync (adapt m) (adapt . f)
1019+bindWAsync (WAsyncT m) f = WAsyncT $ K.bindWith wAsyncK m (getWAsyncT . f)
1196
1020
1197-- GHC: if we specify arguments in the definition of (>>=) we see a significant
1021-- GHC: if we specify arguments in the definition of (>>=) we see a significant
1198-- performance degradation (~2x).
1022-- performance degradation (~2x).
src/Streamly/Internal/Data/Stream/Instances.hs+13−11
@@ -10,7 +10,8 @@
10#define MONAD_COMMON_INSTANCES(STREAM,CONSTRAINT) \
10#define MONAD_COMMON_INSTANCES(STREAM,CONSTRAINT) \
11instance Monad m => Functor (STREAM m) where { \
11instance Monad m => Functor (STREAM m) where { \
12 {-# INLINE fmap #-}; \
12 {-# INLINE fmap #-}; \
13− fmap f (STREAM m) = D.fromStreamD $ D.mapM (return . f) $ D.toStreamD m; \
13+ fmap f (STREAM m) = \
14+ STREAM $ D.toStreamK $ D.mapM (return . f) $ D.fromStreamK m; \
14 {-# INLINE (<$) #-}; \
15 {-# INLINE (<$) #-}; \
15 (<$) = fmap . const }; \
16 (<$) = fmap . const }; \
16 \
17 \
@@ -32,7 +33,7 @@ instance (MonadError e m CONSTRAINT) => MonadError e (STREAM m) where { \
32 \
33 \
33instance (MonadReader r m CONSTRAINT) => MonadReader r (STREAM m) where { \
34instance (MonadReader r m CONSTRAINT) => MonadReader r (STREAM m) where { \
34 ask = lift ask; \
35 ask = lift ask; \
35− local f m = fromStream $ K.withLocal f (toStream m) }; \
36+ local f (STREAM m) = STREAM $ K.withLocal f m }; \
36 \
37 \
37instance (MonadState s m CONSTRAINT) => MonadState s (STREAM m) where { \
38instance (MonadState s m CONSTRAINT) => MonadState s (STREAM m) where { \
38 {-# INLINE get #-}; \
39 {-# INLINE get #-}; \
@@ -59,7 +60,7 @@ instance (MonadState s m CONSTRAINT) => MonadState s (STREAM m) where { \
59#define NFDATA1_INSTANCE(STREAM) \
60#define NFDATA1_INSTANCE(STREAM) \
60instance NFData1 (STREAM Identity) where { \
61instance NFData1 (STREAM Identity) where { \
61 {-# INLINE liftRnf #-}; \
62 {-# INLINE liftRnf #-}; \
62− liftRnf r = runIdentity . P.foldl' (\_ x -> r x) () }
63+ liftRnf f (STREAM xs) = runIdentity $ P.foldl' (\_ x -> f x) () xs}
63#else
64#else
64#define NFDATA1_INSTANCE(STREAM)
65#define NFDATA1_INSTANCE(STREAM)
65#endif
66#endif
@@ -68,17 +69,17 @@ instance NFData1 (STREAM Identity) where { \
68instance IsList (STREAM Identity a) where { \
69instance IsList (STREAM Identity a) where { \
69 type (Item (STREAM Identity a)) = a; \
70 type (Item (STREAM Identity a)) = a; \
70 {-# INLINE fromList #-}; \
71 {-# INLINE fromList #-}; \
71− fromList = P.fromList; \
72+ fromList xs = STREAM $ P.fromList xs; \
72 {-# INLINE toList #-}; \
73 {-# INLINE toList #-}; \
73− toList = runIdentity . P.toList }; \
74+ toList (STREAM xs) = runIdentity $ P.toList xs }; \
74 \
75 \
75instance Eq a => Eq (STREAM Identity a) where { \
76instance Eq a => Eq (STREAM Identity a) where { \
76 {-# INLINE (==) #-}; \
77 {-# INLINE (==) #-}; \
77− (==) xs ys = runIdentity $ P.eqBy (==) xs ys }; \
78+ (==) (STREAM xs) (STREAM ys) = runIdentity $ P.eqBy (==) xs ys }; \
78 \
79 \
79instance Ord a => Ord (STREAM Identity a) where { \
80instance Ord a => Ord (STREAM Identity a) where { \
80 {-# INLINE compare #-}; \
81 {-# INLINE compare #-}; \
81− compare xs ys = runIdentity $ P.cmpBy compare xs ys; \
82+ compare (STREAM xs) (STREAM ys) = runIdentity $ P.cmpBy compare xs ys; \
82 {-# INLINE (<) #-}; \
83 {-# INLINE (<) #-}; \
83 x < y = case compare x y of { LT -> True; _ -> False }; \
84 x < y = case compare x y of { LT -> True; _ -> False }; \
84 {-# INLINE (<=) #-}; \
85 {-# INLINE (<=) #-}; \
@@ -104,11 +105,11 @@ instance Read a => Read (STREAM Identity a) where { \
104 \
105 \
105instance (a ~ Char) => IsString (STREAM Identity a) where { \
106instance (a ~ Char) => IsString (STREAM Identity a) where { \
106 {-# INLINE fromString #-}; \
107 {-# INLINE fromString #-}; \
107− fromString = P.fromList }; \
108+ fromString xs = STREAM $ P.fromList xs }; \
108 \
109 \
109instance NFData a => NFData (STREAM Identity a) where { \
110instance NFData a => NFData (STREAM Identity a) where { \
110 {-# INLINE rnf #-}; \
111 {-# INLINE rnf #-}; \
111− rnf = runIdentity . P.foldl' (\_ x -> rnf x) () }; \
112+ rnf (STREAM xs) = runIdentity $ P.foldl' (\_ x -> rnf x) () xs}; \
112
113
113-------------------------------------------------------------------------------
114-------------------------------------------------------------------------------
114-- Foldable
115-- Foldable
@@ -125,7 +126,7 @@ instance NFData a => NFData (STREAM Identity a) where { \
125instance (Foldable m, Monad m) => Foldable (STREAM m) where { \
126instance (Foldable m, Monad m) => Foldable (STREAM m) where { \
126 \
127 \
127 {-# INLINE foldMap #-}; \
128 {-# INLINE foldMap #-}; \
128− foldMap f = fold . P.foldr (mappend . f) mempty; \
129+ foldMap f (STREAM xs) = fold $ P.foldr (mappend . f) mempty xs; \
129 \
130 \
130 {-# INLINE foldr #-}; \
131 {-# INLINE foldr #-}; \
131 foldr f z t = appEndo (foldMap (Endo #. f) t) z; \
132 foldr f z t = appEndo (foldMap (Endo #. f) t) z; \
@@ -169,5 +170,6 @@ instance (Foldable m, Monad m) => Foldable (STREAM m) where { \
169#define TRAVERSABLE_INSTANCE(STREAM) \
170#define TRAVERSABLE_INSTANCE(STREAM) \
170instance Traversable (STREAM Identity) where { \
171instance Traversable (STREAM Identity) where { \
171 {-# INLINE traverse #-}; \
172 {-# INLINE traverse #-}; \
173+ traverse f (STREAM xs) = \
172− traverse f s = runIdentity $ P.foldr consA (pure mempty) s \
174+ fmap STREAM $ runIdentity $ P.foldr consA (pure mempty) xs \
173 where { consA x ys = liftA2 K.cons (f x) ys }}
175 where { consA x ys = liftA2 K.cons (f x) ys }}
src/Streamly/Internal/Data/Stream/IsStream.hs+4−2
@@ -11,7 +11,7 @@
11-- experimental APIs.
11-- experimental APIs.
12
12
13module Streamly.Internal.Data.Stream.IsStream
13module Streamly.Internal.Data.Stream.IsStream
14− ( module Streamly.Internal.Data.Stream.IsStream.Types
14+ ( module Streamly.Internal.Data.Stream.IsStream.Type
15 , module Streamly.Internal.Data.Stream.IsStream.Generate
15 , module Streamly.Internal.Data.Stream.IsStream.Generate
16 , module Streamly.Internal.Data.Stream.IsStream.Eliminate
16 , module Streamly.Internal.Data.Stream.IsStream.Eliminate
17 , module Streamly.Internal.Data.Stream.IsStream.Transform
17 , module Streamly.Internal.Data.Stream.IsStream.Transform
@@ -31,4 +31,6 @@ import Streamly.Internal.Data.Stream.IsStream.Lift
31import Streamly.Internal.Data.Stream.IsStream.Expand
31import Streamly.Internal.Data.Stream.IsStream.Expand
32import Streamly.Internal.Data.Stream.IsStream.Reduce
32import Streamly.Internal.Data.Stream.IsStream.Reduce
33import Streamly.Internal.Data.Stream.IsStream.Transform
33import Streamly.Internal.Data.Stream.IsStream.Transform
34−import Streamly.Internal.Data.Stream.IsStream.Types
34+import Streamly.Internal.Data.Stream.IsStream.Type
35+ hiding (cmpBy, drain, eqBy, foldl', foldrM, foldr, fold, toList, toStream
36+ , fromEffect, fromPure, repeat)
src/Streamly/Internal/Data/Stream/IsStream/Combinators.hs+5−2
@@ -26,9 +26,12 @@ where
26import Control.Monad.IO.Class (MonadIO(liftIO))
26import Control.Monad.IO.Class (MonadIO(liftIO))
27import Data.Int (Int64)
27import Data.Int (Int64)
28
28
29−import Streamly.Internal.Data.SVar
29+import Streamly.Internal.Data.Stream.IsStream.Type
30−import Streamly.Internal.Data.Stream.StreamK.Type
30+ (IsStream, mkStream, foldStreamShared)
31import Streamly.Internal.Data.Stream.Serial (SerialT)
31import Streamly.Internal.Data.Stream.Serial (SerialT)
32+import Streamly.Internal.Data.Stream.StreamK.Type (Stream)
33+
34+import Streamly.Internal.Data.SVar
32
35
33-------------------------------------------------------------------------------
36-------------------------------------------------------------------------------
34-- Concurrency control
37-- Concurrency control
src/Streamly/Internal/Data/Stream/IsStream/Common.hs+128−15
@@ -26,6 +26,7 @@ module Streamly.Internal.Data.Stream.IsStream.Common
26 , fold_
26 , fold_
27
27
28 -- * Transformation
28 -- * Transformation
29+ , map
29 , scanlMAfter'
30 , scanlMAfter'
30 , postscanlM'
31 , postscanlM'
31 , smapM
32 , smapM
@@ -39,12 +40,21 @@ module Streamly.Internal.Data.Stream.IsStream.Common
39 , reverse
40 , reverse
40 , reverse'
41 , reverse'
41
42
43+ -- * Concurrent
44+ , mkAsync
45+ , mkParallel
46+ , parallelFst
47+
42 -- * Nesting
48 -- * Nesting
43 , concatM
49 , concatM
44 , concatMapM
50 , concatMapM
45 , concatMap
51 , concatMap
46 , splitOnSeq
52 , splitOnSeq
47
53
54+ -- * Zipping
55+ , zipWithM
56+ , zipWith
57+
48 -- * Deprecated
58 -- * Deprecated
49 , yield
59 , yield
50 , yieldM
60 , yieldM
@@ -60,15 +70,15 @@ import Streamly.Internal.Control.Concurrent (MonadAsync)
60import Streamly.Internal.Data.Array.Foreign.Type (Array)
70import Streamly.Internal.Data.Array.Foreign.Type (Array)
61import Streamly.Internal.Data.Fold.Type (Fold (..))
71import Streamly.Internal.Data.Fold.Type (Fold (..))
62import Streamly.Internal.Data.Stream.IsStream.Combinators (maxYields)
72import Streamly.Internal.Data.Stream.IsStream.Combinators (maxYields)
63−import Streamly.Internal.Data.Stream.Prelude (fromStreamS, toStreamS)
73+import Streamly.Internal.Data.Stream.IsStream.Type
74+ (IsStream(..), fromStreamD, toStreamD, fromStreamS, toStreamS)
64import Streamly.Internal.Data.Stream.Serial (SerialT)
75import Streamly.Internal.Data.Stream.Serial (SerialT)
65−import Streamly.Internal.Data.Stream.StreamD.Type (fromStreamD, toStreamD)
66−import Streamly.Internal.Data.Stream.StreamK.Type (IsStream())
67import Streamly.Internal.Data.Time.Units (AbsTime, RelTime64, addToAbsTime64)
76import Streamly.Internal.Data.Time.Units (AbsTime, RelTime64, addToAbsTime64)
68
77
78+import qualified Streamly.Internal.Data.Array.Foreign.Type as A
79+import qualified Streamly.Internal.Data.Stream.Async as Async
80+import qualified Streamly.Internal.Data.Stream.IsStream.Type as IsStream
69import qualified Streamly.Internal.Data.Stream.Parallel as Par
81import qualified Streamly.Internal.Data.Stream.Parallel as Par
70−import qualified Streamly.Internal.Data.Stream.Serial as Serial
71−import qualified Streamly.Internal.Data.Stream.StreamK as K (repeatM)
72import qualified Streamly.Internal.Data.Stream.StreamK.Type as K
82import qualified Streamly.Internal.Data.Stream.StreamK.Type as K
73import qualified Streamly.Internal.Data.Stream.StreamD as D
83import qualified Streamly.Internal.Data.Stream.StreamD as D
74#ifdef USE_STREAMK_ONLY
84#ifdef USE_STREAMK_ONLY
@@ -76,8 +86,9 @@ import qualified Streamly.Internal.Data.Stream.StreamK as S
76#else
86#else
77import qualified Streamly.Internal.Data.Stream.StreamD as S
87import qualified Streamly.Internal.Data.Stream.StreamD as S
78#endif
88#endif
89+import Streamly.Internal.System.IO (defaultChunkSize)
79
90
80−import Prelude hiding (take, takeWhile, drop, reverse, concatMap)
91+import Prelude hiding (take, takeWhile, drop, reverse, concatMap, map, zipWith)
81
92
82--
93--
83-- $setup
94-- $setup
@@ -124,7 +135,7 @@ import Prelude hiding (take, takeWhile, drop, reverse, concatMap)
124--
135--
125{-# INLINE fromPure #-}
136{-# INLINE fromPure #-}
126fromPure :: IsStream t => a -> t m a
137fromPure :: IsStream t => a -> t m a
127−fromPure = K.fromPure
138+fromPure = fromStream . K.fromPure
128
139
129-- | Same as 'fromPure'
140-- | Same as 'fromPure'
130--
141--
@@ -151,7 +162,7 @@ yield = fromPure
151--
162--
152{-# INLINE fromEffect #-}
163{-# INLINE fromEffect #-}
153fromEffect :: (Monad m, IsStream t) => m a -> t m a
164fromEffect :: (Monad m, IsStream t) => m a -> t m a
154−fromEffect = K.fromEffect
165+fromEffect = fromStream . K.fromEffect
155
166
156-- | Same as 'fromEffect'
167-- | Same as 'fromEffect'
157--
168--
@@ -179,7 +190,7 @@ yieldM = fromEffect
179-- @since 0.2.0
190-- @since 0.2.0
180{-# INLINE_EARLY repeatM #-}
191{-# INLINE_EARLY repeatM #-}
181repeatM :: (IsStream t, MonadAsync m) => m a -> t m a
192repeatM :: (IsStream t, MonadAsync m) => m a -> t m a
182−repeatM = K.repeatM
193+repeatM = K.repeatMWith IsStream.consM
183
194
184{-# RULES "repeatM serial" repeatM = repeatMSerial #-}
195{-# RULES "repeatM serial" repeatM = repeatMSerial #-}
185{-# INLINE repeatMSerial #-}
196{-# INLINE repeatMSerial #-}
@@ -286,13 +297,30 @@ fold fl strm = do
286{-# INLINE fold_ #-}
297{-# INLINE fold_ #-}
287fold_ :: Monad m => Fold m a b -> SerialT m a -> m (b, SerialT m a)
298fold_ :: Monad m => Fold m a b -> SerialT m a -> m (b, SerialT m a)
288fold_ fl strm = do
299fold_ fl strm = do
289− (b, str) <- D.fold_ fl $ D.toStreamD strm
300+ (b, str) <- D.fold_ fl $ IsStream.toStreamD strm
290− return $! (b, D.fromStreamD str)
301+ return $! (b, IsStream.fromStreamD str)
291
302
292------------------------------------------------------------------------------
303------------------------------------------------------------------------------
293-- Transformation
304-- Transformation
294------------------------------------------------------------------------------
305------------------------------------------------------------------------------
295
306
307+-- |
308+-- @
309+-- map = fmap
310+-- @
311+--
312+-- Same as 'fmap'.
313+--
314+-- @
315+-- > S.toList $ S.map (+1) $ S.fromList [1,2,3]
316+-- [2,3,4]
317+-- @
318+--
319+-- @since 0.4.0
320+{-# INLINE map #-}
321+map :: (IsStream t, Monad m) => (a -> b) -> t m a -> t m b
322+map f = fromStreamD . D.map f . toStreamD
323+
296-- | @scanlMAfter' accumulate initial done stream@ is like 'scanlM'' except
324-- | @scanlMAfter' accumulate initial done stream@ is like 'scanlM'' except
297-- that it provides an additional @done@ function to be applied on the
325-- that it provides an additional @done@ function to be applied on the
298-- accumulator when the stream stops. The result of @done@ is also emitted in
326-- accumulator when the stream stops. The result of @done@ is also emitted in
@@ -366,7 +394,7 @@ smapM step initial stream =
366 (\(s, _) a -> step s a)
394 (\(s, _) a -> step s a)
367 (fmap (,undefined) initial)
395 (fmap (,undefined) initial)
368 stream
396 stream
369− in Serial.map snd r
397+ in map snd r
370
398
371------------------------------------------------------------------------------
399------------------------------------------------------------------------------
372-- Transformation - Trimming
400-- Transformation - Trimming
@@ -439,7 +467,7 @@ intersperseM m = fromStreamS . S.intersperseM m . toStreamS
439interjectSuffix
467interjectSuffix
440 :: (IsStream t, MonadAsync m)
468 :: (IsStream t, MonadAsync m)
441 => Double -> m a -> t m a -> t m a
469 => Double -> m a -> t m a -> t m a
442−interjectSuffix n f xs = xs `Par.parallelFst` repeatM timed
470+interjectSuffix n f xs = xs `parallelFst` repeatM timed
443 where timed = liftIO (threadDelay (round $ n * 1000000)) >> f
471 where timed = liftIO (threadDelay (round $ n * 1000000)) >> f
444
472
445------------------------------------------------------------------------------
473------------------------------------------------------------------------------
@@ -469,7 +497,59 @@ reverse s = fromStreamS $ S.reverse $ toStreamS s
469-- /Pre-release/
497-- /Pre-release/
470{-# INLINE reverse' #-}
498{-# INLINE reverse' #-}
471reverse' :: (IsStream t, MonadIO m, Storable a) => t m a -> t m a
499reverse' :: (IsStream t, MonadIO m, Storable a) => t m a -> t m a
472−reverse' s = fromStreamD $ D.reverse' $ toStreamD s
500+-- reverse' s = fromStreamD $ D.reverse' $ toStreamD s
501+reverse' =
502+ fromStreamD
503+ . A.flattenArraysRev -- unfoldMany A.readRev
504+ . D.fromStreamK
505+ . K.reverse
506+ . D.toStreamK
507+ . A.arraysOf defaultChunkSize
508+ . toStreamD
509+
510+------------------------------------------------------------------------------
511+-- Concurrent Transformations and Combining
512+------------------------------------------------------------------------------
513+
514+-- | Make the stream producer and consumer run concurrently by introducing a
515+-- buffer between them. The producer thread evaluates the input stream until
516+-- the buffer fills, it terminates if the buffer is full and a worker thread is
517+-- kicked off again to evaluate the remaining stream when there is space in the
518+-- buffer. The consumer consumes the stream lazily from the buffer.
519+--
520+-- /Since: 0.2.0 (Streamly)/
521+--
522+-- @since 0.8.0
523+--
524+{-# INLINE_NORMAL mkAsync #-}
525+mkAsync :: (IsStream t, MonadAsync m) => t m a -> t m a
526+mkAsync = fromStreamD . Async.mkAsyncD . toStreamD
527+
528+-- Compare with mkAsync. mkAsync uses an Async style SVar whereas this uses a
529+-- parallel style SVar for evaluation. Currently, parallel style cannot use
530+-- rate control whereas Async style can use rate control. In async style SVar
531+-- the worker thread terminates when the buffer is full whereas in Parallel
532+-- style it blocks.
533+--
534+-- | Make the stream producer and consumer run concurrently by introducing a
535+-- buffer between them. The producer thread evaluates the input stream until
536+-- the buffer fills, it blocks if the buffer is full until there is space in
537+-- the buffer. The consumer consumes the stream lazily from the buffer.
538+--
539+-- @mkParallel = IsStream.fromStreamD . mkParallelD . IsStream.toStreamD@
540+--
541+-- /Pre-release/
542+--
543+{-# INLINE_NORMAL mkParallel #-}
544+mkParallel :: (IsStream t, MonadAsync m) => t m a -> t m a
545+mkParallel = fromStreamD . Par.mkParallelD . toStreamD
546+
547+-- | Like `parallel` but stops the output as soon as the first stream stops.
548+--
549+-- /Pre-release/
550+{-# INLINE parallelFst #-}
551+parallelFst :: (IsStream t, MonadAsync m) => t m a -> t m a -> t m a
552+parallelFst m1 m2 = fromStream $ Par.parallelFstK (toStream m1) (toStream m2)
473
553
474------------------------------------------------------------------------------
554------------------------------------------------------------------------------
475-- Combine streams and flatten
555-- Combine streams and flatten
@@ -575,4 +655,37 @@ concatM generator = concatMapM (\() -> generator) (fromPure ())
575splitOnSeq
655splitOnSeq
576 :: (IsStream t, MonadIO m, Storable a, Enum a, Eq a)
656 :: (IsStream t, MonadIO m, Storable a, Enum a, Eq a)
577 => Array a -> Fold m a b -> t m a -> t m b
657 => Array a -> Fold m a b -> t m a -> t m b
658+splitOnSeq patt f m =
578−splitOnSeq patt f m = D.fromStreamD $ D.splitOnSeq patt f (D.toStreamD m)
659+ IsStream.fromStreamD $ D.splitOnSeq patt f (IsStream.toStreamD m)
660+
661+------------------------------------------------------------------------------
662+-- Zipping
663+------------------------------------------------------------------------------
664+
665+-- | Like 'zipWith' but using a monadic zipping function.
666+--
667+-- @since 0.4.0
668+{-# INLINABLE zipWithM #-}
669+zipWithM :: (IsStream t, Monad m) => (a -> b -> m c) -> t m a -> t m b -> t m c
670+zipWithM f m1 m2 =
671+ IsStream.fromStreamS
672+ $ S.zipWithM f (IsStream.toStreamS m1) (IsStream.toStreamS m2)
673+
674+-- | Stream @a@ is evaluated first, followed by stream @b@, the resulting
675+-- elements @a@ and @b@ are then zipped using the supplied zip function and the
676+-- result @c@ is yielded to the consumer.
677+--
678+-- If stream @a@ or stream @b@ ends, the zipped stream ends. If stream @b@ ends
679+-- first, the element @a@ from previous evaluation of stream @a@ is discarded.
680+--
681+-- @
682+-- > S.toList $ S.zipWith (+) (S.fromList [1,2,3]) (S.fromList [4,5,6])
683+-- [5,7,9]
684+-- @
685+--
686+-- @since 0.1.0
687+{-# INLINABLE zipWith #-}
688+zipWith :: (IsStream t, Monad m) => (a -> b -> c) -> t m a -> t m b -> t m c
689+zipWith f m1 m2 =
690+ IsStream.fromStreamS
691+ $ S.zipWith f (IsStream.toStreamS m1) (IsStream.toStreamS m2)
src/Streamly/Internal/Data/Stream/IsStream/Eliminate.hs+49−25
@@ -45,6 +45,10 @@ module Streamly.Internal.Data.Stream.IsStream.Eliminate
45 , foldr
45 , foldr
46
46
47 -- * Left Folds
47 -- * Left Folds
48+ -- Lazy left folds are useful only for reversing the stream
49+ , foldlS
50+ , foldlT
51+
48 , foldl'
52 , foldl'
49 , foldl1'
53 , foldl1'
50 , foldlM'
54 , foldlM'
@@ -151,24 +155,23 @@ where
151
155
152import Control.Monad.Catch (MonadThrow)
156import Control.Monad.Catch (MonadThrow)
153import Control.Monad.IO.Class (MonadIO(..))
157import Control.Monad.IO.Class (MonadIO(..))
158+import Control.Monad.Trans.Class (MonadTrans(..))
154import Foreign.Storable (Storable)
159import Foreign.Storable (Storable)
155import Streamly.Internal.Control.Concurrent (MonadAsync)
160import Streamly.Internal.Control.Concurrent (MonadAsync)
156import Streamly.Internal.Data.Parser (Parser (..))
161import Streamly.Internal.Data.Parser (Parser (..))
157import Streamly.Internal.Data.SVar (defState)
162import Streamly.Internal.Data.SVar (defState)
158import Streamly.Internal.Data.Stream.IsStream.Common
163import Streamly.Internal.Data.Stream.IsStream.Common
159 ( fold, fold_, drop, findIndices, reverse, splitOnSeq, take
164 ( fold, fold_, drop, findIndices, reverse, splitOnSeq, take
160− , takeWhile)
165+ , takeWhile, mkParallel)
161−import Streamly.Internal.Data.Stream.Prelude (toStreamS)
166+import Streamly.Internal.Data.Stream.IsStream.Type
162−import Streamly.Internal.Data.Stream.StreamD (fromStreamD, toStreamD)
167+ (IsStream, toStreamS, fromStreamD, toStreamD)
163−import Streamly.Internal.Data.Stream.StreamK (IsStream)
168+import Streamly.Internal.Data.Stream.Serial (SerialT(..))
164−import Streamly.Internal.Data.Stream.Serial (SerialT)
165
169
166import qualified Streamly.Internal.Data.Array.Foreign.Type as A
170import qualified Streamly.Internal.Data.Array.Foreign.Type as A
167import qualified Streamly.Internal.Data.Fold as FL
171import qualified Streamly.Internal.Data.Fold as FL
168−import qualified Streamly.Internal.Data.Stream.Parallel as Par
172+import qualified Streamly.Internal.Data.Stream.IsStream.Type as IsStream
169−import qualified Streamly.Internal.Data.Stream.Prelude as P
170import qualified Streamly.Internal.Data.Stream.StreamD as D
173import qualified Streamly.Internal.Data.Stream.StreamD as D
171−import qualified Streamly.Internal.Data.Stream.StreamK as K
174+import qualified Streamly.Internal.Data.Stream.StreamK.Type as K
172import qualified Streamly.Internal.Data.Parser.ParserD as PRD
175import qualified Streamly.Internal.Data.Parser.ParserD as PRD
173import qualified Streamly.Internal.Data.Parser.ParserK.Type as PRK
176import qualified Streamly.Internal.Data.Parser.ParserK.Type as PRK
174import qualified System.IO as IO
177import qualified System.IO as IO
@@ -212,7 +215,7 @@ import Prelude hiding
212-- @since 0.1.0
215-- @since 0.1.0
213{-# INLINE uncons #-}
216{-# INLINE uncons #-}
214uncons :: (IsStream t, Monad m) => SerialT m a -> m (Maybe (a, t m a))
217uncons :: (IsStream t, Monad m) => SerialT m a -> m (Maybe (a, t m a))
215−uncons m = K.uncons (K.adapt m)
218+uncons (SerialT m) = fmap (fmap (fmap IsStream.fromStream)) $ K.uncons m
216
219
217------------------------------------------------------------------------------
220------------------------------------------------------------------------------
218-- Right Folds
221-- Right Folds
@@ -240,7 +243,7 @@ uncons m = K.uncons (K.adapt m)
240-- /Since: 0.1.0/
243-- /Since: 0.1.0/
241{-# INLINE foldrM #-}
244{-# INLINE foldrM #-}
242foldrM :: Monad m => (a -> m b -> m b) -> m b -> SerialT m a -> m b
245foldrM :: Monad m => (a -> m b -> m b) -> m b -> SerialT m a -> m b
243−foldrM = P.foldrM
246+foldrM = IsStream.foldrM
244
247
245-- | Right fold, lazy for lazy monads and pure streams, and strict for strict
248-- | Right fold, lazy for lazy monads and pure streams, and strict for strict
246-- monads.
249-- monads.
@@ -255,7 +258,7 @@ foldrM = P.foldrM
255-- @since 0.1.0
258-- @since 0.1.0
256{-# INLINE foldr #-}
259{-# INLINE foldr #-}
257foldr :: Monad m => (a -> b -> b) -> b -> SerialT m a -> m b
260foldr :: Monad m => (a -> b -> b) -> b -> SerialT m a -> m b
258−foldr = P.foldr
261+foldr = IsStream.foldr
259
262
260-- XXX This seems to be of limited use as it cannot be used to construct
263-- XXX This seems to be of limited use as it cannot be used to construct
261-- recursive structures and for reduction foldl1' is better.
264-- recursive structures and for reduction foldl1' is better.
@@ -273,6 +276,27 @@ foldr1 f m = S.foldr1 f (toStreamS m)
273-- Left Folds
276-- Left Folds
274------------------------------------------------------------------------------
277------------------------------------------------------------------------------
275
278
279+-- | Lazy left fold to a stream.
280+{-# INLINE foldlS #-}
281+foldlS :: IsStream t => (t m b -> a -> t m b) -> t m b -> t m a -> t m b
282+foldlS f z =
283+ IsStream.fromStream
284+ . K.foldlS
285+ (\xs x -> IsStream.toStream $ f (IsStream.fromStream xs) x)
286+ (IsStream.toStream z)
287+ . IsStream.toStream
288+
289+-- | Lazy left fold to a transformer monad.
290+--
291+-- For example, to reverse a stream:
292+--
293+-- > S.toList $ S.foldlT (flip S.cons) S.nil $ (S.fromList [1..5] :: SerialT IO Int)
294+--
295+{-# INLINE foldlT #-}
296+foldlT :: (Monad m, IsStream t, Monad (s m), MonadTrans s)
297+ => (s m b -> a -> s m b) -> s m b -> t m a -> s m b
298+foldlT f z s = S.foldlT f z (toStreamS s)
299+
276-- | Strict left fold with an extraction function. Like the standard strict
300-- | Strict left fold with an extraction function. Like the standard strict
277-- left fold, but applies a user supplied extraction function (the third
301-- left fold, but applies a user supplied extraction function (the third
278-- argument) to the folded value at the end. This is designed to work with the
302-- argument) to the folded value at the end. This is designed to work with the
@@ -282,7 +306,7 @@ foldr1 f m = S.foldr1 f (toStreamS m)
282{-# DEPRECATED foldx "Please use foldl' followed by fmap instead." #-}
306{-# DEPRECATED foldx "Please use foldl' followed by fmap instead." #-}
283{-# INLINE foldx #-}
307{-# INLINE foldx #-}
284foldx :: Monad m => (x -> a -> x) -> x -> (x -> b) -> SerialT m a -> m b
308foldx :: Monad m => (x -> a -> x) -> x -> (x -> b) -> SerialT m a -> m b
285−foldx = P.foldlx'
309+foldx = IsStream.foldlx'
286
310
287-- | Left associative/strict push fold. @foldl' reduce initial stream@ invokes
311-- | Left associative/strict push fold. @foldl' reduce initial stream@ invokes
288-- @reduce@ with the accumulator and the next input in the input stream, using
312-- @reduce@ with the accumulator and the next input in the input stream, using
@@ -295,7 +319,7 @@ foldx = P.foldlx'
295-- @since 0.2.0
319-- @since 0.2.0
296{-# INLINE foldl' #-}
320{-# INLINE foldl' #-}
297foldl' :: Monad m => (b -> a -> b) -> b -> SerialT m a -> m b
321foldl' :: Monad m => (b -> a -> b) -> b -> SerialT m a -> m b
298−foldl' = P.foldl'
322+foldl' = IsStream.foldl'
299
323
300-- | Strict left fold, for non-empty streams, using first element as the
324-- | Strict left fold, for non-empty streams, using first element as the
301-- starting value. Returns 'Nothing' if the stream is empty.
325-- starting value. Returns 'Nothing' if the stream is empty.
@@ -317,7 +341,7 @@ foldl1' step m = do
317{-# DEPRECATED foldxM "Please use foldlM' followed by fmap instead." #-}
341{-# DEPRECATED foldxM "Please use foldlM' followed by fmap instead." #-}
318{-# INLINE foldxM #-}
342{-# INLINE foldxM #-}
319foldxM :: Monad m => (x -> a -> m x) -> m x -> (x -> m b) -> SerialT m a -> m b
343foldxM :: Monad m => (x -> a -> m x) -> m x -> (x -> m b) -> SerialT m a -> m b
320−foldxM = P.foldlMx'
344+foldxM = IsStream.foldlMx'
321
345
322-- | Like 'foldl'' but with a monadic step function.
346-- | Like 'foldl'' but with a monadic step function.
323--
347--
@@ -422,7 +446,7 @@ mapM_ f m = S.mapM_ f $ toStreamS m
422-- @since 0.7.0
446-- @since 0.7.0
423{-# INLINE drain #-}
447{-# INLINE drain #-}
424drain :: Monad m => SerialT m a -> m ()
448drain :: Monad m => SerialT m a -> m ()
425−drain = P.drain
449+drain = IsStream.drain
426
450
427-- |
451-- |
428-- > drainN n = Stream.drain . Stream.take n
452-- > drainN n = Stream.drain . Stream.take n
@@ -513,14 +537,14 @@ headElse x = D.headElse x . toStreamD
513-- @since 0.1.1
537-- @since 0.1.1
514{-# INLINE tail #-}
538{-# INLINE tail #-}
515tail :: (IsStream t, Monad m) => SerialT m a -> m (Maybe (t m a))
539tail :: (IsStream t, Monad m) => SerialT m a -> m (Maybe (t m a))
516−tail m = K.tail (K.adapt m)
540+tail (SerialT m) = fmap (fmap IsStream.fromStream) $ K.tail m
517
541
518-- | Extract all but the last element of the stream, if any.
542-- | Extract all but the last element of the stream, if any.
519--
543--
520-- @since 0.5.0
544-- @since 0.5.0
521{-# INLINE init #-}
545{-# INLINE init #-}
522init :: (IsStream t, Monad m) => SerialT m a -> m (Maybe (t m a))
546init :: (IsStream t, Monad m) => SerialT m a -> m (Maybe (t m a))
523−init m = K.init (K.adapt m)
547+init (SerialT m) = fmap (fmap IsStream.fromStream) $ K.init m
524
548
525-- | Extract the last element of the stream, if any.
549-- | Extract the last element of the stream, if any.
526--
550--
@@ -657,7 +681,7 @@ minimumBy cmp m = S.minimumBy cmp (toStreamS m)
657-- @since 0.1.0
681-- @since 0.1.0
658{-# INLINE maximum #-}
682{-# INLINE maximum #-}
659maximum :: (Monad m, Ord a) => SerialT m a -> m (Maybe a)
683maximum :: (Monad m, Ord a) => SerialT m a -> m (Maybe a)
660−maximum = P.maximum
684+maximum m = S.maximum (toStreamS m)
661
685
662-- | Determine the maximum element in a stream using the supplied comparison
686-- | Determine the maximum element in a stream using the supplied comparison
663-- function.
687-- function.
@@ -755,7 +779,7 @@ elemIndex a = findIndex (== a)
755-- @since 0.1.0
779-- @since 0.1.0
756{-# INLINE toList #-}
780{-# INLINE toList #-}
757toList :: Monad m => SerialT m a -> m [a]
781toList :: Monad m => SerialT m a -> m [a]
758−toList = P.toList
782+toList = IsStream.toList
759
783
760-- |
784-- |
761-- @
785-- @
@@ -789,7 +813,7 @@ toHandle h = go
789 let stop = return ()
813 let stop = return ()
790 single a = liftIO (IO.hPutStrLn h a)
814 single a = liftIO (IO.hPutStrLn h a)
791 yieldk a r = liftIO (IO.hPutStrLn h a) >> go r
815 yieldk a r = liftIO (IO.hPutStrLn h a) >> go r
792− in K.foldStream defState yieldk single stop m1
816+ in IsStream.foldStream defState yieldk single stop m1
793
817
794-- | Convert a stream to a pure stream.
818-- | Convert a stream to a pure stream.
795--
819--
@@ -801,7 +825,7 @@ toHandle h = go
801--
825--
802{-# INLINE toStream #-}
826{-# INLINE toStream #-}
803toStream :: Monad m => SerialT m a -> m (SerialT n a)
827toStream :: Monad m => SerialT m a -> m (SerialT n a)
804−toStream = foldr K.cons K.nil
828+toStream = foldr IsStream.cons IsStream.nil
805
829
806-- | Convert a stream to a pure stream in reverse order.
830-- | Convert a stream to a pure stream in reverse order.
807--
831--
@@ -813,7 +837,7 @@ toStream = foldr K.cons K.nil
813--
837--
814{-# INLINE toStreamRev #-}
838{-# INLINE toStreamRev #-}
815toStreamRev :: Monad m => SerialT m a -> m (SerialT n a)
839toStreamRev :: Monad m => SerialT m a -> m (SerialT n a)
816−toStreamRev = foldl' (flip K.cons) K.nil
840+toStreamRev = foldl' (flip IsStream.cons) IsStream.nil
817
841
818------------------------------------------------------------------------------
842------------------------------------------------------------------------------
819-- Concurrent Application
843-- Concurrent Application
@@ -853,7 +877,7 @@ toStreamRev = foldl' (flip K.cons) K.nil
853{-# INLINE (|$.) #-}
877{-# INLINE (|$.) #-}
854(|$.) :: (IsStream t, MonadAsync m) => (t m a -> m b) -> (t m a -> m b)
878(|$.) :: (IsStream t, MonadAsync m) => (t m a -> m b) -> (t m a -> m b)
855-- (|$.) f = f . Async.mkAsync
879-- (|$.) f = f . Async.mkAsync
856−(|$.) f = f . Par.mkParallel
880+(|$.) f = f . mkParallel
857
881
858infixr 0 |$.
882infixr 0 |$.
859
883
@@ -1009,7 +1033,7 @@ stripSuffix m1 m2 = fmap reverse <$> stripPrefix (reverse m1) (reverse m2)
1009-- @since 0.6.0
1033-- @since 0.6.0
1010{-# INLINABLE eqBy #-}
1034{-# INLINABLE eqBy #-}
1011eqBy :: (IsStream t, Monad m) => (a -> b -> Bool) -> t m a -> t m b -> m Bool
1035eqBy :: (IsStream t, Monad m) => (a -> b -> Bool) -> t m a -> t m b -> m Bool
1012−eqBy = P.eqBy
1036+eqBy = IsStream.eqBy
1013
1037
1014-- | Compare two streams lexicographically using a comparison function.
1038-- | Compare two streams lexicographically using a comparison function.
1015--
1039--
@@ -1018,4 +1042,4 @@ eqBy = P.eqBy
1018cmpBy
1042cmpBy
1019 :: (IsStream t, Monad m)
1043 :: (IsStream t, Monad m)
1020 => (a -> b -> Ordering) -> t m a -> t m b -> m Ordering
1044 => (a -> b -> Ordering) -> t m a -> t m b -> m Ordering
1021−cmpBy = P.cmpBy
1045+cmpBy = IsStream.cmpBy
src/Streamly/Internal/Data/Stream/IsStream/Enumeration.hs+20−13
@@ -60,9 +60,9 @@ import Data.Word
60import Numeric.Natural
60import Numeric.Natural
61import Data.Functor.Identity (Identity(..))
61import Data.Functor.Identity (Identity(..))
62
62
63−import Streamly.Internal.Data.Stream.StreamD.Type (fromStreamD)
63+import Streamly.Internal.Data.Stream.IsStream.Type (IsStream(..), fromStreamD)
64−import Streamly.Internal.Data.Stream.StreamK.Type (IsStream(..))
65
64
65+import qualified Streamly.Internal.Data.Stream.IsStream.Type as IsStream
66import qualified Streamly.Internal.Data.Stream.StreamD.Generate as D
66import qualified Streamly.Internal.Data.Stream.StreamD.Generate as D
67import qualified Streamly.Internal.Data.Stream.Serial as Serial (map)
67import qualified Streamly.Internal.Data.Stream.Serial as Serial (map)
68
68
@@ -292,8 +292,10 @@ enumerateFromThenToFractional from next to =
292-- @since 0.6.0
292-- @since 0.6.0
293{-# INLINE enumerateFromToSmall #-}
293{-# INLINE enumerateFromToSmall #-}
294enumerateFromToSmall :: (IsStream t, Monad m, Enum a) => a -> a -> t m a
294enumerateFromToSmall :: (IsStream t, Monad m, Enum a) => a -> a -> t m a
295−enumerateFromToSmall from to = Serial.map toEnum $
295+enumerateFromToSmall from to =
296+ IsStream.fromSerial
297+ $ Serial.map toEnum
296− enumerateFromToIntegral (fromEnum from) (fromEnum to)
298+ $ enumerateFromToIntegral (fromEnum from) (fromEnum to)
297
299
298-- | 'enumerateFromThenTo' for 'Enum' types not larger than 'Int'.
300-- | 'enumerateFromThenTo' for 'Enum' types not larger than 'Int'.
299--
301--
@@ -301,8 +303,11 @@ enumerateFromToSmall from to = Serial.map toEnum $
301{-# INLINE enumerateFromThenToSmall #-}
303{-# INLINE enumerateFromThenToSmall #-}
302enumerateFromThenToSmall :: (IsStream t, Monad m, Enum a)
304enumerateFromThenToSmall :: (IsStream t, Monad m, Enum a)
303 => a -> a -> a -> t m a
305 => a -> a -> a -> t m a
304−enumerateFromThenToSmall from next to = Serial.map toEnum $
306+enumerateFromThenToSmall from next to =
307+ IsStream.fromSerial
308+ $ Serial.map toEnum
309+ $ enumerateFromThenToIntegral
305− enumerateFromThenToIntegral (fromEnum from) (fromEnum next) (fromEnum to)
310+ (fromEnum from) (fromEnum next) (fromEnum to)
306
311
307-- | 'enumerateFromThen' for 'Enum' types not larger than 'Int'.
312-- | 'enumerateFromThen' for 'Enum' types not larger than 'Int'.
308--
313--
@@ -550,17 +555,19 @@ ENUMERABLE_FRACTIONAL((Ratio a),Integral a)
550
555
551instance Enumerable a => Enumerable (Identity a) where
556instance Enumerable a => Enumerable (Identity a) where
552 {-# INLINE enumerateFrom #-}
557 {-# INLINE enumerateFrom #-}
553− enumerateFrom (Identity from) = Serial.map Identity $
558+ enumerateFrom (Identity from) =
554− enumerateFrom from
559+ IsStream.fromSerial $ Serial.map Identity $ enumerateFrom from
555 {-# INLINE enumerateFromThen #-}
560 {-# INLINE enumerateFromThen #-}
556− enumerateFromThen (Identity from) (Identity next) = Serial.map Identity $
561+ enumerateFromThen (Identity from) (Identity next) =
557− enumerateFromThen from next
562+ IsStream.fromSerial $ Serial.map Identity $ enumerateFromThen from next
558 {-# INLINE enumerateFromTo #-}
563 {-# INLINE enumerateFromTo #-}
559− enumerateFromTo (Identity from) (Identity to) = Serial.map Identity $
564+ enumerateFromTo (Identity from) (Identity to) =
560− enumerateFromTo from to
565+ IsStream.fromSerial $ Serial.map Identity $ enumerateFromTo from to
561 {-# INLINE enumerateFromThenTo #-}
566 {-# INLINE enumerateFromThenTo #-}
562 enumerateFromThenTo (Identity from) (Identity next) (Identity to) =
567 enumerateFromThenTo (Identity from) (Identity next) (Identity to) =
568+ IsStream.fromSerial
569+ $ Serial.map Identity
563− Serial.map Identity $ enumerateFromThenTo from next to
570+ $ enumerateFromThenTo from next to
564
571
565-- TODO
572-- TODO
566{-
573{-
src/Streamly/Internal/Data/Stream/IsStream/Exception.hs+15−15
@@ -29,8 +29,8 @@ import Control.Monad.IO.Class (MonadIO(..))
29import Control.Monad.Trans.Control (MonadBaseControl)
29import Control.Monad.Trans.Control (MonadBaseControl)
30import Data.Map.Strict (Map)
30import Data.Map.Strict (Map)
31import Streamly.Internal.Control.Concurrent (MonadAsync)
31import Streamly.Internal.Control.Concurrent (MonadAsync)
32−import Streamly.Internal.Data.Stream.StreamD (toStreamD)
32+import Streamly.Internal.Data.Stream.IsStream.Type
33−import Streamly.Internal.Data.Stream.StreamK (IsStream)
33+ (IsStream(..), fromStreamD, toStreamD)
34
34
35import qualified Streamly.Internal.Data.Stream.StreamD as D
35import qualified Streamly.Internal.Data.Stream.StreamD as D
36
36
@@ -53,7 +53,7 @@ import qualified Streamly.Internal.Data.Stream.StreamD as D
53-- @since 0.7.0
53-- @since 0.7.0
54{-# INLINE before #-}
54{-# INLINE before #-}
55before :: (IsStream t, Monad m) => m b -> t m a -> t m a
55before :: (IsStream t, Monad m) => m b -> t m a -> t m a
56−before action xs = D.fromStreamD $ D.before action $ D.toStreamD xs
56+before action xs = fromStreamD $ D.before action $ toStreamD xs
57
57
58-- | Like 'after', with following differences:
58-- | Like 'after', with following differences:
59--
59--
@@ -70,7 +70,7 @@ before action xs = D.fromStreamD $ D.before action $ D.toStreamD xs
70--
70--
71{-# INLINE after_ #-}
71{-# INLINE after_ #-}
72after_ :: (IsStream t, Monad m) => m b -> t m a -> t m a
72after_ :: (IsStream t, Monad m) => m b -> t m a -> t m a
73−after_ action xs = D.fromStreamD $ D.after_ action $ D.toStreamD xs
73+after_ action xs = fromStreamD $ D.after_ action $ toStreamD xs
74
74
75-- | Run the action @m b@ whenever the stream @t m a@ stops normally, or if it
75-- | Run the action @m b@ whenever the stream @t m a@ stops normally, or if it
76-- is garbage collected after a partial lazy evaluation.
76-- is garbage collected after a partial lazy evaluation.
@@ -85,7 +85,7 @@ after_ action xs = D.fromStreamD $ D.after_ action $ D.toStreamD xs
85{-# INLINE after #-}
85{-# INLINE after #-}
86after :: (IsStream t, MonadIO m, MonadBaseControl IO m)
86after :: (IsStream t, MonadIO m, MonadBaseControl IO m)
87 => m b -> t m a -> t m a
87 => m b -> t m a -> t m a
88−after action xs = D.fromStreamD $ D.after action $ D.toStreamD xs
88+after action xs = fromStreamD $ D.after action $ toStreamD xs
89
89
90-- | Run the action @m b@ if the stream aborts due to an exception. The
90-- | Run the action @m b@ if the stream aborts due to an exception. The
91-- exception is not caught, simply rethrown.
91-- exception is not caught, simply rethrown.
@@ -95,7 +95,7 @@ after action xs = D.fromStreamD $ D.after action $ D.toStreamD xs
95-- @since 0.7.0
95-- @since 0.7.0
96{-# INLINE onException #-}
96{-# INLINE onException #-}
97onException :: (IsStream t, MonadCatch m) => m b -> t m a -> t m a
97onException :: (IsStream t, MonadCatch m) => m b -> t m a -> t m a
98−onException action xs = D.fromStreamD $ D.onException action $ D.toStreamD xs
98+onException action xs = fromStreamD $ D.onException action $ toStreamD xs
99
99
100-- | Like 'finally' with following differences:
100-- | Like 'finally' with following differences:
101--
101--
@@ -110,7 +110,7 @@ onException action xs = D.fromStreamD $ D.onException action $ D.toStreamD xs
110--
110--
111{-# INLINE finally_ #-}
111{-# INLINE finally_ #-}
112finally_ :: (IsStream t, MonadCatch m) => m b -> t m a -> t m a
112finally_ :: (IsStream t, MonadCatch m) => m b -> t m a -> t m a
113−finally_ action xs = D.fromStreamD $ D.finally_ action $ D.toStreamD xs
113+finally_ action xs = fromStreamD $ D.finally_ action $ toStreamD xs
114
114
115-- | Run the action @m b@ whenever the stream @t m a@ stops normally, aborts
115-- | Run the action @m b@ whenever the stream @t m a@ stops normally, aborts
116-- due to an exception or if it is garbage collected after a partial lazy
116-- due to an exception or if it is garbage collected after a partial lazy
@@ -131,7 +131,7 @@ finally_ action xs = D.fromStreamD $ D.finally_ action $ D.toStreamD xs
131--
131--
132{-# INLINE finally #-}
132{-# INLINE finally #-}
133finally :: (IsStream t, MonadAsync m, MonadCatch m) => m b -> t m a -> t m a
133finally :: (IsStream t, MonadAsync m, MonadCatch m) => m b -> t m a -> t m a
134−finally action xs = D.fromStreamD $ D.finally action $ D.toStreamD xs
134+finally action xs = fromStreamD $ D.finally action $ toStreamD xs
135
135
136-- | Like 'bracket' but with following differences:
136-- | Like 'bracket' but with following differences:
137--
137--
@@ -148,7 +148,7 @@ finally action xs = D.fromStreamD $ D.finally action $ D.toStreamD xs
148{-# INLINE bracket_ #-}
148{-# INLINE bracket_ #-}
149bracket_ :: (IsStream t, MonadCatch m)
149bracket_ :: (IsStream t, MonadCatch m)
150 => m b -> (b -> m c) -> (b -> t m a) -> t m a
150 => m b -> (b -> m c) -> (b -> t m a) -> t m a
151−bracket_ bef aft bet = D.fromStreamD $
151+bracket_ bef aft bet = fromStreamD $
152 D.bracket_ bef aft (toStreamD . bet)
152 D.bracket_ bef aft (toStreamD . bet)
153
153
154-- | Run the alloc action @m b@ with async exceptions disabled but keeping
154-- | Run the alloc action @m b@ with async exceptions disabled but keeping
@@ -193,7 +193,7 @@ bracket bef aft = bracket' bef aft aft aft
193{-# INLINE bracket' #-}
193{-# INLINE bracket' #-}
194bracket' :: (IsStream t, MonadAsync m, MonadCatch m)
194bracket' :: (IsStream t, MonadAsync m, MonadCatch m)
195 => m b -> (b -> m c) -> (b -> m d) -> (b -> m e) -> (b -> t m a) -> t m a
195 => m b -> (b -> m c) -> (b -> m d) -> (b -> m e) -> (b -> t m a) -> t m a
196−bracket' bef aft gc exc bet = D.fromStreamD $
196+bracket' bef aft gc exc bet = fromStreamD $
197 D.bracket' bef aft exc gc (toStreamD . bet)
197 D.bracket' bef aft exc gc (toStreamD . bet)
198
198
199-- | Like 'handle' but the exception handler is also provided with the stream
199-- | Like 'handle' but the exception handler is also provided with the stream
@@ -212,9 +212,9 @@ bracket' bef aft gc exc bet = D.fromStreamD $
212ghandle :: (IsStream t, MonadCatch m, Exception e)
212ghandle :: (IsStream t, MonadCatch m, Exception e)
213 => (e -> t m a -> t m a) -> t m a -> t m a
213 => (e -> t m a -> t m a) -> t m a -> t m a
214ghandle handler =
214ghandle handler =
215− D.fromStreamD
215+ fromStreamD
216− . D.ghandle (\e xs -> D.toStreamD $ handler e (D.fromStreamD xs))
216+ . D.ghandle (\e xs -> toStreamD $ handler e (fromStreamD xs))
217− . D.toStreamD
217+ . toStreamD
218
218
219-- | When evaluating a stream if an exception occurs, stream evaluation aborts
219-- | When evaluating a stream if an exception occurs, stream evaluation aborts
220-- and the specified exception handler is run with the exception as argument.
220-- and the specified exception handler is run with the exception as argument.
@@ -226,7 +226,7 @@ ghandle handler =
226handle :: (IsStream t, MonadCatch m, Exception e)
226handle :: (IsStream t, MonadCatch m, Exception e)
227 => (e -> t m a) -> t m a -> t m a
227 => (e -> t m a) -> t m a -> t m a
228handle handler xs =
228handle handler xs =
229− D.fromStreamD $ D.handle (D.toStreamD . handler) $ D.toStreamD xs
229+ fromStreamD $ D.handle (toStreamD . handler) $ toStreamD xs
230
230
231
231
232-- | @retry@ takes 3 arguments
232-- | @retry@ takes 3 arguments
@@ -269,4 +269,4 @@ retry :: (IsStream t, MonadCatch m, Exception e, Ord e)
269 -> t m a
269 -> t m a
270 -> t m a
270 -> t m a
271retry emap handler inp =
271retry emap handler inp =
272− D.fromStreamD $ D.retry emap (D.toStreamD . handler) $ D.toStreamD inp
272+ fromStreamD $ D.retry emap (toStreamD . handler) $ toStreamD inp
src/Streamly/Internal/Data/Stream/IsStream/Expand.hs+397−61
@@ -30,8 +30,8 @@ module Streamly.Internal.Data.Stream.IsStream.Expand
30 , async
30 , async
31 , wAsync
31 , wAsync
32 , parallel
32 , parallel
33− , Par.parallelFst
33+ , parallelFst
34− , Par.parallelMin
34+ , parallelMin
35
35
36 -- * Binary Combinators (Pair Wise)
36 -- * Binary Combinators (Pair Wise)
37 -- | Like the functions in the section above these functions also combine
37 -- | Like the functions in the section above these functions also combine
@@ -68,10 +68,10 @@ module Streamly.Internal.Data.Stream.IsStream.Expand
68 , roundrobin
68 , roundrobin
69
69
70 -- ** Zip
70 -- ** Zip
71− , Z.zipWith
71+ , zipWith
72− , Z.zipWithM
72+ , zipWithM
73− , Z.zipAsyncWith
73+ , zipAsyncWith
74− , Z.zipAsyncWithM
74+ , zipAsyncWithM
75
75
76 -- ** Merge
76 -- ** Merge
77 -- , merge
77 -- , merge
@@ -120,9 +120,9 @@ module Streamly.Internal.Data.Stream.IsStream.Expand
120 -- * Flatten Containers
120 -- * Flatten Containers
121 -- | Flatten 'Foldable' containers using the binary stream merging
121 -- | Flatten 'Foldable' containers using the binary stream merging
122 -- operations.
122 -- operations.
123− , concatFoldableWith
123+ , IsStream.concatFoldableWith
124− , concatMapFoldableWith
124+ , IsStream.concatMapFoldableWith
125− , concatForFoldableWith
125+ , IsStream.concatForFoldableWith
126
126
127 -- * ConcatMapWith
127 -- * ConcatMapWith
128 -- | Map and flatten a stream like 'concatMap' but using a custom binary
128 -- | Map and flatten a stream like 'concatMap' but using a custom binary
@@ -136,8 +136,8 @@ module Streamly.Internal.Data.Stream.IsStream.Expand
136 -- fashion, a pair wise merging using 'concatPairsWith' would be more
136 -- fashion, a pair wise merging using 'concatPairsWith' would be more
137 -- efficient. These cases include operations like 'mergeBy' or 'zipWith'.
137 -- efficient. These cases include operations like 'mergeBy' or 'zipWith'.
138
138
139− , concatMapWith
139+ , IsStream.concatMapWith
140− , K.bindWith
140+ , IsStream.bindWith
141 , concatSmapMWith
141 , concatSmapMWith
142
142
143 -- * ConcatPairsWith
143 -- * ConcatPairsWith
@@ -153,49 +153,56 @@ module Streamly.Internal.Data.Stream.IsStream.Expand
153
153
154 -- * Deprecated
154 -- * Deprecated
155 , concatUnfold
155 , concatUnfold
156+ , (<=>)
157+ , (<|)
156 )
158 )
157where
159where
158
160
159#include "inline.hs"
161#include "inline.hs"
160
162
161import Streamly.Internal.Control.Concurrent (MonadAsync)
163import Streamly.Internal.Control.Concurrent (MonadAsync)
162−import Streamly.Internal.Data.Stream.Ahead (ahead)
164+import Streamly.Internal.Data.Stream.Ahead (aheadK)
163−import Streamly.Internal.Data.Stream.Async (async, wAsync)
165+import Streamly.Internal.Data.Stream.Async (asyncK, wAsyncK)
164import Streamly.Internal.Data.Stream.IsStream.Common
166import Streamly.Internal.Data.Stream.IsStream.Common
165− (concatM, concatMapM, concatMap, smapM, fromPure, fromEffect)
167+ ( concatM, concatMapM, concatMap, smapM, fromPure, fromEffect, parallelFst
166−import Streamly.Internal.Data.Stream.Parallel (parallel)
168+ , zipWith, zipWithM)
167−import Streamly.Internal.Data.Stream.Prelude
169+import Streamly.Internal.Data.Stream.IsStream.Type
168− ( concatFoldableWith, concatMapFoldableWith
169− , concatForFoldableWith, fromStreamS, toStreamS)
170+ (IsStream(..), fromStreamS, toStreamS, fromStreamD, toStreamD)
170−import Streamly.Internal.Data.Stream.Serial (serial, wSerial)
171−import Streamly.Internal.Data.Stream.StreamD (fromStreamD, toStreamD)
172−import Streamly.Internal.Data.Stream.StreamK (IsStream)
173import Streamly.Internal.Data.Unfold.Type (Unfold)
171import Streamly.Internal.Data.Unfold.Type (Unfold)
174
172
173+import qualified Streamly.Internal.Data.Stream.IsStream.Type as IsStream
175import qualified Streamly.Internal.Data.Stream.Parallel as Par
174import qualified Streamly.Internal.Data.Stream.Parallel as Par
176import qualified Streamly.Internal.Data.Stream.Serial as Serial
175import qualified Streamly.Internal.Data.Stream.Serial as Serial
177import qualified Streamly.Internal.Data.Stream.StreamD as D
176import qualified Streamly.Internal.Data.Stream.StreamD as D
178−import qualified Streamly.Internal.Data.Stream.StreamK as K
177+import qualified Streamly.Internal.Data.Stream.StreamK.Type as K
179#ifdef USE_STREAMK_ONLY
178#ifdef USE_STREAMK_ONLY
180import qualified Streamly.Internal.Data.Stream.StreamK as S
179import qualified Streamly.Internal.Data.Stream.StreamK as S
181#else
180#else
182import qualified Streamly.Internal.Data.Stream.StreamD as S
181import qualified Streamly.Internal.Data.Stream.StreamD as S
183#endif
182#endif
184−import qualified Streamly.Internal.Data.Stream.Zip as Z
183+import qualified Streamly.Internal.Data.Stream.Zip as Zip
185
184
186−import Prelude hiding (concat, concatMap)
185+import Prelude hiding (concat, concatMap, zipWith)
187
186
188-- $setup
187-- $setup
189-- >>> :m
188-- >>> :m
189+-- >>> import Control.Concurrent (threadDelay)
190-- >>> import Data.IORef
190-- >>> import Data.IORef
191-- >>> import Prelude hiding (zipWith, concatMap, concat)
191-- >>> import Prelude hiding (zipWith, concatMap, concat)
192-- >>> import qualified Streamly.Prelude as Stream
192-- >>> import qualified Streamly.Prelude as Stream
193−-- >>> import Streamly.Internal.Data.Stream.IsStream as Stream
193+-- >>> import qualified Streamly.Internal.Data.Stream.IsStream as Stream
194-- >>> import qualified Streamly.Data.Fold as Fold
194-- >>> import qualified Streamly.Data.Fold as Fold
195-- >>> import qualified Streamly.Internal.Data.Fold as Fold
195-- >>> import qualified Streamly.Internal.Data.Fold as Fold
196-- >>> import qualified Streamly.Internal.Data.Unfold as Unfold
196-- >>> import qualified Streamly.Internal.Data.Unfold as Unfold
197-- >>> import qualified Streamly.Internal.Data.Parser as Parser
197-- >>> import qualified Streamly.Internal.Data.Parser as Parser
198-- >>> import qualified Streamly.Data.Array.Foreign as Array
198-- >>> import qualified Streamly.Data.Array.Foreign as Array
199+-- >>> :{
200+-- delay n = do
201+-- threadDelay (n * 1000000) -- sleep for n seconds
202+-- putStrLn (show n ++ " sec") -- print "n sec"
203+-- return n -- IO Int
204+-- :}
205+--
199
206
200-------------------------------------------------------------------------------
207-------------------------------------------------------------------------------
201-- Appending
208-- Appending
@@ -218,10 +225,79 @@ import Prelude hiding (concat, concatMap)
218append ::(IsStream t, Monad m) => t m b -> t m b -> t m b
225append ::(IsStream t, Monad m) => t m b -> t m b -> t m b
219append m1 m2 = fromStreamD $ D.append (toStreamD m1) (toStreamD m2)
226append m1 m2 = fromStreamD $ D.append (toStreamD m1) (toStreamD m2)
220
227
228+infixr 6 `serial`
229+
230+-- | Appends two streams sequentially, yielding all elements from the first
231+-- stream, and then all elements from the second stream.
232+--
233+-- >>> import Streamly.Prelude (serial)
234+-- >>> stream1 = Stream.fromList [1,2]
235+-- >>> stream2 = Stream.fromList [3,4]
236+-- >>> Stream.toList $ stream1 `serial` stream2
237+-- [1,2,3,4]
238+--
239+-- This operation can be used to fold an infinite lazy container of streams.
240+--
241+-- /Since: 0.2.0 ("Streamly")/
242+--
243+-- @since 0.8.0
244+{-# INLINE serial #-}
245+serial :: IsStream t => t m a -> t m a -> t m a
246+serial m1 m2 = fromStream $ K.serial (toStream m1) (toStream m2)
247+
221-------------------------------------------------------------------------------
248-------------------------------------------------------------------------------
222-- Interleaving
249-- Interleaving
223-------------------------------------------------------------------------------
250-------------------------------------------------------------------------------
224
251
252+infixr 6 `wSerial`
253+
254+-- XXX doc duplicated from Stream.Serial module.
255+--
256+-- | Interleaves two streams, yielding one element from each stream
257+-- alternately. When one stream stops the rest of the other stream is used in
258+-- the output stream.
259+--
260+-- >>> import Streamly.Prelude (wSerial)
261+-- >>> stream1 = Stream.fromList [1,2]
262+-- >>> stream2 = Stream.fromList [3,4]
263+-- >>> Stream.toList $ Stream.fromWSerial $ stream1 `wSerial` stream2
264+-- [1,3,2,4]
265+--
266+-- Note, for singleton streams 'wSerial' and 'serial' are identical.
267+--
268+-- Note that this operation cannot be used to fold a container of infinite
269+-- streams but it can be used for very large streams as the state that it needs
270+-- to maintain is proportional to the logarithm of the number of streams.
271+--
272+-- @since 0.8.0
273+--
274+-- /Since: 0.2.0 ("Streamly")/
275+
276+-- Scheduling Notes:
277+--
278+-- Note that evaluation of @a \`wSerial` b \`wSerial` c@ does not interleave
279+-- @a@, @b@ and @c@ with equal priority. This expression is equivalent to @a
280+-- \`wSerial` (b \`wSerial` c)@, therefore, it fairly interleaves @a@ with the
281+-- result of @b \`wSerial` c@. For example, @Stream.fromList [1,2] \`wSerial`
282+-- Stream.fromList [3,4] \`wSerial` Stream.fromList [5,6]@ would result in
283+-- [1,3,2,5,4,6]. In other words, the leftmost stream gets the same scheduling
284+-- priority as the rest of the streams taken together. The same is true for
285+-- each subexpression on the right.
286+--
287+{-# INLINE wSerial #-}
288+wSerial :: IsStream t => t m a -> t m a -> t m a
289+wSerial m1 m2 = fromStream $ Serial.wSerialK (toStream m1) (toStream m2)
290+
291+infixr 5 <=>
292+
293+-- | Same as 'wSerial'.
294+--
295+-- @since 0.1.0
296+{-# DEPRECATED (<=>) "Please use 'wSerial' instead." #-}
297+{-# INLINE (<=>) #-}
298+(<=>) :: IsStream t => t m a -> t m a -> t m a
299+(<=>) = wSerial
300+
225-- XXX Same as 'wSerial'. We should perhaps rename wSerial to interleave.
301-- XXX Same as 'wSerial'. We should perhaps rename wSerial to interleave.
226-- XXX Document the interleaving behavior of side effects in all the
302-- XXX Document the interleaving behavior of side effects in all the
227-- interleaving combinators.
303-- interleaving combinators.
@@ -341,6 +417,276 @@ interleaveMin m1 m2 = fromStreamD $ D.interleaveMin (toStreamD m1) (toStreamD m2
341roundrobin ::(IsStream t, Monad m) => t m b -> t m b -> t m b
417roundrobin ::(IsStream t, Monad m) => t m b -> t m b -> t m b
342roundrobin m1 m2 = fromStreamD $ D.roundRobin (toStreamD m1) (toStreamD m2)
418roundrobin m1 m2 = fromStreamD $ D.roundRobin (toStreamD m1) (toStreamD m2)
343
419
420+infixr 6 `async`
421+
422+-- | Merges two streams, both the streams may be evaluated concurrently,
423+-- outputs from both are used as they arrive:
424+--
425+-- >>> import Streamly.Prelude (async)
426+-- >>> stream1 = Stream.fromEffect (delay 4)
427+-- >>> stream2 = Stream.fromEffect (delay 2)
428+-- >>> Stream.toList $ stream1 `async` stream2
429+-- 2 sec
430+-- 4 sec
431+-- [2,4]
432+--
433+-- Multiple streams can be combined. With enough threads, all of them can be
434+-- scheduled simultaneously:
435+--
436+-- >>> stream3 = Stream.fromEffect (delay 1)
437+-- >>> Stream.toList $ stream1 `async` stream2 `async` stream3
438+-- ...
439+-- [1,2,4]
440+--
441+-- With 2 threads, only two can be scheduled at a time, when one of those
442+-- finishes, the third one gets scheduled:
443+--
444+-- >>> Stream.toList $ Stream.maxThreads 2 $ stream1 `async` stream2 `async` stream3
445+-- ...
446+-- [2,1,4]
447+--
448+-- With a single thread, it becomes serial:
449+--
450+-- >>> Stream.toList $ Stream.maxThreads 1 $ stream1 `async` stream2 `async` stream3
451+-- ...
452+-- [4,2,1]
453+--
454+-- Only streams are scheduled for async evaluation, how actions within a
455+-- stream are evaluated depends on the stream type. If it is a concurrent
456+-- stream they will be evaluated concurrently.
457+--
458+-- In the following example, both the streams are scheduled for concurrent
459+-- evaluation but each individual stream is evaluated serially:
460+--
461+-- >>> stream1 = Stream.fromListM $ Prelude.map delay [3,3] -- SerialT IO Int
462+-- >>> stream2 = Stream.fromListM $ Prelude.map delay [1,1] -- SerialT IO Int
463+-- >>> Stream.toList $ stream1 `async` stream2 -- IO [Int]
464+-- ...
465+-- [1,1,3,3]
466+--
467+-- If total threads are 2, the third stream is scheduled only after one of the
468+-- first two has finished:
469+--
470+-- > stream3 = Stream.fromListM $ Prelude.map delay [2,2] -- SerialT IO Int
471+-- > Stream.toList $ Stream.maxThreads 2 $ stream1 `async` stream2 `async` stream3 -- IO [Int]
472+-- ...
473+-- [1,1,3,2,3,2]
474+--
475+-- Thus 'async' goes deep in first few streams rather than going wide in all
476+-- streams. It prefers to evaluate the leftmost streams as much as possible.
477+-- Because of this behavior, 'async' can be safely used to fold an infinite
478+-- lazy container of streams.
479+--
480+-- /Since: 0.2.0 ("Streamly")/
481+--
482+-- @since 0.8.0
483+{-# INLINE async #-}
484+async :: (IsStream t, MonadAsync m) => t m a -> t m a -> t m a
485+async m1 m2 = fromStream $ asyncK (toStream m1) (toStream m2)
486+
487+-- | Same as 'async'.
488+--
489+-- @since 0.1.0
490+{-# DEPRECATED (<|) "Please use 'async' instead." #-}
491+{-# INLINE (<|) #-}
492+(<|) :: (IsStream t, MonadAsync m) => t m a -> t m a -> t m a
493+(<|) = async
494+
495+infixr 6 `wAsync`
496+
497+-- | For singleton streams, 'wAsync' is the same as 'async'. See 'async' for
498+-- singleton stream behavior. For multi-element streams, while 'async' is left
499+-- biased i.e. it tries to evaluate the left side stream as much as possible,
500+-- 'wAsync' tries to schedule them both fairly. In other words, 'async' goes
501+-- deep while 'wAsync' goes wide. However, outputs are always used as they
502+-- arrive.
503+--
504+-- With a single thread, 'async' starts behaving like 'serial' while 'wAsync'
505+-- starts behaving like 'wSerial'.
506+--
507+-- >>> import Streamly.Prelude (async, wAsync)
508+-- >>> stream1 = Stream.fromList [1,2,3]
509+-- >>> stream2 = Stream.fromList [4,5,6]
510+-- >>> Stream.toList $ Stream.fromAsync $ Stream.maxThreads 1 $ stream1 `async` stream2
511+-- [1,2,3,4,5,6]
512+--
513+-- >>> Stream.toList $ Stream.fromWAsync $ Stream.maxThreads 1 $ stream1 `wAsync` stream2
514+-- [1,4,2,5,3,6]
515+--
516+-- With two threads available, and combining three streams:
517+--
518+-- >>> stream3 = Stream.fromList [7,8,9]
519+-- >>> Stream.toList $ Stream.fromAsync $ Stream.maxThreads 2 $ stream1 `async` stream2 `async` stream3
520+-- [1,2,3,4,5,6,7,8,9]
521+--
522+-- >>> Stream.toList $ Stream.fromWAsync $ Stream.maxThreads 2 $ stream1 `wAsync` stream2 `wAsync` stream3
523+-- [1,4,2,7,5,3,8,6,9]
524+--
525+-- This operation cannot be used to fold an infinite lazy container of streams,
526+-- because it schedules all the streams in a round robin manner.
527+--
528+-- Note that 'WSerialT' and single threaded 'WAsyncT' both interleave streams
529+-- but the exact scheduling is slightly different in both cases.
530+--
531+-- @since 0.8.0
532+--
533+-- /Since: 0.2.0 ("Streamly")/
534+
535+-- Scheduling details:
536+--
537+-- This is how the execution of the above example proceeds:
538+--
539+-- 1. The scheduler queue is initialized with @[S.fromList [1,2,3],
540+-- (S.fromList [4,5,6]) \<> (S.fromList [7,8,9])]@ assuming the head of the
541+-- queue is represented by the rightmost item.
542+-- 2. @S.fromList [1,2,3]@ is executed, yielding the element @1@ and putting
543+-- @[2,3]@ at the back of the scheduler queue. The scheduler queue now looks
544+-- like @[(S.fromList [4,5,6]) \<> (S.fromList [7,8,9]), S.fromList [2,3]]@.
545+-- 3. Now @(S.fromList [4,5,6]) \<> (S.fromList [7,8,9])@ is picked up for
546+-- execution, @S.fromList [7,8,9]@ is added at the back of the queue and
547+-- @S.fromList [4,5,6]@ is executed, yielding the element @4@ and adding
548+-- @S.fromList [5,6]@ at the back of the queue. The queue now looks like
549+-- @[S.fromList [2,3], S.fromList [7,8,9], S.fromList [5,6]]@.
550+-- 4. Note that the scheduler queue expands by one more stream component in
551+-- every pass because one more @<>@ is broken down into two components. At this
552+-- point there are no more @<>@ operations to be broken down further and the
553+-- queue has reached its maximum size. Now these streams are scheduled in
554+-- round-robin fashion yielding @[2,7,5,3,8,6,9]@.
555+--
556+-- As we see above, in a right associated expression composed with @<>@, only
557+-- one @<>@ operation is broken down into two components in one execution,
558+-- therefore, if we have @n@ streams composed using @<>@ it will take @n@
559+-- scheduler passes to expand the whole expression. By the time @n-th@
560+-- component is added to the scheduler queue, the first component would have
561+-- received @n@ scheduler passes.
562+--
563+{-# INLINE wAsync #-}
564+wAsync :: (IsStream t, MonadAsync m) => t m a -> t m a -> t m a
565+wAsync m1 m2 = fromStream $ wAsyncK (toStream m1) (toStream m2)
566+
567+infixr 6 `ahead`
568+
569+-- | Appends two streams, both the streams may be evaluated concurrently but
570+-- the outputs are used in the same order as the corresponding actions in the
571+-- original streams, side effects will happen in the order in which the streams
572+-- are evaluated:
573+--
574+-- >>> import Streamly.Prelude (ahead, SerialT)
575+-- >>> stream1 = Stream.fromEffect (delay 4) :: SerialT IO Int
576+-- >>> stream2 = Stream.fromEffect (delay 2) :: SerialT IO Int
577+-- >>> Stream.toList $ stream1 `ahead` stream2 :: IO [Int]
578+-- 2 sec
579+-- 4 sec
580+-- [4,2]
581+--
582+-- Multiple streams can be combined. With enough threads, all of them can be
583+-- scheduled simultaneously:
584+--
585+-- >>> stream3 = Stream.fromEffect (delay 1)
586+-- >>> Stream.toList $ stream1 `ahead` stream2 `ahead` stream3
587+-- 1 sec
588+-- 2 sec
589+-- 4 sec
590+-- [4,2,1]
591+--
592+-- With 2 threads, only two can be scheduled at a time, when one of those
593+-- finishes, the third one gets scheduled:
594+--
595+-- >>> Stream.toList $ Stream.maxThreads 2 $ stream1 `ahead` stream2 `ahead` stream3
596+-- 2 sec
597+-- 1 sec
598+-- 4 sec
599+-- [4,2,1]
600+--
601+-- Only streams are scheduled for ahead evaluation, how actions within a stream
602+-- are evaluated depends on the stream type. If it is a concurrent stream they
603+-- will be evaluated concurrently. It may not make much sense combining serial
604+-- streams using 'ahead'.
605+--
606+-- 'ahead' can be safely used to fold an infinite lazy container of streams.
607+--
608+-- /Since: 0.3.0 ("Streamly")/
609+--
610+-- @since 0.8.0
611+{-# INLINE ahead #-}
612+ahead :: (IsStream t, MonadAsync m) => t m a -> t m a -> t m a
613+ahead m1 m2 = fromStream $ aheadK (toStream m1) (toStream m2)
614+
615+infixr 6 `parallel`
616+
617+-- | Like 'Streamly.Prelude.async' except that the execution is much more
618+-- strict. There is no limit on the number of threads. While
619+-- 'Streamly.Prelude.async' may not schedule a stream if there is no demand
620+-- from the consumer, 'parallel' always evaluates both the streams immediately.
621+-- The only limit that applies to 'parallel' is 'Streamly.Prelude.maxBuffer'.
622+-- Evaluation may block if the output buffer becomes full.
623+--
624+-- >>> import Streamly.Prelude (parallel)
625+-- >>> stream = Stream.fromEffect (delay 2) `parallel` Stream.fromEffect (delay 1)
626+-- >>> Stream.toList stream -- IO [Int]
627+-- 1 sec
628+-- 2 sec
629+-- [1,2]
630+--
631+-- 'parallel' guarantees that all the streams are scheduled for execution
632+-- immediately, therefore, we could use things like starting timers inside the
633+-- streams and relying on the fact that all timers were started at the same
634+-- time.
635+--
636+-- Unlike 'async' this operation cannot be used to fold an infinite lazy
637+-- container of streams, because it schedules all the streams strictly
638+-- concurrently.
639+--
640+-- /Since: 0.2.0 ("Streamly")/
641+--
642+-- @since 0.8.0
643+{-# INLINE parallel #-}
644+parallel :: (IsStream t, MonadAsync m) => t m a -> t m a -> t m a
645+parallel m1 m2 = fromStream $ Par.parallelK (toStream m1) (toStream m2)
646+
647+-- This is a race like combinator for streams.
648+--
649+-- | Like `parallel` but stops the output as soon as any of the two streams
650+-- stops.
651+--
652+-- /Pre-release/
653+{-# INLINE parallelMin #-}
654+parallelMin :: (IsStream t, MonadAsync m) => t m a -> t m a -> t m a
655+parallelMin m1 m2 = fromStream $ Par.parallelMinK (toStream m1) (toStream m2)
656+
657+------------------------------------------------------------------------------
658+-- Zipping
659+------------------------------------------------------------------------------
660+
661+-- | Like 'zipAsyncWith' but with a monadic zipping function.
662+--
663+-- @since 0.4.0
664+{-# INLINE zipAsyncWithM #-}
665+zipAsyncWithM :: (IsStream t, MonadAsync m)
666+ => (a -> b -> m c) -> t m a -> t m b -> t m c
667+zipAsyncWithM f m1 m2 =
668+ fromStream $ Zip.zipAsyncWithMK f (toStream m1) (toStream m2)
669+
670+-- XXX Should we rename this to zipParWith or zipParallelWith? This can happen
671+-- along with the change of behvaior to end the stream concurrently.
672+--
673+-- | Like 'zipWith' but zips concurrently i.e. both the streams being zipped
674+-- are evaluated concurrently using the 'ParallelT' concurrent evaluation
675+-- style. The maximum number of elements of each stream evaluated in advance
676+-- can be controlled by 'maxBuffer'.
677+--
678+-- The stream ends if stream @a@ or stream @b@ ends. However, if stream @b@
679+-- ends while we are still evaluating stream @a@ and waiting for a result then
680+-- stream will not end until after the evaluation of stream @a@ finishes. This
681+-- behavior can potentially be changed in future to end the stream immediately
682+-- as soon as any of the stream end is detected.
683+--
684+-- @since 0.1.0
685+{-# INLINE zipAsyncWith #-}
686+zipAsyncWith :: (IsStream t, MonadAsync m)
687+ => (a -> b -> c) -> t m a -> t m b -> t m c
688+zipAsyncWith f = zipAsyncWithM (\a b -> return (f a b))
689+
344------------------------------------------------------------------------------
690------------------------------------------------------------------------------
345-- Merging (sorted streams)
691-- Merging (sorted streams)
346------------------------------------------------------------------------------
692------------------------------------------------------------------------------
@@ -510,7 +856,7 @@ unfoldManyRoundRobin u m =
510interpose :: (IsStream t, Monad m)
856interpose :: (IsStream t, Monad m)
511 => c -> Unfold m b c -> t m b -> t m c
857 => c -> Unfold m b c -> t m b -> t m c
512interpose x unf str =
858interpose x unf str =
513− D.fromStreamD $ D.interpose (return x) unf (D.toStreamD str)
859+ fromStreamD $ D.interpose (return x) unf (toStreamD str)
514
860
515-- interposeSuffix x unf str = gintercalateSuffix unf str UF.identity (repeat x)
861-- interposeSuffix x unf str = gintercalateSuffix unf str UF.identity (repeat x)
516--
862--
@@ -524,7 +870,7 @@ interpose x unf str =
524interposeSuffix :: (IsStream t, Monad m)
870interposeSuffix :: (IsStream t, Monad m)
525 => c -> Unfold m b c -> t m b -> t m c
871 => c -> Unfold m b c -> t m b -> t m c
526interposeSuffix x unf str =
872interposeSuffix x unf str =
527− D.fromStreamD $ D.interposeSuffix (return x) unf (D.toStreamD str)
873+ fromStreamD $ D.interposeSuffix (return x) unf (toStreamD str)
528
874
529------------------------------------------------------------------------------
875------------------------------------------------------------------------------
530-- Combine N Streams - intercalate
876-- Combine N Streams - intercalate
@@ -546,9 +892,9 @@ gintercalate
546 :: (IsStream t, Monad m)
892 :: (IsStream t, Monad m)
547 => Unfold m a c -> t m a -> Unfold m b c -> t m b -> t m c
893 => Unfold m a c -> t m a -> Unfold m b c -> t m b -> t m c
548gintercalate unf1 str1 unf2 str2 =
894gintercalate unf1 str1 unf2 str2 =
549− D.fromStreamD $ D.gintercalate
895+ fromStreamD $ D.gintercalate
550− unf1 (D.toStreamD str1)
896+ unf1 (toStreamD str1)
551− unf2 (D.toStreamD str2)
897+ unf2 (toStreamD str2)
552
898
553-- > intercalate unf seed str = gintercalate unf str unf (repeatM seed)
899-- > intercalate unf seed str = gintercalate unf str unf (repeatM seed)
554--
900--
@@ -565,7 +911,7 @@ gintercalate unf1 str1 unf2 str2 =
565{-# INLINE intercalate #-}
911{-# INLINE intercalate #-}
566intercalate :: (IsStream t, Monad m)
912intercalate :: (IsStream t, Monad m)
567 => Unfold m b c -> b -> t m b -> t m c
913 => Unfold m b c -> b -> t m b -> t m c
568−intercalate unf seed str = D.fromStreamD $
914+intercalate unf seed str = fromStreamD $
569 D.unfoldMany unf $ D.intersperse seed (toStreamD str)
915 D.unfoldMany unf $ D.intersperse seed (toStreamD str)
570
916
571-- | 'interleaveSuffix' followed by unfold and concat.
917-- | 'interleaveSuffix' followed by unfold and concat.
@@ -576,9 +922,9 @@ gintercalateSuffix
576 :: (IsStream t, Monad m)
922 :: (IsStream t, Monad m)
577 => Unfold m a c -> t m a -> Unfold m b c -> t m b -> t m c
923 => Unfold m a c -> t m a -> Unfold m b c -> t m b -> t m c
578gintercalateSuffix unf1 str1 unf2 str2 =
924gintercalateSuffix unf1 str1 unf2 str2 =
579− D.fromStreamD $ D.gintercalateSuffix
925+ fromStreamD $ D.gintercalateSuffix
580− unf1 (D.toStreamD str1)
926+ unf1 (toStreamD str1)
581− unf2 (D.toStreamD str2)
927+ unf2 (toStreamD str2)
582
928
583-- > intercalateSuffix unf seed str = gintercalateSuffix unf str unf (repeatM seed)
929-- > intercalateSuffix unf seed str = gintercalateSuffix unf str unf (repeatM seed)
584--
930--
@@ -596,7 +942,7 @@ gintercalateSuffix unf1 str1 unf2 str2 =
596intercalateSuffix :: (IsStream t, Monad m)
942intercalateSuffix :: (IsStream t, Monad m)
597 => Unfold m b c -> b -> t m b -> t m c
943 => Unfold m b c -> b -> t m b -> t m c
598intercalateSuffix unf seed str = fromStreamD $ D.unfoldMany unf
944intercalateSuffix unf seed str = fromStreamD $ D.unfoldMany unf
599− $ D.intersperseSuffix (return seed) (D.toStreamD str)
945+ $ D.intersperseSuffix (return seed) (toStreamD str)
600
946
601{-
947{-
602{-# INLINE iterateUnfold #-}
948{-# INLINE iterateUnfold #-}
@@ -624,25 +970,6 @@ concat = concatMap id
624-- Combine N Streams - concatMap
970-- Combine N Streams - concatMap
625------------------------------------------------------------------------------
971------------------------------------------------------------------------------
626
972
627−-- | @concatMapWith mixer generator stream@ is a two dimensional looping
628−-- combinator. The @generator@ function is used to generate streams from the
629−-- elements in the input @stream@ and the @mixer@ function is used to merge
630−-- those streams.
631−--
632−-- Note we can merge streams concurrently by using a concurrent merge function.
633−--
634−-- /Since: 0.7.0/
635−--
636−-- /Since: 0.8.0 (signature change)/
637−{-# INLINE concatMapWith #-}
638−concatMapWith
639− :: IsStream t
640− => (t m b -> t m b -> t m b)
641− -> (a -> t m b)
642− -> t m a
643− -> t m b
644−concatMapWith = K.concatMapBy
645−
646-- | Like 'concatMapWith' but carries a state which can be used to share
973-- | Like 'concatMapWith' but carries a state which can be used to share
647-- information across multiple steps of concat.
974-- information across multiple steps of concat.
648--
975--
@@ -660,7 +987,8 @@ concatSmapMWith
660 -> m s
987 -> m s
661 -> t m a
988 -> t m a
662 -> t m b
989 -> t m b
990+concatSmapMWith combine f initial =
663−concatSmapMWith combine f initial = concatMapWith combine id . smapM f initial
991+ IsStream.concatMapWith combine id . smapM f initial
664
992
665-- Keep concating either streams as long as rights are generated, stop as soon
993-- Keep concating either streams as long as rights are generated, stop as soon
666-- as a left is generated and concat the left stream.
994-- as a left is generated and concat the left stream.
@@ -700,7 +1028,12 @@ concatPairsWith :: IsStream t =>
700 -> (a -> t m b)
1028 -> (a -> t m b)
701 -> t m a
1029 -> t m a
702 -> t m b
1030 -> t m b
1031+concatPairsWith par f m =
1032+ fromStream
703−concatPairsWith = K.concatPairsWith
1033+ $ K.concatPairsWith
1034+ (\s1 s2 -> toStream $ fromStream s1 `par` fromStream s2)
1035+ (toStream . f)
1036+ (toStream m)
704
1037
705------------------------------------------------------------------------------
1038------------------------------------------------------------------------------
706-- IterateMap - Map and flatten Trees of Streams
1039-- IterateMap - Map and flatten Trees of Streams
@@ -737,9 +1070,9 @@ iterateMapWith
737 -> (a -> t m a)
1070 -> (a -> t m a)
738 -> t m a
1071 -> t m a
739 -> t m a
1072 -> t m a
740−iterateMapWith combine f = concatMapWith combine go
1073+iterateMapWith combine f = IsStream.concatMapWith combine go
741 where
1074 where
742− go x = fromPure x `combine` concatMapWith combine go (f x)
1075+ go x = fromPure x `combine` IsStream.concatMapWith combine go (f x)
743
1076
744{-
1077{-
745{-# INLINE iterateUnfold #-}
1078{-# INLINE iterateUnfold #-}
@@ -776,7 +1109,9 @@ iterateSmapMWith
776 -> t m a
1109 -> t m a
777 -> t m a
1110 -> t m a
778iterateSmapMWith combine f initial stream =
1111iterateSmapMWith combine f initial stream =
1112+ concatMap
779− concatMap (\b -> concatMapWith combine (go b) stream) (fromEffect initial)
1113+ (\b -> IsStream.concatMapWith combine (go b) stream)
1114+ (fromEffect initial)
780
1115
781 where
1116 where
782
1117
@@ -784,7 +1119,7 @@ iterateSmapMWith combine f initial stream =
784
1119
785 feedback b a =
1120 feedback b a =
786 concatMap
1121 concatMap
787− (\(b1, s) -> concatMapWith combine (go b1) s)
1122+ (\(b1, s) -> IsStream.concatMapWith combine (go b1) s)
788 (fromEffect $ f b a)
1123 (fromEffect $ f b a)
789
1124
790------------------------------------------------------------------------------
1125------------------------------------------------------------------------------
@@ -813,4 +1148,5 @@ iterateMapLeftsWith
813 -> (a -> t m (Either a b))
1148 -> (a -> t m (Either a b))
814 -> t m (Either a b)
1149 -> t m (Either a b)
815 -> t m (Either a b)
1150 -> t m (Either a b)
1151+iterateMapLeftsWith combine f =
816−iterateMapLeftsWith combine f = iterateMapWith combine (either f (const K.nil))
1152+ iterateMapWith combine (either f (const IsStream.nil))
src/Streamly/Internal/Data/Stream/IsStream/Generate.hs+125−30
@@ -18,10 +18,10 @@
18module Streamly.Internal.Data.Stream.IsStream.Generate
18module Streamly.Internal.Data.Stream.IsStream.Generate
19 (
19 (
20 -- * Primitives
20 -- * Primitives
21− K.nil
21+ IsStream.nil
22− , K.nilM
22+ , IsStream.nilM
23− , K.cons
23+ , IsStream.cons
24− , (K..:)
24+ , (IsStream..:)
25
25
26 , consM
26 , consM
27 , (|:)
27 , (|:)
@@ -68,17 +68,18 @@ module Streamly.Internal.Data.Stream.IsStream.Generate
68 , iterateM
68 , iterateM
69
69
70 -- * Cyclic Elements
70 -- * Cyclic Elements
71− , K.mfix
71+ , mfix
72
72
73 -- * From Containers
73 -- * From Containers
74− , P.fromList
74+ , IsStream.fromList
75 , fromListM
75 , fromListM
76− , K.fromFoldable
76+ , fromFoldable
77 , fromFoldableM
77 , fromFoldableM
78 , fromCallback
78 , fromCallback
79+ , fromPrimIORef
79
80
80 -- * Deprecated
81 -- * Deprecated
81− , K.once
82+ , once
82 , yield
83 , yield
83 , yieldM
84 , yieldM
84 , each
85 , each
@@ -90,6 +91,7 @@ where
90#include "inline.hs"
91#include "inline.hs"
91
92
92import Control.Monad.IO.Class (MonadIO(..))
93import Control.Monad.IO.Class (MonadIO(..))
94+import Data.Primitive.Types (Prim)
93import Data.Void (Void)
95import Data.Void (Void)
94import Streamly.Internal.Control.Concurrent (MonadAsync)
96import Streamly.Internal.Control.Concurrent (MonadAsync)
95import Streamly.Internal.Data.Unfold.Type (Unfold)
97import Streamly.Internal.Data.Unfold.Type (Unfold)
@@ -99,20 +101,21 @@ import Streamly.Internal.Data.Stream.IsStream.Enumeration
99import Streamly.Internal.Data.Stream.IsStream.Common
101import Streamly.Internal.Data.Stream.IsStream.Common
100 ( absTimesWith, concatM, relTimesWith, timesWith, fromPure, fromEffect
102 ( absTimesWith, concatM, relTimesWith, timesWith, fromPure, fromEffect
101 , yield, yieldM, repeatM)
103 , yield, yieldM, repeatM)
102−import Streamly.Internal.Data.Stream.Prelude (fromStreamS)
104+import Streamly.Internal.Data.Stream.IsStream.Type
105+ (IsStream (..), fromSerial, consM, fromStreamD, fromStreamS)
103−import Streamly.Internal.Data.Stream.StreamD (fromStreamD)
106+import Streamly.Internal.Data.Stream.Serial (SerialT(..), WSerialT)
104−import Streamly.Internal.Data.Stream.StreamK (IsStream((|:), consM))
105−import Streamly.Internal.Data.Stream.Serial (SerialT, WSerialT)
106import Streamly.Internal.Data.Stream.Zip (ZipSerialM)
107import Streamly.Internal.Data.Stream.Zip (ZipSerialM)
107import Streamly.Internal.Data.Time.Units (AbsTime , RelTime64, addToAbsTime64)
108import Streamly.Internal.Data.Time.Units (AbsTime , RelTime64, addToAbsTime64)
108
109
110+import qualified Streamly.Internal.Data.IORef.Prim as Prim
111+import qualified Streamly.Internal.Data.Stream.IsStream.Type as IsStream
109import qualified Streamly.Internal.Data.Stream.Parallel as Par
112import qualified Streamly.Internal.Data.Stream.Parallel as Par
110−import qualified Streamly.Internal.Data.Stream.Prelude as P
111import qualified Streamly.Internal.Data.Stream.Serial as Serial
113import qualified Streamly.Internal.Data.Stream.Serial as Serial
112import qualified Streamly.Internal.Data.Stream.StreamD.Generate as D
114import qualified Streamly.Internal.Data.Stream.StreamD.Generate as D
113−import qualified Streamly.Internal.Data.Stream.StreamK as K
115+import qualified Streamly.Internal.Data.Stream.StreamK.Type as K
114#ifdef USE_STREAMK_ONLY
116#ifdef USE_STREAMK_ONLY
115import qualified Streamly.Internal.Data.Stream.StreamK as S
117import qualified Streamly.Internal.Data.Stream.StreamK as S
118+import qualified Streamly.Internal.Data.Stream.StreamK.Type as S
116#else
119#else
117import qualified Streamly.Internal.Data.Stream.StreamD.Generate as S
120import qualified Streamly.Internal.Data.Stream.StreamD.Generate as S
118#endif
121#endif
@@ -217,8 +220,9 @@ unfoldr step seed = fromStreamS (S.unfoldr step seed)
217--
220--
218-- /Since: 0.1.0/
221-- /Since: 0.1.0/
219{-# INLINE_EARLY unfoldrM #-}
222{-# INLINE_EARLY unfoldrM #-}
220−unfoldrM :: (IsStream t, MonadAsync m) => (b -> m (Maybe (a, b))) -> b -> t m a
223+unfoldrM :: forall t m a b. (IsStream t, MonadAsync m) =>
221−unfoldrM = K.unfoldrM
224+ (b -> m (Maybe (a, b))) -> b -> t m a
225+unfoldrM step = fromStream . K.unfoldrMWith (IsStream.toConsK (consM @t)) step
222
226
223{-# RULES "unfoldrM serial" unfoldrM = unfoldrMSerial #-}
227{-# RULES "unfoldrM serial" unfoldrM = unfoldrMSerial #-}
224{-# INLINE_EARLY unfoldrMSerial #-}
228{-# INLINE_EARLY unfoldrMSerial #-}
@@ -228,12 +232,13 @@ unfoldrMSerial = Serial.unfoldrM
228{-# RULES "unfoldrM wSerial" unfoldrM = unfoldrMWSerial #-}
232{-# RULES "unfoldrM wSerial" unfoldrM = unfoldrMWSerial #-}
229{-# INLINE_EARLY unfoldrMWSerial #-}
233{-# INLINE_EARLY unfoldrMWSerial #-}
230unfoldrMWSerial :: MonadAsync m => (b -> m (Maybe (a, b))) -> b -> WSerialT m a
234unfoldrMWSerial :: MonadAsync m => (b -> m (Maybe (a, b))) -> b -> WSerialT m a
231−unfoldrMWSerial = Serial.unfoldrM
235+unfoldrMWSerial f = fromSerial . Serial.unfoldrM f
232
236
233{-# RULES "unfoldrM zipSerial" unfoldrM = unfoldrMZipSerial #-}
237{-# RULES "unfoldrM zipSerial" unfoldrM = unfoldrMZipSerial #-}
234{-# INLINE_EARLY unfoldrMZipSerial #-}
238{-# INLINE_EARLY unfoldrMZipSerial #-}
235−unfoldrMZipSerial :: MonadAsync m => (b -> m (Maybe (a, b))) -> b -> ZipSerialM m a
239+unfoldrMZipSerial :: MonadAsync m =>
240+ (b -> m (Maybe (a, b))) -> b -> ZipSerialM m a
236−unfoldrMZipSerial = Serial.unfoldrM
241+unfoldrMZipSerial f = fromSerial . Serial.unfoldrM f
237
242
238------------------------------------------------------------------------------
243------------------------------------------------------------------------------
239-- From Values
244-- From Values
@@ -275,8 +280,9 @@ replicate n = fromStreamS . S.replicate n
275--
280--
276-- @since 0.1.1
281-- @since 0.1.1
277{-# INLINE_EARLY replicateM #-}
282{-# INLINE_EARLY replicateM #-}
278−replicateM :: (IsStream t, MonadAsync m) => Int -> m a -> t m a
283+replicateM :: forall t m a. (IsStream t, MonadAsync m) => Int -> m a -> t m a
279−replicateM = K.replicateM
284+replicateM count =
285+ fromStream . K.replicateMWith (IsStream.toConsK (consM @t)) count
280
286
281{-# RULES "replicateM serial" replicateM = replicateMSerial #-}
287{-# RULES "replicateM serial" replicateM = replicateMSerial #-}
282{-# INLINE replicateMSerial #-}
288{-# INLINE replicateMSerial #-}
@@ -422,8 +428,9 @@ fromIndices = fromStreamS . S.fromIndices
422--
428--
423-- @since 0.6.0
429-- @since 0.6.0
424{-# INLINE_EARLY fromIndicesM #-}
430{-# INLINE_EARLY fromIndicesM #-}
425−fromIndicesM :: (IsStream t, MonadAsync m) => (Int -> m a) -> t m a
431+fromIndicesM :: forall t m a. (IsStream t, MonadAsync m) =>
426−fromIndicesM = K.fromIndicesM
432+ (Int -> m a) -> t m a
433+fromIndicesM = fromStream . K.fromIndicesMWith (IsStream.toConsK (consM @t))
427
434
428{-# RULES "fromIndicesM serial" fromIndicesM = fromIndicesMSerial #-}
435{-# RULES "fromIndicesM serial" fromIndicesM = fromIndicesMSerial #-}
429{-# INLINE fromIndicesMSerial #-}
436{-# INLINE fromIndicesMSerial #-}
@@ -482,18 +489,90 @@ iterate step = fromStreamS . S.iterate step
482--
489--
483-- /Since: 0.7.0 (signature change)/
490-- /Since: 0.7.0 (signature change)/
484{-# INLINE_EARLY iterateM #-}
491{-# INLINE_EARLY iterateM #-}
485−iterateM :: (IsStream t, MonadAsync m) => (a -> m a) -> m a -> t m a
492+iterateM :: forall t m a. (IsStream t, MonadAsync m) =>
486−iterateM = K.iterateM
493+ (a -> m a) -> m a -> t m a
494+iterateM f = fromStream . K.iterateMWith (IsStream.toConsK (consM @t)) f
487
495
488{-# RULES "iterateM serial" iterateM = iterateMSerial #-}
496{-# RULES "iterateM serial" iterateM = iterateMSerial #-}
489{-# INLINE iterateMSerial #-}
497{-# INLINE iterateMSerial #-}
490iterateMSerial :: MonadAsync m => (a -> m a) -> m a -> SerialT m a
498iterateMSerial :: MonadAsync m => (a -> m a) -> m a -> SerialT m a
491iterateMSerial step = fromStreamS . S.iterateM step
499iterateMSerial step = fromStreamS . S.iterateM step
492
500
501+-- | We can define cyclic structures using @let@:
502+--
503+-- >>> let (a, b) = ([1, b], head a) in (a, b)
504+-- ([1,1],1)
505+--
506+-- The function @fix@ defined as:
507+--
508+-- > fix f = let x = f x in x
509+--
510+-- ensures that the argument of a function and its output refer to the same
511+-- lazy value @x@ i.e. the same location in memory. Thus @x@ can be defined
512+-- in terms of itself, creating structures with cyclic references.
513+--
514+-- >>> import Data.Function (fix)
515+-- >>> f ~(a, b) = ([1, b], head a)
516+-- >>> fix f
517+-- ([1,1],1)
518+--
519+-- 'Control.Monad.mfix' is essentially the same as @fix@ but for monadic
520+-- values.
521+--
522+-- Using 'mfix' for streams we can construct a stream in which each element of
523+-- the stream is defined in a cyclic fashion. The argument of the function
524+-- being fixed represents the current element of the stream which is being
525+-- returned by the stream monad. Thus, we can use the argument to construct
526+-- itself.
527+--
528+-- In the following example, the argument @action@ of the function @f@
529+-- represents the tuple @(x,y)@ returned by it in a given iteration. We define
530+-- the first element of the tuple in terms of the second.
531+--
532+-- @
533+-- import Streamly.Internal.Data.Stream.IsStream as Stream
534+-- import System.IO.Unsafe (unsafeInterleaveIO)
535+--
536+-- main = do
537+-- Stream.mapM_ print $ Stream.mfix f
538+--
539+-- where
540+--
541+-- f action = do
542+-- let incr n act = fmap ((+n) . snd) $ unsafeInterleaveIO act
543+-- x <- Stream.fromListM [incr 1 action, incr 2 action]
544+-- y <- Stream.fromList [4,5]
545+-- return (x, y)
546+-- @
547+--
548+-- Note: you cannot achieve this by just changing the order of the monad
549+-- statements because that would change the order in which the stream elements
550+-- are generated.
551+--
552+-- Note that the function @f@ must be lazy in its argument, that's why we use
553+-- 'unsafeInterleaveIO' on @action@ because IO monad is strict.
554+--
555+-- /Pre-release/
556+{-# INLINE mfix #-}
557+mfix :: (IsStream t, Monad m) => (m a -> t m a) -> t m a
558+mfix f = fromStream $ K.mfix (toStream . f)
559+
493------------------------------------------------------------------------------
560------------------------------------------------------------------------------
494-- Conversions
561-- Conversions
495------------------------------------------------------------------------------
562------------------------------------------------------------------------------
496
563
564+-- |
565+-- @
566+-- fromFoldable = 'Prelude.foldr' 'cons' 'nil'
567+-- @
568+--
569+-- Construct a stream from a 'Foldable' containing pure values:
570+--
571+-- @since 0.2.0
572+{-# INLINE fromFoldable #-}
573+fromFoldable :: (IsStream t, Foldable f) => f a -> t m a
574+fromFoldable = fromStream . K.fromFoldable
575+
497-- |
576-- |
498-- @
577-- @
499-- fromFoldableM = 'Prelude.foldr' 'consM' 'K.nil'
578-- fromFoldableM = 'Prelude.foldr' 'consM' 'K.nil'
@@ -511,7 +590,7 @@ iterateMSerial step = fromStreamS . S.iterateM step
511-- @since 0.3.0
590-- @since 0.3.0
512{-# INLINE fromFoldableM #-}
591{-# INLINE fromFoldableM #-}
513fromFoldableM :: (IsStream t, MonadAsync m, Foldable f) => f (m a) -> t m a
592fromFoldableM :: (IsStream t, MonadAsync m, Foldable f) => f (m a) -> t m a
514−fromFoldableM = Prelude.foldr consM K.nil
593+fromFoldableM = Prelude.foldr consM IsStream.nil
515
594
516-- |
595-- |
517-- @
596-- @
@@ -526,7 +605,7 @@ fromFoldableM = Prelude.foldr consM K.nil
526fromListM :: (MonadAsync m, IsStream t) => [m a] -> t m a
605fromListM :: (MonadAsync m, IsStream t) => [m a] -> t m a
527fromListM = fromFoldableM
606fromListM = fromFoldableM
528{-# RULES "fromListM fallback to StreamK" [1]
607{-# RULES "fromListM fallback to StreamK" [1]
529− forall a. D.toStreamK (D.fromListM a) = fromFoldableM a #-}
608+ forall a. D.toStreamK (D.fromListM a) = K.fromFoldableM a #-}
530
609
531{-# RULES "fromListM serial" fromListM = fromListMSerial #-}
610{-# RULES "fromListM serial" fromListM = fromListMSerial #-}
532{-# INLINE_EARLY fromListMSerial #-}
611{-# INLINE_EARLY fromListMSerial #-}
@@ -539,7 +618,7 @@ fromListMSerial = fromStreamD . D.fromListM
539{-# DEPRECATED each "Please use fromFoldable instead." #-}
618{-# DEPRECATED each "Please use fromFoldable instead." #-}
540{-# INLINE each #-}
619{-# INLINE each #-}
541each :: (IsStream t, Foldable f) => f a -> t m a
620each :: (IsStream t, Foldable f) => f a -> t m a
542−each = K.fromFoldable
621+each = fromFoldable
543
622
544-- | Read lines from an IO Handle into a stream of Strings.
623-- | Read lines from an IO Handle into a stream of Strings.
545--
624--
@@ -549,7 +628,7 @@ each = K.fromFoldable
549fromHandle :: (IsStream t, MonadIO m) => IO.Handle -> t m String
628fromHandle :: (IsStream t, MonadIO m) => IO.Handle -> t m String
550fromHandle h = go
629fromHandle h = go
551 where
630 where
552− go = K.mkStream $ \_ yld _ stp -> do
631+ go = IsStream.mkStream $ \_ yld _ stp -> do
553 eof <- liftIO $ IO.hIsEOF h
632 eof <- liftIO $ IO.hIsEOF h
554 if eof
633 if eof
555 then stp
634 then stp
@@ -570,4 +649,20 @@ fromCallback :: MonadAsync m => ((a -> m ()) -> m ()) -> SerialT m a
570fromCallback setCallback = concatM $ do
649fromCallback setCallback = concatM $ do
571 (callback, stream) <- Par.newCallbackStream
650 (callback, stream) <- Par.newCallbackStream
572 setCallback callback
651 setCallback callback
573− return stream
652+ return $ SerialT stream
653+
654+-- | Construct a stream by reading a 'Prim' 'IORef' repeatedly.
655+--
656+-- /Pre-release/
657+--
658+{-# INLINE fromPrimIORef #-}
659+fromPrimIORef :: (IsStream t, MonadIO m, Prim a) => Prim.IORef a -> t m a
660+fromPrimIORef = fromStreamD . Prim.toStreamD
661+
662+-- | Same as fromEffect
663+--
664+-- @since 0.2.0
665+{-# DEPRECATED once "Please use fromEffect instead." #-}
666+{-# INLINE once #-}
667+once :: (Monad m, IsStream t) => m a -> t m a
668+once = IsStream.fromEffect
src/Streamly/Internal/Data/Stream/IsStream/Lift.hs+2−3
@@ -28,10 +28,9 @@ import Control.Monad.Trans.Reader (ReaderT)
28import Control.Monad.Trans.State.Strict (StateT)
28import Control.Monad.Trans.State.Strict (StateT)
29import Control.Monad.Trans.Class (MonadTrans(..))
29import Control.Monad.Trans.Class (MonadTrans(..))
30import Data.Functor.Identity (Identity (..))
30import Data.Functor.Identity (Identity (..))
31−import Streamly.Internal.Data.Stream.Prelude (fromStreamS, toStreamS)
31+import Streamly.Internal.Data.Stream.IsStream.Type
32+ (IsStream(..), fromStreamS, toStreamS, fromStreamD, toStreamD)
32import Streamly.Internal.Data.Stream.Serial (SerialT)
33import Streamly.Internal.Data.Stream.Serial (SerialT)
33−import Streamly.Internal.Data.Stream.StreamD (fromStreamD, toStreamD)
34−import Streamly.Internal.Data.Stream.StreamK (IsStream)
35
34
36import qualified Streamly.Internal.Data.Stream.StreamD as D
35import qualified Streamly.Internal.Data.Stream.StreamD as D
37#ifdef USE_STREAMK_ONLY
36#ifdef USE_STREAMK_ONLY
src/Streamly/Internal/Data/Stream/IsStream/Reduce.hs+36−32
@@ -163,11 +163,14 @@ import Streamly.Internal.Data.Stream.IsStream.Common
163 , fold
163 , fold
164 , interjectSuffix
164 , interjectSuffix
165 , intersperseM
165 , intersperseM
166+ , map
167+ , parallelFst
166 , repeatM
168 , repeatM
167 , scanlMAfter'
169 , scanlMAfter'
168 , splitOnSeq
170 , splitOnSeq
169 , fromPure)
171 , fromPure)
170−import Streamly.Internal.Data.Stream.StreamK (IsStream)
172+import Streamly.Internal.Data.Stream.IsStream.Type
173+ (IsStream(..), fromStreamD, toStreamD, cons)
171import Streamly.Internal.Data.Time.Units
174import Streamly.Internal.Data.Time.Units
172 ( AbsTime, MilliSecond64(..), addToAbsTime, toRelTime
175 ( AbsTime, MilliSecond64(..), addToAbsTime, toRelTime
173 , toAbsTime)
176 , toAbsTime)
@@ -179,12 +182,10 @@ import qualified Streamly.Internal.Data.Array.Foreign.Type as A
179import qualified Streamly.Internal.Data.Fold as FL
182import qualified Streamly.Internal.Data.Fold as FL
180import qualified Streamly.Internal.Data.Parser.ParserK.Type as PRK
183import qualified Streamly.Internal.Data.Parser.ParserK.Type as PRK
181import qualified Streamly.Internal.Data.Parser.ParserD as PRD
184import qualified Streamly.Internal.Data.Parser.ParserD as PRD
182−import qualified Streamly.Internal.Data.Stream.Parallel as Par
185+import qualified Streamly.Internal.Data.Stream.IsStream.Type as IsStream
183−import qualified Streamly.Internal.Data.Stream.Serial as Serial
184import qualified Streamly.Internal.Data.Stream.StreamD as D
186import qualified Streamly.Internal.Data.Stream.StreamD as D
185−import qualified Streamly.Internal.Data.Stream.StreamK as K
186
187
187−import Prelude hiding (concatMap)
188+import Prelude hiding (concatMap, map)
188
189
189-- $setup
190-- $setup
190-- >>> :m
191-- >>> :m
@@ -265,7 +266,7 @@ foldManyPost
265 => Fold m a b
266 => Fold m a b
266 -> t m a
267 -> t m a
267 -> t m b
268 -> t m b
268−foldManyPost f m = D.fromStreamD $ D.foldManyPost f (D.toStreamD m)
269+foldManyPost f m = fromStreamD $ D.foldManyPost f (toStreamD m)
269
270
270-- | Apply a 'Fold' repeatedly on a stream and emit the fold outputs in the
271-- | Apply a 'Fold' repeatedly on a stream and emit the fold outputs in the
271-- output stream.
272-- output stream.
@@ -292,7 +293,7 @@ foldMany
292 => Fold m a b
293 => Fold m a b
293 -> t m a
294 -> t m a
294 -> t m b
295 -> t m b
295−foldMany f m = D.fromStreamD $ D.foldMany f (D.toStreamD m)
296+foldMany f m = fromStreamD $ D.foldMany f (toStreamD m)
296
297
297-- | Apply a stream of folds to an input stream and emit the results in the
298-- | Apply a stream of folds to an input stream and emit the results in the
298-- output stream.
299-- output stream.
@@ -328,7 +329,7 @@ foldSequence _f _m = undefined
328{-# INLINE foldIterateM #-}
329{-# INLINE foldIterateM #-}
329foldIterateM ::
330foldIterateM ::
330 (IsStream t, Monad m) => (b -> m (Fold m a b)) -> b -> t m a -> t m b
331 (IsStream t, Monad m) => (b -> m (Fold m a b)) -> b -> t m a -> t m b
331−foldIterateM f i m = D.fromStreamD $ D.foldIterateM f i (D.toStreamD m)
332+foldIterateM f i m = fromStreamD $ D.foldIterateM f i (toStreamD m)
332
333
333------------------------------------------------------------------------------
334------------------------------------------------------------------------------
334-- Parsing
335-- Parsing
@@ -365,7 +366,7 @@ parseMany
365 -> t m a
366 -> t m a
366 -> t m b
367 -> t m b
367parseMany p m =
368parseMany p m =
368− D.fromStreamD $ D.parseMany (PRK.fromParserK p) (D.toStreamD m)
369+ fromStreamD $ D.parseMany (PRK.fromParserK p) (toStreamD m)
369
370
370{-# INLINE parseManyD #-}
371{-# INLINE parseManyD #-}
371parseManyD
372parseManyD
@@ -374,7 +375,7 @@ parseManyD
374 -> t m a
375 -> t m a
375 -> t m b
376 -> t m b
376parseManyD p m =
377parseManyD p m =
377− D.fromStreamD $ D.parseMany p (D.toStreamD m)
378+ fromStreamD $ D.parseMany p (toStreamD m)
378
379
379-- | Apply a stream of parsers to an input stream and emit the results in the
380-- | Apply a stream of parsers to an input stream and emit the results in the
380-- output stream.
381-- output stream.
@@ -428,8 +429,8 @@ parseIterate
428 -> b
429 -> b
429 -> t m a
430 -> t m a
430 -> t m b
431 -> t m b
431−parseIterate f i m = D.fromStreamD $
432+parseIterate f i m = fromStreamD $
432− D.parseIterate (PRK.fromParserK . f) i (D.toStreamD m)
433+ D.parseIterate (PRK.fromParserK . f) i (toStreamD m)
433
434
434------------------------------------------------------------------------------
435------------------------------------------------------------------------------
435-- Generalized grouping
436-- Generalized grouping
@@ -492,7 +493,7 @@ groupsBy
492 -> Fold m a b
493 -> Fold m a b
493 -> t m a
494 -> t m a
494 -> t m b
495 -> t m b
495−groupsBy cmp f m = D.fromStreamD $ D.groupsBy cmp f (D.toStreamD m)
496+groupsBy cmp f m = fromStreamD $ D.groupsBy cmp f (toStreamD m)
496
497
497-- | Unlike @groupsBy@ this function performs a rolling comparison of two
498-- | Unlike @groupsBy@ this function performs a rolling comparison of two
498-- successive elements in the input stream. @groupsByRolling cmp f $ S.fromList
499-- successive elements in the input stream. @groupsByRolling cmp f $ S.fromList
@@ -513,7 +514,7 @@ groupsByRolling
513 -> Fold m a b
514 -> Fold m a b
514 -> t m a
515 -> t m a
515 -> t m b
516 -> t m b
516−groupsByRolling cmp f m = D.fromStreamD $ D.groupsRollingBy cmp f (D.toStreamD m)
517+groupsByRolling cmp f m = fromStreamD $ D.groupsRollingBy cmp f (toStreamD m)
517
518
518-- |
519-- |
519-- > groups = groupsBy (==)
520-- > groups = groupsBy (==)
@@ -736,7 +737,7 @@ wordsBy
736 :: (IsStream t, Monad m)
737 :: (IsStream t, Monad m)
737 => (a -> Bool) -> Fold m a b -> t m a -> t m b
738 => (a -> Bool) -> Fold m a b -> t m a -> t m b
738wordsBy predicate f m =
739wordsBy predicate f m =
739− D.fromStreamD $ D.wordsBy predicate f (D.toStreamD m)
740+ fromStreamD $ D.wordsBy predicate f (toStreamD m)
740
741
741-- | Like 'splitOnSuffix' but keeps the suffix attached to the resulting
742-- | Like 'splitOnSuffix' but keeps the suffix attached to the resulting
742-- splits.
743-- splits.
@@ -812,7 +813,8 @@ splitWithSuffix predicate f = foldMany (FL.takeEndBy predicate f)
812splitOnAny
813splitOnAny
813 :: (IsStream t, Monad m, Storable a, Integral a)
814 :: (IsStream t, Monad m, Storable a, Integral a)
814 => [Array a] -> Fold m a b -> t m a -> t m b
815 => [Array a] -> Fold m a b -> t m a -> t m b
816+splitOnAny subseq f m = undefined
815−splitOnAny subseq f m = undefined -- D.fromStreamD $ D.splitOnAny f subseq (D.toStreamD m)
817+ -- fromStreamD $ D.splitOnAny f subseq (toStreamD m)
816-}
818-}
817
819
818-- XXX use a non-monadic intersperse to remove the MonadAsync constraint.
820-- XXX use a non-monadic intersperse to remove the MonadAsync constraint.
@@ -907,7 +909,7 @@ splitOnSuffixSeq
907 :: (IsStream t, MonadIO m, Storable a, Enum a, Eq a)
909 :: (IsStream t, MonadIO m, Storable a, Enum a, Eq a)
908 => Array a -> Fold m a b -> t m a -> t m b
910 => Array a -> Fold m a b -> t m a -> t m b
909splitOnSuffixSeq patt f m =
911splitOnSuffixSeq patt f m =
910− D.fromStreamD $ D.splitOnSuffixSeq False patt f (D.toStreamD m)
912+ fromStreamD $ D.splitOnSuffixSeq False patt f (toStreamD m)
911
913
912{-
914{-
913-- | Like 'splitOn' but drops any empty splits.
915-- | Like 'splitOn' but drops any empty splits.
@@ -916,7 +918,8 @@ splitOnSuffixSeq patt f m =
916wordsOn
918wordsOn
917 :: (IsStream t, Monad m, Storable a, Eq a)
919 :: (IsStream t, Monad m, Storable a, Eq a)
918 => Array a -> Fold m a b -> t m a -> t m b
920 => Array a -> Fold m a b -> t m a -> t m b
921+wordsOn subseq f m = undefined
919−wordsOn subseq f m = undefined -- D.fromStreamD $ D.wordsOn f subseq (D.toStreamD m)
922+ -- fromStreamD $ D.wordsOn f subseq (toStreamD m)
920-}
923-}
921
924
922-- | Like 'splitOnSuffixSeq' but keeps the suffix intact in the splits.
925-- | Like 'splitOnSuffixSeq' but keeps the suffix intact in the splits.
@@ -953,7 +956,7 @@ splitWithSuffixSeq
953 :: (IsStream t, MonadIO m, Storable a, Enum a, Eq a)
956 :: (IsStream t, MonadIO m, Storable a, Enum a, Eq a)
954 => Array a -> Fold m a b -> t m a -> t m b
957 => Array a -> Fold m a b -> t m a -> t m b
955splitWithSuffixSeq patt f m =
958splitWithSuffixSeq patt f m =
956− D.fromStreamD $ D.splitOnSuffixSeq True patt f (D.toStreamD m)
959+ fromStreamD $ D.splitOnSuffixSeq True patt f (toStreamD m)
957
960
958{-
961{-
959-- This can be implemented easily using Rabin Karp
962-- This can be implemented easily using Rabin Karp
@@ -963,7 +966,7 @@ splitOnSuffixSeqAny
963 :: (IsStream t, Monad m, Storable a, Integral a)
966 :: (IsStream t, Monad m, Storable a, Integral a)
964 => [Array a] -> Fold m a b -> t m a -> t m b
967 => [Array a] -> Fold m a b -> t m a -> t m b
965splitOnSuffixSeqAny subseq f m = undefined
968splitOnSuffixSeqAny subseq f m = undefined
966− -- D.fromStreamD $ D.splitPostAny f subseq (D.toStreamD m)
969+ -- fromStreamD $ D.splitPostAny f subseq (toStreamD m)
967-}
970-}
968
971
969------------------------------------------------------------------------------
972------------------------------------------------------------------------------
@@ -986,7 +989,7 @@ splitOnSuffixSeqAny subseq f m = undefined
986chunksOf
989chunksOf
987 :: (IsStream t, Monad m)
990 :: (IsStream t, Monad m)
988 => Int -> Fold m a b -> t m a -> t m b
991 => Int -> Fold m a b -> t m a -> t m b
989−chunksOf n f = D.fromStreamD . D.chunksOf n f . D.toStreamD
992+chunksOf n f = fromStreamD . D.chunksOf n f . toStreamD
990
993
991-- |
994-- |
992--
995--
@@ -995,7 +998,7 @@ chunksOf n f = D.fromStreamD . D.chunksOf n f . D.toStreamD
995chunksOf2
998chunksOf2
996 :: (IsStream t, Monad m)
999 :: (IsStream t, Monad m)
997 => Int -> m c -> Fold2 m c a b -> t m a -> t m b
1000 => Int -> m c -> Fold2 m c a b -> t m a -> t m b
998−chunksOf2 n action f m = D.fromStreamD $ D.groupsOf2 n action f (D.toStreamD m)
1001+chunksOf2 n action f m = fromStreamD $ D.groupsOf2 n action f (toStreamD m)
999
1002
1000-- | @arraysOf n stream@ groups the elements in the input stream into arrays of
1003-- | @arraysOf n stream@ groups the elements in the input stream into arrays of
1001-- @n@ elements each.
1004-- @n@ elements each.
@@ -1008,7 +1011,7 @@ chunksOf2 n action f m = D.fromStreamD $ D.groupsOf2 n action f (D.toStreamD m)
1008{-# INLINE arraysOf #-}
1011{-# INLINE arraysOf #-}
1009arraysOf :: (IsStream t, MonadIO m, Storable a)
1012arraysOf :: (IsStream t, MonadIO m, Storable a)
1010 => Int -> t m a -> t m (Array a)
1013 => Int -> t m a -> t m (Array a)
1011−arraysOf n = D.fromStreamD . A.arraysOf n . D.toStreamD
1014+arraysOf n = fromStreamD . A.arraysOf n . toStreamD
1012
1015
1013-- XXX we can implement this by repeatedly applying the 'lrunFor' fold.
1016-- XXX we can implement this by repeatedly applying the 'lrunFor' fold.
1014-- XXX add this example after fixing the serial stream rate control
1017-- XXX add this example after fixing the serial stream rate control
@@ -1026,7 +1029,7 @@ intervalsOf
1026 => Double -> Fold m a b -> t m a -> t m b
1029 => Double -> Fold m a b -> t m a -> t m b
1027intervalsOf n f xs =
1030intervalsOf n f xs =
1028 splitWithSuffix isNothing (FL.catMaybes f)
1031 splitWithSuffix isNothing (FL.catMaybes f)
1029− (interjectSuffix n (return Nothing) (Serial.map Just xs))
1032+ (interjectSuffix n (return Nothing) (map Just xs))
1030
1033
1031------------------------------------------------------------------------------
1034------------------------------------------------------------------------------
1032-- Windowed classification
1035-- Windowed classification
@@ -1223,7 +1226,7 @@ classifySessionsBy tick reset ejectPred tmout
1223 , sessionCount = 0
1226 , sessionCount = 0
1224 , sessionTimerHeap = H.empty
1227 , sessionTimerHeap = H.empty
1225 , sessionKeyValueMap = Map.empty
1228 , sessionKeyValueMap = Map.empty
1226− , sessionOutputStream = K.nil
1229+ , sessionOutputStream = IsStream.nil
1227 }
1230 }
1228
1231
1229 -- We can eject sessions based on the current session count to limit
1232 -- We can eject sessions based on the current session count to limit
@@ -1274,7 +1277,7 @@ classifySessionsBy tick reset ejectPred tmout
1274 let acc = Tuple' timestamp fs1
1277 let acc = Tuple' timestamp fs1
1275 (hp1, mp1, out1, cnt1) <- do
1278 (hp1, mp1, out1, cnt1) <- do
1276 let vars = (sessionTimerHeap, sessionKeyValueMap,
1279 let vars = (sessionTimerHeap, sessionKeyValueMap,
1277− K.nil, sessionCount)
1280+ IsStream.nil, sessionCount)
1278 case mOld of
1281 case mOld of
1279 -- inserting new entry
1282 -- inserting new entry
1280 Nothing -> do
1283 Nothing -> do
@@ -1323,7 +1326,7 @@ classifySessionsBy tick reset ejectPred tmout
1323 ejectAll
1326 ejectAll
1324 ( sessionTimerHeap
1327 ( sessionTimerHeap
1325 , sessionKeyValueMap
1328 , sessionKeyValueMap
1326− , K.nil
1329+ , IsStream.nil
1327 , sessionCount
1330 , sessionCount
1328 )
1331 )
1329 return $ session
1332 return $ session
@@ -1336,7 +1339,7 @@ classifySessionsBy tick reset ejectPred tmout
1336 -- delete from map and output the fold accumulator
1339 -- delete from map and output the fold accumulator
1337 ejectEntry hp mp out cnt acc key = do
1340 ejectEntry hp mp out cnt acc key = do
1338 sess <- extract acc
1341 sess <- extract acc
1339− let out1 = (key, sess) `K.cons` out
1342+ let out1 = (key, sess) `cons` out
1340 let mp1 = Map.delete key mp
1343 let mp1 = Map.delete key mp
1341 return (hp, mp1, out1, cnt - 1)
1344 return (hp, mp1, out1, cnt - 1)
1342
1345
@@ -1372,7 +1375,8 @@ classifySessionsBy tick reset ejectPred tmout
1372
1375
1373 ejectExpired session@SessionState{..} curTime = do
1376 ejectExpired session@SessionState{..} curTime = do
1374 (hp', mp', out, count) <-
1377 (hp', mp', out, count) <-
1378+ ejectLoop
1375− ejectLoop sessionTimerHeap sessionKeyValueMap K.nil sessionCount
1379+ sessionTimerHeap sessionKeyValueMap IsStream.nil sessionCount
1376 return $ session
1380 return $ session
1377 { sessionCurTime = curTime
1381 { sessionCurTime = curTime
1378 , sessionCount = count
1382 , sessionCount = count
@@ -1414,7 +1418,7 @@ classifySessionsBy tick reset ejectPred tmout
1414 return (hp, mp, out, cnt)
1418 return (hp, mp, out, cnt)
1415
1419
1416 -- merge timer events in the stream
1420 -- merge timer events in the stream
1417− stream = Serial.map Just str `Par.parallelFst` repeatM timer
1421+ stream = map Just str `parallelFst` repeatM timer
1418 timer = do
1422 timer = do
1419 liftIO $ threadDelay (round $ tick * 1000000)
1423 liftIO $ threadDelay (round $ tick * 1000000)
1420 return Nothing
1424 return Nothing
@@ -1510,7 +1514,7 @@ splitInnerBy
1510 -> t m (f a)
1514 -> t m (f a)
1511 -> t m (f a)
1515 -> t m (f a)
1512splitInnerBy splitter joiner xs =
1516splitInnerBy splitter joiner xs =
1513− D.fromStreamD $ D.splitInnerBy splitter joiner $ D.toStreamD xs
1517+ fromStreamD $ D.splitInnerBy splitter joiner $ toStreamD xs
1514
1518
1515-- | Like 'splitInnerBy' but splits assuming the separator joins the segment in
1519-- | Like 'splitInnerBy' but splits assuming the separator joins the segment in
1516-- a suffix style.
1520-- a suffix style.
@@ -1524,4 +1528,4 @@ splitInnerBySuffix
1524 -> t m (f a)
1528 -> t m (f a)
1525 -> t m (f a)
1529 -> t m (f a)
1526splitInnerBySuffix splitter joiner xs =
1530splitInnerBySuffix splitter joiner xs =
1527− D.fromStreamD $ D.splitInnerBySuffix splitter joiner $ D.toStreamD xs
1531+ fromStreamD $ D.splitInnerBySuffix splitter joiner $ toStreamD xs
src/Streamly/Internal/Data/Stream/IsStream/Top.hs+15−15
@@ -61,9 +61,9 @@ import Data.Semigroup (Semigroup(..))
61#endif
61#endif
62import Streamly.Internal.Control.Concurrent (MonadAsync)
62import Streamly.Internal.Control.Concurrent (MonadAsync)
63import Streamly.Internal.Data.Stream.IsStream.Common (concatM)
63import Streamly.Internal.Data.Stream.IsStream.Common (concatM)
64−import Streamly.Internal.Data.Stream.Prelude (foldl', fromList)
64+import Streamly.Internal.Data.Stream.IsStream.Type
65+ (IsStream(..), adapt, foldl', fromList)
65import Streamly.Internal.Data.Stream.Serial (SerialT)
66import Streamly.Internal.Data.Stream.Serial (SerialT)
66−import Streamly.Internal.Data.Stream.StreamK (IsStream)
67import Streamly.Internal.Data.Time.Units (NanoSecond64(..), toRelTime64)
67import Streamly.Internal.Data.Time.Units (NanoSecond64(..), toRelTime64)
68
68
69import qualified Data.List as List
69import qualified Data.List as List
@@ -75,7 +75,7 @@ import qualified Streamly.Internal.Data.Stream.IsStream.Generate as Stream
75import qualified Streamly.Internal.Data.Stream.IsStream.Expand as Stream
75import qualified Streamly.Internal.Data.Stream.IsStream.Expand as Stream
76import qualified Streamly.Internal.Data.Stream.IsStream.Reduce as Stream
76import qualified Streamly.Internal.Data.Stream.IsStream.Reduce as Stream
77import qualified Streamly.Internal.Data.Stream.IsStream.Transform as Stream
77import qualified Streamly.Internal.Data.Stream.IsStream.Transform as Stream
78−import qualified Streamly.Internal.Data.Stream.StreamK as StreamK
78+import qualified Streamly.Internal.Data.Stream.IsStream.Type as IsStream
79
79
80import Prelude hiding (filter, zipWith, concatMap, concat)
80import Prelude hiding (filter, zipWith, concatMap, concat)
81
81
@@ -272,7 +272,7 @@ innerJoin eq s1 s2 = do
272 b <- s2
272 b <- s2
273 if a `eq` b
273 if a `eq` b
274 then return (a, b)
274 then return (a, b)
275− else StreamK.nil
275+ else Stream.nil
276
276
277-- If the second stream is too big it can be partitioned based on hashes and
277-- If the second stream is too big it can be partitioned based on hashes and
278-- then we can process one parition at a time.
278-- then we can process one parition at a time.
@@ -338,8 +338,8 @@ leftJoin eq s1 s2 = Stream.evalStateT (return False) $ do
338 let final = do
338 let final = do
339 r <- lift get
339 r <- lift get
340 if r
340 if r
341− then StreamK.nil
341+ then Stream.nil
342− else StreamK.fromPure Nothing
342+ else Stream.fromPure Nothing
343 b <- fmap Just (Stream.liftInner s2) <> final
343 b <- fmap Just (Stream.liftInner s2) <> final
344 case b of
344 case b of
345 Just b1 ->
345 Just b1 ->
@@ -347,7 +347,7 @@ leftJoin eq s1 s2 = Stream.evalStateT (return False) $ do
347 then do
347 then do
348 lift $ put True
348 lift $ put True
349 return (a, Just b1)
349 return (a, Just b1)
350− else StreamK.nil
350+ else Stream.nil
351 Nothing -> return (a, Nothing)
351 Nothing -> return (a, Nothing)
352
352
353-- | Like 'outerJoin' but uses a hashmap for efficiency.
353-- | Like 'outerJoin' but uses a hashmap for efficiency.
@@ -415,11 +415,11 @@ outerJoin eq s1 s =
415 let final = do
415 let final = do
416 r <- lift get
416 r <- lift get
417 if r
417 if r
418− then StreamK.nil
418+ then Stream.nil
419− else StreamK.fromPure Nothing
419+ else Stream.fromPure Nothing
420 (_i, b) <-
420 (_i, b) <-
421− Stream.indexed
421+ let stream = IsStream.fromSerial $ Array.toStream arr
422− $ fmap Just (Stream.liftInner (Array.toStream arr)) <> final
422+ in Stream.indexed $ fmap Just (Stream.liftInner stream) <> final
423 case b of
423 case b of
424 Just (b1, _used) ->
424 Just (b1, _used) ->
425 if a `eq` b1
425 if a `eq` b1
@@ -428,7 +428,7 @@ outerJoin eq s1 s =
428 -- XXX Need to use a mutable array
428 -- XXX Need to use a mutable array
429 -- when (not used) $ Array.writeIndex i True
429 -- when (not used) $ Array.writeIndex i True
430 return (Just a, Just b1)
430 return (Just a, Just b1)
431− else StreamK.nil
431+ else Stream.nil
432 Nothing -> return (Just a, Nothing)
432 Nothing -> return (Just a, Nothing)
433
433
434-- Put the b's that have been paired, in another hash or mutate the hash to set
434-- Put the b's that have been paired, in another hash or mutate the hash to set
@@ -496,7 +496,7 @@ intersectBy eq s1 s2 =
496 concatM
496 concatM
497 $ do
497 $ do
498 -- This may work well when s2 is small
498 -- This may work well when s2 is small
499− xs <- Stream.toListRev $ Stream.uniqBy eq $ StreamK.adapt s2
499+ xs <- Stream.toListRev $ Stream.uniqBy eq $ adapt s2
500 return $ Stream.filter (\x -> List.any (eq x) xs) s1
500 return $ Stream.filter (\x -> List.any (eq x) xs) s1
501
501
502-- | Like 'intersectBy' but works only on sorted streams.
502-- | Like 'intersectBy' but works only on sorted streams.
@@ -546,7 +546,7 @@ differenceBy eq s1 s2 =
546 -- not emitting an element if it was successfully deleted from s2.
546 -- not emitting an element if it was successfully deleted from s2.
547 -- we will need a deleteBy that can return whether the element was
547 -- we will need a deleteBy that can return whether the element was
548 -- deleted or not.
548 -- deleted or not.
549− xs <- Stream.toList $ StreamK.adapt s1
549+ xs <- Stream.toList $ adapt s1
550 fmap fromList $ foldl' (flip (List.deleteBy eq)) xs s2
550 fmap fromList $ foldl' (flip (List.deleteBy eq)) xs s2
551
551
552-- | Like 'differenceBy' but works only on sorted streams.
552-- | Like 'differenceBy' but works only on sorted streams.
@@ -585,7 +585,7 @@ unionBy :: (IsStream t, MonadAsync m, Semigroup (t m a)) =>
585unionBy eq s1 s2 =
585unionBy eq s1 s2 =
586 concatM
586 concatM
587 $ do
587 $ do
588− xs <- Stream.toList $ StreamK.adapt s2
588+ xs <- Stream.toList $ adapt s2
589 -- XXX we can use postscanlMAfter' instead of IORef
589 -- XXX we can use postscanlMAfter' instead of IORef
590 ref <- liftIO $ newIORef $! List.nubBy eq xs
590 ref <- liftIO $ newIORef $! List.nubBy eq xs
591 let f x = do
591 let f x = do
src/Streamly/Internal/Data/Stream/IsStream/Transform.hs+107−28
@@ -14,11 +14,12 @@ module Streamly.Internal.Data.Stream.IsStream.Transform
14
14
15 -- * Folding
15 -- * Folding
16 , foldrS
16 , foldrS
17+ , foldrSShared
17 , foldrT
18 , foldrT
18
19
19 -- * Mapping
20 -- * Mapping
20 -- | Stateless one-to-one maps.
21 -- | Stateless one-to-one maps.
21− , Serial.map
22+ , map
22 , sequence
23 , sequence
23 , mapM
24 , mapM
24 , smapM
25 , smapM
@@ -30,6 +31,8 @@ module Streamly.Internal.Data.Stream.IsStream.Transform
30 , tap
31 , tap
31 , tapOffsetEvery
32 , tapOffsetEvery
32 , tapAsync
33 , tapAsync
34+ , tapAsyncK
35+ , distributeAsync_
33 , tapRate
36 , tapRate
34 , pollCounts
37 , pollCounts
35
38
@@ -170,7 +173,8 @@ module Streamly.Internal.Data.Stream.IsStream.Transform
170 -- ** Concurrent Pipelines
173 -- ** Concurrent Pipelines
171 -- | Run streaming stages concurrently.
174 -- | Run streaming stages concurrently.
172
175
176+ , mkAsync
173− , Par.mkParallel
177+ , mkParallel
174 , applyAsync
178 , applyAsync
175 , (|$)
179 , (|$)
176 , (|&)
180 , (|&)
@@ -226,6 +230,7 @@ import Streamly.Internal.Data.Stream.IsStream.Common
226 ( absTimesWith
230 ( absTimesWith
227 , drop
231 , drop
228 , findIndices
232 , findIndices
233+ , map
229 , postscanlM'
234 , postscanlM'
230 , relTimesWith
235 , relTimesWith
231 , reverse
236 , reverse
@@ -236,31 +241,35 @@ import Streamly.Internal.Data.Stream.IsStream.Common
236 , takeWhile
241 , takeWhile
237 , interjectSuffix
242 , interjectSuffix
238 , intersperseM
243 , intersperseM
244+ , mkAsync
245+ , mkParallel
246+ , zipWith
239 )
247 )
240import Streamly.Internal.Control.Concurrent (MonadAsync)
248import Streamly.Internal.Control.Concurrent (MonadAsync)
241−import Streamly.Internal.Data.Stream.Prelude (fromStreamS, toStreamS)
249+import Streamly.Internal.Data.Stream.IsStream.Type
250+ (IsStream(..), fromStreamS, toStreamS, fromStreamD, toStreamD, toConsK)
242import Streamly.Internal.Data.Stream.Serial (SerialT)
251import Streamly.Internal.Data.Stream.Serial (SerialT)
243−import Streamly.Internal.Data.Stream.StreamD (fromStreamD, toStreamD)
244−import Streamly.Internal.Data.Stream.StreamK (IsStream)
245import Streamly.Internal.Data.SVar (Rate(..))
252import Streamly.Internal.Data.SVar (Rate(..))
246import Streamly.Internal.Data.Time.Units (TimeUnit64, AbsTime, RelTime64)
253import Streamly.Internal.Data.Time.Units (TimeUnit64, AbsTime, RelTime64)
247
254
248import qualified Streamly.Internal.Data.Fold as FL
255import qualified Streamly.Internal.Data.Fold as FL
249import qualified Streamly.Internal.Data.Stream.Parallel as Par
256import qualified Streamly.Internal.Data.Stream.Parallel as Par
250−import qualified Streamly.Internal.Data.Stream.Prelude as P
251import qualified Streamly.Internal.Data.Stream.Serial as Serial
257import qualified Streamly.Internal.Data.Stream.Serial as Serial
252import qualified Streamly.Internal.Data.Stream.StreamD as D
258import qualified Streamly.Internal.Data.Stream.StreamD as D
259+#if __GLASGOW_HASKELL__ == 802
253import qualified Streamly.Internal.Data.Stream.StreamK as K
260import qualified Streamly.Internal.Data.Stream.StreamK as K
261+#endif
254−import qualified Streamly.Internal.Data.Stream.Zip as Z
262+import qualified Streamly.Internal.Data.Stream.StreamK.Type as K
255#ifdef USE_STREAMK_ONLY
263#ifdef USE_STREAMK_ONLY
256import qualified Streamly.Internal.Data.Stream.StreamK as S
264import qualified Streamly.Internal.Data.Stream.StreamK as S
257#else
265#else
258import qualified Streamly.Internal.Data.Stream.StreamD as S
266import qualified Streamly.Internal.Data.Stream.StreamD as S
259#endif
267#endif
268+import qualified Prelude
260
269
261import Prelude hiding
270import Prelude hiding
262 ( filter, drop, dropWhile, take, takeWhile, foldr, map, mapM, sequence
271 ( filter, drop, dropWhile, take, takeWhile, foldr, map, mapM, sequence
263− , reverse, foldr1 , scanl, scanl1)
272+ , reverse, foldr1 , scanl, scanl1, zipWith)
264
273
265--
274--
266-- $setup
275-- $setup
@@ -320,7 +329,21 @@ transform pipe xs = fromStreamD $ D.transform pipe (toStreamD xs)
320-- /Pre-release/
329-- /Pre-release/
321{-# INLINE foldrS #-}
330{-# INLINE foldrS #-}
322foldrS :: IsStream t => (a -> t m b -> t m b) -> t m b -> t m a -> t m b
331foldrS :: IsStream t => (a -> t m b -> t m b) -> t m b -> t m a -> t m b
332+foldrS f z xs =
333+ fromStream
323−foldrS = K.foldrS
334+ $ K.foldrS
335+ (\y ys -> toStream $ f y (fromStream ys))
336+ (toStream z)
337+ (toStream xs)
338+
339+{-# INLINE foldrSShared #-}
340+foldrSShared :: IsStream t => (a -> t m b -> t m b) -> t m b -> t m a -> t m b
341+foldrSShared f z xs =
342+ fromStream
343+ $ K.foldrSShared
344+ (\y ys -> toStream $ f y (fromStream ys))
345+ (toStream z)
346+ (toStream xs)
324
347
325-- | Right fold to a transformer monad. This is the most general right fold
348-- | Right fold to a transformer monad. This is the most general right fold
326-- function. 'foldrS' is a special case of 'foldrT', however 'foldrS'
349-- function. 'foldrS' is a special case of 'foldrT', however 'foldrS'
@@ -370,8 +393,9 @@ foldrT f z s = S.foldrT f z (toStreamS s)
370--
393--
371-- @since 0.1.0
394-- @since 0.1.0
372{-# INLINE_EARLY mapM #-}
395{-# INLINE_EARLY mapM #-}
373−mapM :: (IsStream t, MonadAsync m) => (a -> m b) -> t m a -> t m b
396+mapM :: forall t m a b. (IsStream t, MonadAsync m) =>
374−mapM = K.mapM
397+ (a -> m b) -> t m a -> t m b
398+mapM f = fromStream . K.mapMWith (toConsK (consM @t)) f . toStream
375
399
376{-# RULES "mapM serial" mapM = mapMSerial #-}
400{-# RULES "mapM serial" mapM = mapMSerial #-}
377{-# INLINE mapMSerial #-}
401{-# INLINE mapMSerial #-}
@@ -439,7 +463,7 @@ sequence m = fromStreamS $ S.sequence (toStreamS m)
439-- @since 0.7.0
463-- @since 0.7.0
440{-# INLINE tap #-}
464{-# INLINE tap #-}
441tap :: (IsStream t, Monad m) => FL.Fold m a b -> t m a -> t m a
465tap :: (IsStream t, Monad m) => FL.Fold m a b -> t m a -> t m a
442−tap f xs = D.fromStreamD $ D.tap f (D.toStreamD xs)
466+tap f xs = fromStreamD $ D.tap f (toStreamD xs)
443
467
444-- XXX Remove this. It can be expressed in terms of Fold.sampleFromThen.
468-- XXX Remove this. It can be expressed in terms of Fold.sampleFromThen.
445--
469--
@@ -458,7 +482,7 @@ tap f xs = D.fromStreamD $ D.tap f (D.toStreamD xs)
458tapOffsetEvery :: (IsStream t, Monad m)
482tapOffsetEvery :: (IsStream t, Monad m)
459 => Int -> Int -> FL.Fold m a b -> t m a -> t m a
483 => Int -> Int -> FL.Fold m a b -> t m a -> t m a
460tapOffsetEvery offset n f xs =
484tapOffsetEvery offset n f xs =
461− D.fromStreamD $ D.tapOffsetEvery offset n f (D.toStreamD xs)
485+ fromStreamD $ D.tapOffsetEvery offset n f (toStreamD xs)
462
486
463-- | Redirect a copy of the stream to a supplied fold and run it concurrently
487-- | Redirect a copy of the stream to a supplied fold and run it concurrently
464-- in an independent thread. The fold may buffer some elements. The buffer size
488-- in an independent thread. The fold may buffer some elements. The buffer size
@@ -490,7 +514,61 @@ tapOffsetEvery offset n f xs =
490-- /Pre-release/
514-- /Pre-release/
491{-# INLINE tapAsync #-}
515{-# INLINE tapAsync #-}
492tapAsync :: (IsStream t, MonadAsync m) => FL.Fold m a b -> t m a -> t m a
516tapAsync :: (IsStream t, MonadAsync m) => FL.Fold m a b -> t m a -> t m a
493−tapAsync f xs = D.fromStreamD $ Par.tapAsyncF f (D.toStreamD xs)
517+tapAsync f xs = fromStreamD $ Par.tapAsyncF f (toStreamD xs)
518+
519+-- | Redirect a copy of the stream to a supplied fold and run it concurrently
520+-- in an independent thread. The fold may buffer some elements. The buffer size
521+-- is determined by the prevailing 'Streamly.Prelude.maxBuffer' setting.
522+--
523+-- @
524+-- Stream m a -> m b
525+-- |
526+-- -----stream m a ---------------stream m a-----
527+--
528+-- @
529+--
530+-- @
531+-- > S.drain $ S.tapAsync (S.mapM_ print) (S.enumerateFromTo 1 2)
532+-- 1
533+-- 2
534+-- @
535+--
536+-- Exceptions from the concurrently running fold are propagated to the current
537+-- computation. Note that, because of buffering in the fold, exceptions may be
538+-- delayed and may not correspond to the current element being processed in the
539+-- parent stream, but we guarantee that before the parent stream stops the tap
540+-- finishes and all exceptions from it are drained.
541+--
542+--
543+-- Compare with 'tap'.
544+--
545+-- /Pre-release/
546+{-# INLINE tapAsyncK #-}
547+tapAsyncK :: (IsStream t, MonadAsync m) => (t m a -> m b) -> t m a -> t m a
548+tapAsyncK f m = fromStream $ Par.tapAsyncK (f . fromStream) (toStream m)
549+
550+-- | Concurrently distribute a stream to a collection of fold functions,
551+-- discarding the outputs of the folds.
552+--
553+-- @
554+-- > Stream.drain $ Stream.distributeAsync_ [Stream.mapM_ print, Stream.mapM_ print] (Stream.enumerateFromTo 1 2)
555+-- 1
556+-- 2
557+-- 1
558+-- 2
559+--
560+-- @
561+--
562+-- @
563+-- distributeAsync_ = flip (foldr tapAsync)
564+-- @
565+--
566+-- /Pre-release/
567+--
568+{-# INLINE distributeAsync_ #-}
569+distributeAsync_ :: (Foldable f, IsStream t, MonadAsync m)
570+ => f (t m a -> m b) -> t m a -> t m a
571+distributeAsync_ = flip (Prelude.foldr tapAsyncK)
494
572
495-- | @pollCounts predicate transform fold stream@ counts those elements in the
573-- | @pollCounts predicate transform fold stream@ counts those elements in the
496-- stream that pass the @predicate@. The resulting count stream is sent to
574-- stream that pass the @predicate@. The resulting count stream is sent to
@@ -518,9 +596,9 @@ pollCounts ::
518 -> t m a
596 -> t m a
519 -> t m a
597 -> t m a
520pollCounts predicate transf f xs =
598pollCounts predicate transf f xs =
521− D.fromStreamD
599+ fromStreamD
522− $ D.pollCounts predicate (D.toStreamD . transf . D.fromStreamD) f
600+ $ D.pollCounts predicate (toStreamD . transf . fromStreamD) f
523− $ D.toStreamD xs
601+ $ toStreamD xs
524
602
525-- | Calls the supplied function with the number of elements consumed
603-- | Calls the supplied function with the number of elements consumed
526-- every @n@ seconds. The given function is run in a separate thread
604-- every @n@ seconds. The given function is run in a separate thread
@@ -547,7 +625,7 @@ tapRate ::
547 -> (Int -> m b)
625 -> (Int -> m b)
548 -> t m a
626 -> t m a
549 -> t m a
627 -> t m a
550−tapRate n f xs = D.fromStreamD $ D.tapRate n f $ D.toStreamD xs
628+tapRate n f xs = fromStreamD $ D.tapRate n f $ toStreamD xs
551
629
552-- | Apply a monadic function to each element flowing through the stream and
630-- | Apply a monadic function to each element flowing through the stream and
553-- discard the results.
631-- discard the results.
@@ -583,7 +661,7 @@ trace f = mapM (\x -> void (f x) >> return x)
583-- /Pre-release/
661-- /Pre-release/
584{-# INLINE trace_ #-}
662{-# INLINE trace_ #-}
585trace_ :: (IsStream t, Monad m) => m b -> t m a -> t m a
663trace_ :: (IsStream t, Monad m) => m b -> t m a -> t m a
586−trace_ eff = Serial.mapM (\x -> eff >> return x)
664+trace_ eff = fromStreamD . D.mapM (\x -> eff >> return x) . toStreamD
587
665
588------------------------------------------------------------------------------
666------------------------------------------------------------------------------
589-- Scanning with a Fold
667-- Scanning with a Fold
@@ -597,7 +675,8 @@ trace_ eff = Serial.mapM (\x -> eff >> return x)
597-- @since 0.7.0
675-- @since 0.7.0
598{-# INLINE scan #-}
676{-# INLINE scan #-}
599scan :: (IsStream t, Monad m) => Fold m a b -> t m a -> t m b
677scan :: (IsStream t, Monad m) => Fold m a b -> t m a -> t m b
600−scan = P.scanOnce
678+-- scan = P.scanOnce
679+scan fld m = fromStreamD $ D.scanOnce fld $ toStreamD m
601
680
602-- | Postscan a stream using the given monadic fold.
681-- | Postscan a stream using the given monadic fold.
603--
682--
@@ -617,7 +696,7 @@ scan = P.scanOnce
617-- @since 0.7.0
696-- @since 0.7.0
618{-# INLINE postscan #-}
697{-# INLINE postscan #-}
619postscan :: (IsStream t, Monad m) => Fold m a b -> t m a -> t m b
698postscan :: (IsStream t, Monad m) => Fold m a b -> t m a -> t m b
620−postscan = P.postscanOnce
699+postscan fld = fromStreamD . D.postscanOnce fld . toStreamD
621
700
622------------------------------------------------------------------------------
701------------------------------------------------------------------------------
623-- Scanning - Transformation by Folding
702-- Scanning - Transformation by Folding
@@ -644,7 +723,7 @@ postscan = P.postscanOnce
644{-# DEPRECATED scanx "Please use scanl followed by map instead." #-}
723{-# DEPRECATED scanx "Please use scanl followed by map instead." #-}
645{-# INLINE scanx #-}
724{-# INLINE scanx #-}
646scanx :: (IsStream t, Monad m) => (x -> a -> x) -> x -> (x -> b) -> t m a -> t m b
725scanx :: (IsStream t, Monad m) => (x -> a -> x) -> x -> (x -> b) -> t m a -> t m b
647−scanx = P.scanlx'
726+scanx step begin done = fromStreamS . S.scanlx' step begin done . toStreamS
648
727
649-- XXX this needs to be concurrent
728-- XXX this needs to be concurrent
650-- XXX because of the use of D.cons for appending, scanlM' has quadratic
729-- XXX because of the use of D.cons for appending, scanlM' has quadratic
@@ -807,7 +886,7 @@ filter :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> t m a
807filter p m = fromStreamS $ S.filter p $ toStreamS m
886filter p m = fromStreamS $ S.filter p $ toStreamS m
808#else
887#else
809filter :: IsStream t => (a -> Bool) -> t m a -> t m a
888filter :: IsStream t => (a -> Bool) -> t m a -> t m a
810−filter = K.filter
889+filter p m = fromStream $ K.filter p $ toStream m
811#endif
890#endif
812
891
813-- | Same as 'filter' but with a monadic predicate.
892-- | Same as 'filter' but with a monadic predicate.
@@ -1365,7 +1444,7 @@ indexedR n = fromStreamD . D.indexedR n . toStreamD
1365{-# INLINE timestampWith #-}
1444{-# INLINE timestampWith #-}
1366timestampWith :: (IsStream t, MonadAsync m, Functor (t m))
1445timestampWith :: (IsStream t, MonadAsync m, Functor (t m))
1367 => Double -> t m a -> t m (AbsTime, a)
1446 => Double -> t m a -> t m (AbsTime, a)
1368−timestampWith g stream = Z.zipWith (flip (,)) stream (absTimesWith g)
1447+timestampWith g stream = zipWith (flip (,)) stream (absTimesWith g)
1369
1448
1370-- TBD: check performance vs a custom implementation without using zipWith.
1449-- TBD: check performance vs a custom implementation without using zipWith.
1371--
1450--
@@ -1390,7 +1469,7 @@ timestamped = timestampWith 0.01
1390{-# INLINE timeIndexWith #-}
1469{-# INLINE timeIndexWith #-}
1391timeIndexWith :: (IsStream t, MonadAsync m, Functor (t m))
1470timeIndexWith :: (IsStream t, MonadAsync m, Functor (t m))
1392 => Double -> t m a -> t m (RelTime64, a)
1471 => Double -> t m a -> t m (RelTime64, a)
1393−timeIndexWith g stream = Z.zipWith (flip (,)) stream (relTimesWith g)
1472+timeIndexWith g stream = zipWith (flip (,)) stream (relTimesWith g)
1394
1473
1395-- | Pair each element in a stream with relative times starting from 0, using a
1474-- | Pair each element in a stream with relative times starting from 0, using a
1396-- 10 ms granularity clock. The time is measured just before the element is
1475-- 10 ms granularity clock. The time is measured just before the element is
@@ -1480,7 +1559,7 @@ mapMaybe f m = fromStreamS $ S.mapMaybe f $ toStreamS m
1480{-# INLINE_EARLY mapMaybeM #-}
1559{-# INLINE_EARLY mapMaybeM #-}
1481mapMaybeM :: (IsStream t, MonadAsync m, Functor (t m))
1560mapMaybeM :: (IsStream t, MonadAsync m, Functor (t m))
1482 => (a -> m (Maybe b)) -> t m a -> t m b
1561 => (a -> m (Maybe b)) -> t m a -> t m b
1483−mapMaybeM f = fmap fromJust . filter isJust . K.mapM f
1562+mapMaybeM f = fmap fromJust . filter isJust . mapM f
1484
1563
1485{-# RULES "mapMaybeM serial" mapMaybeM = mapMaybeMSerial #-}
1564{-# RULES "mapMaybeM serial" mapMaybeM = mapMaybeMSerial #-}
1486{-# INLINE mapMaybeMSerial #-}
1565{-# INLINE mapMaybeMSerial #-}
@@ -1559,8 +1638,8 @@ both = fmap (either id id)
1559-- @since 0.8.0
1638-- @since 0.8.0
1560{-# INLINE (|$) #-}
1639{-# INLINE (|$) #-}
1561(|$) :: (IsStream t, MonadAsync m) => (t m a -> t m b) -> (t m a -> t m b)
1640(|$) :: (IsStream t, MonadAsync m) => (t m a -> t m b) -> (t m a -> t m b)
1562−-- (|$) f = f . Async.mkAsync
1641+-- (|$) f = f . mkAsync
1563−(|$) f = f . Par.mkParallel
1642+(|$) f = f . mkParallel
1564
1643
1565infixr 0 |$
1644infixr 0 |$
1566
1645
src/Streamly/Internal/Data/Stream/IsStream/Type.hsnew file+698
@@ -0,0 +1,698 @@
1+{-# LANGUAGE UndecidableInstances #-}
2+{-# OPTIONS_GHC -Wno-orphans #-}
3+
4+-- |
5+-- Module : Streamly.Internal.Data.Stream.Type
6+-- Copyright : (c) 2017 Composewell Technologies
7+-- License : BSD3
8+-- Maintainer : streamly@composewell.com
9+-- Stability : experimental
10+-- Portability : GHC
11+--
12+--
13+module Streamly.Internal.Data.Stream.IsStream.Type
14+ (
15+ -- * IsStream Type Class
16+ IsStream (..)
17+ , K.Stream (..)
18+ , Streaming
19+
20+ -- * Type Conversion
21+ , fromStreamS
22+ , toStreamS
23+ , fromStreamD
24+ , toStreamD
25+ , adapt
26+ , toConsK
27+
28+ -- * Building a stream
29+ , mkStream
30+ , foldStreamShared
31+ , foldStream
32+
33+ -- * Stream Types
34+ , SerialT
35+ , Serial
36+ , fromSerial
37+
38+ , WSerialT
39+ , WSerial
40+ , fromWSerial
41+
42+ , AsyncT
43+ , Async
44+ , fromAsync
45+
46+ , WAsyncT
47+ , WAsync
48+ , fromWAsync
49+
50+ , AheadT
51+ , Ahead
52+ , fromAhead
53+
54+ , ParallelT
55+ , Parallel
56+ , fromParallel
57+
58+ , ZipSerialM
59+ , ZipSerial
60+ , fromZipSerial
61+
62+ , ZipAsyncM
63+ , ZipAsync
64+ , fromZipAsync
65+
66+ -- * Construction
67+ , cons
68+ , (.:)
69+ , nil
70+ , nilM
71+ , fromPure
72+ , fromEffect
73+ , repeat
74+
75+ -- * Bind/Concat
76+ , bindWith
77+ , concatMapWith
78+
79+ -- * Fold Utilities
80+ , concatFoldableWith
81+ , concatMapFoldableWith
82+ , concatForFoldableWith
83+
84+ -- * Running Effects
85+ , drain
86+
87+ -- * Conversion operations
88+ , fromList
89+ , toList
90+
91+ -- * Fold operations
92+ , foldrM
93+ , foldrMx
94+ , foldr
95+
96+ , foldlx'
97+ , foldlMx'
98+ , foldl'
99+ , fold
100+
101+ -- * Zip style operations
102+ , eqBy
103+ , cmpBy
104+
105+ -- * Deprecated
106+ , interleaving
107+ , zipping
108+ , zippingAsync
109+ )
110+where
111+
112+import Streamly.Internal.Control.Concurrent (MonadAsync)
113+import Streamly.Internal.Data.Fold.Type (Fold (..))
114+import Streamly.Internal.Data.Stream.Serial
115+ (SerialT(..), Serial, WSerialT(..), WSerial)
116+import Streamly.Internal.Data.Stream.Async
117+ (AsyncT(..), Async, WAsyncT(..), WAsync)
118+import Streamly.Internal.Data.Stream.Ahead (AheadT(..), Ahead)
119+import Streamly.Internal.Data.Stream.Parallel (ParallelT(..), Parallel)
120+import Streamly.Internal.Data.Stream.Zip
121+ (ZipSerialM(..), ZipSerial, ZipAsyncM(..), ZipAsync)
122+import Streamly.Internal.Data.SVar.Type (State, adaptState)
123+
124+import qualified Prelude
125+import qualified Streamly.Internal.Data.Stream.Ahead as Ahead
126+import qualified Streamly.Internal.Data.Stream.Async as Async
127+import qualified Streamly.Internal.Data.Stream.Parallel as Parallel
128+import qualified Streamly.Internal.Data.Stream.Serial as Serial
129+import qualified Streamly.Internal.Data.Stream.StreamD.Type as D
130+import qualified Streamly.Internal.Data.Stream.StreamK.Type as K
131+#ifdef USE_STREAMK_ONLY
132+import qualified Streamly.Internal.Data.Stream.StreamK as S
133+import qualified Streamly.Internal.Data.Stream.StreamK.Type as S
134+#else
135+import qualified Streamly.Internal.Data.Stream.StreamD.Type as S
136+#endif
137+import qualified Streamly.Internal.Data.Stream.Zip as Zip
138+
139+import Prelude hiding (foldr, repeat)
140+
141+#include "inline.hs"
142+#define USE_IS_STREAM
143+#include "PreludeCommon.hs"
144+
145+------------------------------------------------------------------------------
146+-- Types that can behave as a Stream
147+------------------------------------------------------------------------------
148+
149+infixr 5 `consM`
150+infixr 5 |:
151+
152+-- XXX Use a different SVar based on the stream type. But we need to make sure
153+-- that we do not lose performance due to polymorphism.
154+--
155+-- | Class of types that can represent a stream of elements of some type 'a' in
156+-- some monad 'm'.
157+--
158+-- /Since: 0.2.0 ("Streamly")/
159+--
160+-- @since 0.8.0
161+class
162+#if __GLASGOW_HASKELL__ >= 806
163+ ( forall m a. MonadAsync m => Semigroup (t m a)
164+ , forall m a. MonadAsync m => Monoid (t m a)
165+ , forall m. Monad m => Functor (t m)
166+ , forall m. MonadAsync m => Applicative (t m)
167+ ) =>
168+#endif
169+ IsStream t where
170+ toStream :: t m a -> K.Stream m a
171+ fromStream :: K.Stream m a -> t m a
172+ -- | Constructs a stream by adding a monadic action at the head of an
173+ -- existing stream. For example:
174+ --
175+ -- @
176+ -- > toList $ getLine \`consM` getLine \`consM` nil
177+ -- hello
178+ -- world
179+ -- ["hello","world"]
180+ -- @
181+ --
182+ -- /Concurrent (do not use 'fromParallel' to construct infinite streams)/
183+ --
184+ -- @since 0.2.0
185+ consM :: MonadAsync m => m a -> t m a -> t m a
186+ -- | Operator equivalent of 'consM'. We can read it as "@parallel colon@"
187+ -- to remember that @|@ comes before ':'.
188+ --
189+ -- @
190+ -- > toList $ getLine |: getLine |: nil
191+ -- hello
192+ -- world
193+ -- ["hello","world"]
194+ -- @
195+ --
196+ -- @
197+ -- let delay = threadDelay 1000000 >> print 1
198+ -- drain $ fromSerial $ delay |: delay |: delay |: nil
199+ -- drain $ fromParallel $ delay |: delay |: delay |: nil
200+ -- @
201+ --
202+ -- /Concurrent (do not use 'fromParallel' to construct infinite streams)/
203+ --
204+ -- @since 0.2.0
205+ (|:) :: MonadAsync m => m a -> t m a -> t m a
206+ -- We can define (|:) just as 'consM' but it is defined explicitly for each
207+ -- type because we want to use SPECIALIZE pragma on the definition.
208+
209+-- | Same as 'IsStream'.
210+--
211+-- @since 0.1.0
212+{-# DEPRECATED Streaming "Please use IsStream instead." #-}
213+type Streaming = IsStream
214+
215+-------------------------------------------------------------------------------
216+-- Type adapting combinators
217+-------------------------------------------------------------------------------
218+
219+-- XXX Move/reset the State here by reconstructing the stream with cleared
220+-- state. Can we make sure we do not do that when t1 = t2? If we do this then
221+-- we do not need to do that explicitly using svarStyle. It would act as
222+-- unShare when the stream type is the same.
223+--
224+-- | Adapt any specific stream type to any other specific stream type.
225+--
226+-- /Since: 0.1.0 ("Streamly")/
227+--
228+-- @since 0.8.0
229+adapt :: (IsStream t1, IsStream t2) => t1 m a -> t2 m a
230+adapt = fromStream . toStream
231+
232+{-# INLINE fromStreamD #-}
233+fromStreamD :: (IS_STREAM Monad m) => D.Stream m a -> STREAM m a
234+fromStreamD = FROM_STREAM . D.toStreamK
235+
236+-- | Adapt a polymorphic consM operation to a StreamK cons operation
237+{-# INLINE toConsK #-}
238+toConsK :: IsStream t =>
239+ (m a -> t m a -> t m a) -> m a -> K.Stream m a -> K.Stream m a
240+toConsK cns x xs = toStream $ x `cns` fromStream xs
241+
242+------------------------------------------------------------------------------
243+-- Building a stream
244+------------------------------------------------------------------------------
245+
246+-- XXX The State is always parameterized by "Stream" which means State is not
247+-- different for different stream types. So we have to manually make sure that
248+-- when converting from one stream to another we migrate the state correctly.
249+-- This can be fixed if we use a different SVar type for different streams.
250+-- Currently we always use "SVar Stream" and therefore a different State type
251+-- parameterized by that stream.
252+--
253+-- XXX Since t is coercible we should be able to coerce k
254+-- mkStream k = fromStream $ MkStream $ coerce k
255+--
256+-- | Build a stream from an 'SVar', a stop continuation, a singleton stream
257+-- continuation and a yield continuation.
258+{-# INLINE_EARLY mkStream #-}
259+mkStream :: IsStream t
260+ => (forall r. State K.Stream m a
261+ -> (a -> t m a -> m r)
262+ -> (a -> m r)
263+ -> m r
264+ -> m r)
265+ -> t m a
266+mkStream k = fromStream $ K.MkStream $ \st yld sng stp ->
267+ let yieldk a r = yld a (toStream r)
268+ in k st yieldk sng stp
269+
270+{-# RULES "mkStream from stream" mkStream = mkStreamFromStream #-}
271+mkStreamFromStream :: IsStream t
272+ => (forall r. State K.Stream m a
273+ -> (a -> K.Stream m a -> m r)
274+ -> (a -> m r)
275+ -> m r
276+ -> m r)
277+ -> t m a
278+mkStreamFromStream k = fromStream $ K.MkStream k
279+
280+{-# RULES "mkStream stream" mkStream = mkStreamStream #-}
281+mkStreamStream
282+ :: (forall r. State K.Stream m a
283+ -> (a -> K.Stream m a -> m r)
284+ -> (a -> m r)
285+ -> m r
286+ -> m r)
287+ -> K.Stream m a
288+mkStreamStream = K.MkStream
289+
290+------------------------------------------------------------------------------
291+-- Folding a stream
292+------------------------------------------------------------------------------
293+
294+-- | Fold a stream by providing an SVar, a stop continuation, a singleton
295+-- continuation and a yield continuation. The stream would share the current
296+-- SVar passed via the State.
297+{-# INLINE_EARLY foldStreamShared #-}
298+foldStreamShared
299+ :: IsStream t
300+ => State K.Stream m a
301+ -> (a -> t m a -> m r)
302+ -> (a -> m r)
303+ -> m r
304+ -> t m a
305+ -> m r
306+foldStreamShared st yld sng stp m =
307+ let yieldk a x = yld a (fromStream x)
308+ K.MkStream k = toStream m
309+ in k st yieldk sng stp
310+
311+-- XXX write a similar rule for foldStream as well?
312+{-# RULES "foldStreamShared from stream"
313+ foldStreamShared = foldStreamSharedStream #-}
314+foldStreamSharedStream
315+ :: State K.Stream m a
316+ -> (a -> K.Stream m a -> m r)
317+ -> (a -> m r)
318+ -> m r
319+ -> K.Stream m a
320+ -> m r
321+foldStreamSharedStream st yld sng stp m =
322+ let K.MkStream k = m
323+ in k st yld sng stp
324+
325+-- | Fold a stream by providing a State, stop continuation, a singleton
326+-- continuation and a yield continuation. The stream will not use the SVar
327+-- passed via State.
328+{-# INLINE foldStream #-}
329+foldStream
330+ :: IsStream t
331+ => State K.Stream m a
332+ -> (a -> t m a -> m r)
333+ -> (a -> m r)
334+ -> m r
335+ -> t m a
336+ -> m r
337+foldStream st yld sng stp m =
338+ let yieldk a x = yld a (fromStream x)
339+ K.MkStream k = toStream m
340+ in k (adaptState st) yieldk sng stp
341+
342+-------------------------------------------------------------------------------
343+-- Serial
344+-------------------------------------------------------------------------------
345+
346+-- | Fix the type of a polymorphic stream as 'SerialT'.
347+--
348+-- /Since: 0.1.0 ("Streamly")/
349+--
350+-- @since 0.8.0
351+fromSerial :: IsStream t => SerialT m a -> t m a
352+fromSerial = adapt
353+
354+instance IsStream SerialT where
355+ toStream = getSerialT
356+ fromStream = SerialT
357+
358+ {-# INLINE consM #-}
359+ {-# SPECIALIZE consM :: IO a -> SerialT IO a -> SerialT IO a #-}
360+ consM = Serial.consM
361+
362+ {-# INLINE (|:) #-}
363+ {-# SPECIALIZE (|:) :: IO a -> SerialT IO a -> SerialT IO a #-}
364+ (|:) = Serial.consM
365+
366+-- | Fix the type of a polymorphic stream as 'WSerialT'.
367+--
368+-- /Since: 0.2.0 ("Streamly")/
369+--
370+-- @since 0.8.0
371+fromWSerial :: IsStream t => WSerialT m a -> t m a
372+fromWSerial = adapt
373+
374+-- | Same as 'fromWSerial'.
375+--
376+-- @since 0.1.0
377+{-# DEPRECATED interleaving "Please use fromWSerial instead." #-}
378+interleaving :: IsStream t => WSerialT m a -> t m a
379+interleaving = fromWSerial
380+
381+instance IsStream WSerialT where
382+ toStream = getWSerialT
383+ fromStream = WSerialT
384+
385+ {-# INLINE consM #-}
386+ {-# SPECIALIZE consM :: IO a -> WSerialT IO a -> WSerialT IO a #-}
387+ consM :: Monad m => m a -> WSerialT m a -> WSerialT m a
388+ consM = Serial.consMWSerial
389+
390+ {-# INLINE (|:) #-}
391+ {-# SPECIALIZE (|:) :: IO a -> WSerialT IO a -> WSerialT IO a #-}
392+ (|:) :: Monad m => m a -> WSerialT m a -> WSerialT m a
393+ (|:) = Serial.consMWSerial
394+
395+-------------------------------------------------------------------------------
396+-- Async
397+-------------------------------------------------------------------------------
398+
399+-- | Fix the type of a polymorphic stream as 'AsyncT'.
400+--
401+-- /Since: 0.1.0 ("Streamly")/
402+--
403+-- @since 0.8.0
404+fromAsync :: IsStream t => AsyncT m a -> t m a
405+fromAsync = adapt
406+
407+instance IsStream AsyncT where
408+ toStream = getAsyncT
409+ fromStream = AsyncT
410+
411+ {-# INLINE consM #-}
412+ {-# SPECIALIZE consM :: IO a -> AsyncT IO a -> AsyncT IO a #-}
413+ consM = Async.consMAsync
414+
415+ {-# INLINE (|:) #-}
416+ {-# SPECIALIZE (|:) :: IO a -> AsyncT IO a -> AsyncT IO a #-}
417+ (|:) = Async.consMAsync
418+
419+-- | Fix the type of a polymorphic stream as 'WAsyncT'.
420+--
421+-- /Since: 0.2.0 ("Streamly")/
422+--
423+-- @since 0.8.0
424+fromWAsync :: IsStream t => WAsyncT m a -> t m a
425+fromWAsync = adapt
426+
427+instance IsStream WAsyncT where
428+ toStream = getWAsyncT
429+ fromStream = WAsyncT
430+
431+ {-# INLINE consM #-}
432+ {-# SPECIALIZE consM :: IO a -> WAsyncT IO a -> WAsyncT IO a #-}
433+ consM = Async.consMWAsync
434+
435+ {-# INLINE (|:) #-}
436+ {-# SPECIALIZE (|:) :: IO a -> WAsyncT IO a -> WAsyncT IO a #-}
437+ (|:) = Async.consMWAsync
438+
439+-------------------------------------------------------------------------------
440+-- Ahead
441+-------------------------------------------------------------------------------
442+
443+-- | Fix the type of a polymorphic stream as 'AheadT'.
444+--
445+-- /Since: 0.3.0 ("Streamly")/
446+--
447+-- @since 0.8.0
448+fromAhead :: IsStream t => AheadT m a -> t m a
449+fromAhead = adapt
450+
451+instance IsStream AheadT where
452+ toStream = getAheadT
453+ fromStream = AheadT
454+
455+ {-# INLINE consM #-}
456+ {-# SPECIALIZE consM :: IO a -> AheadT IO a -> AheadT IO a #-}
457+ consM = Ahead.consM
458+
459+ {-# INLINE (|:) #-}
460+ {-# SPECIALIZE (|:) :: IO a -> AheadT IO a -> AheadT IO a #-}
461+ (|:) = Ahead.consM
462+
463+-------------------------------------------------------------------------------
464+-- Parallel
465+-------------------------------------------------------------------------------
466+
467+-- | Fix the type of a polymorphic stream as 'ParallelT'.
468+--
469+-- /Since: 0.1.0 ("Streamly")/
470+--
471+-- @since 0.8.0
472+fromParallel :: IsStream t => ParallelT m a -> t m a
473+fromParallel = adapt
474+
475+instance IsStream ParallelT where
476+ toStream = getParallelT
477+ fromStream = ParallelT
478+
479+ {-# INLINE consM #-}
480+ {-# SPECIALIZE consM :: IO a -> ParallelT IO a -> ParallelT IO a #-}
481+ consM = Parallel.consM
482+
483+ {-# INLINE (|:) #-}
484+ {-# SPECIALIZE (|:) :: IO a -> ParallelT IO a -> ParallelT IO a #-}
485+ (|:) = Parallel.consM
486+
487+-------------------------------------------------------------------------------
488+-- Zip
489+-------------------------------------------------------------------------------
490+
491+-- | Fix the type of a polymorphic stream as 'ZipSerialM'.
492+--
493+-- /Since: 0.2.0 ("Streamly")/
494+--
495+-- @since 0.8.0
496+fromZipSerial :: IsStream t => ZipSerialM m a -> t m a
497+fromZipSerial = adapt
498+
499+-- | Same as 'fromZipSerial'.
500+--
501+-- @since 0.1.0
502+{-# DEPRECATED zipping "Please use fromZipSerial instead." #-}
503+zipping :: IsStream t => ZipSerialM m a -> t m a
504+zipping = fromZipSerial
505+
506+instance IsStream ZipSerialM where
507+ toStream = getZipSerialM
508+ fromStream = ZipSerialM
509+
510+ {-# INLINE consM #-}
511+ {-# SPECIALIZE consM :: IO a -> ZipSerialM IO a -> ZipSerialM IO a #-}
512+ consM :: Monad m => m a -> ZipSerialM m a -> ZipSerialM m a
513+ consM = Zip.consMZip
514+
515+ {-# INLINE (|:) #-}
516+ {-# SPECIALIZE (|:) :: IO a -> ZipSerialM IO a -> ZipSerialM IO a #-}
517+ (|:) :: Monad m => m a -> ZipSerialM m a -> ZipSerialM m a
518+ (|:) = Zip.consMZip
519+
520+-- | Fix the type of a polymorphic stream as 'ZipAsyncM'.
521+--
522+-- /Since: 0.2.0 ("Streamly")/
523+--
524+-- @since 0.8.0
525+fromZipAsync :: IsStream t => ZipAsyncM m a -> t m a
526+fromZipAsync = adapt
527+
528+-- | Same as 'fromZipAsync'.
529+--
530+-- @since 0.1.0
531+{-# DEPRECATED zippingAsync "Please use fromZipAsync instead." #-}
532+zippingAsync :: IsStream t => ZipAsyncM m a -> t m a
533+zippingAsync = fromZipAsync
534+
535+instance IsStream ZipAsyncM where
536+ toStream = getZipAsyncM
537+ fromStream = ZipAsyncM
538+
539+ {-# INLINE consM #-}
540+ {-# SPECIALIZE consM :: IO a -> ZipAsyncM IO a -> ZipAsyncM IO a #-}
541+ consM :: Monad m => m a -> ZipAsyncM m a -> ZipAsyncM m a
542+ consM = Zip.consMZipAsync
543+
544+ {-# INLINE (|:) #-}
545+ {-# SPECIALIZE (|:) :: IO a -> ZipAsyncM IO a -> ZipAsyncM IO a #-}
546+ (|:) :: Monad m => m a -> ZipAsyncM m a -> ZipAsyncM m a
547+ (|:) = Zip.consMZipAsync
548+
549+-------------------------------------------------------------------------------
550+-- Construction
551+-------------------------------------------------------------------------------
552+
553+infixr 5 `cons`
554+
555+-- | Construct a stream by adding a pure value at the head of an existing
556+-- stream. For serial streams this is the same as @(return a) \`consM` r@ but
557+-- more efficient. For concurrent streams this is not concurrent whereas
558+-- 'consM' is concurrent. For example:
559+--
560+-- @
561+-- > toList $ 1 \`cons` 2 \`cons` 3 \`cons` nil
562+-- [1,2,3]
563+-- @
564+--
565+-- @since 0.1.0
566+{-# INLINE_NORMAL cons #-}
567+cons :: IsStream t => a -> t m a -> t m a
568+cons a r = fromStream $ K.cons a (toStream r)
569+
570+infixr 5 .:
571+
572+-- | Operator equivalent of 'cons'.
573+--
574+-- @
575+-- > toList $ 1 .: 2 .: 3 .: nil
576+-- [1,2,3]
577+-- @
578+--
579+-- @since 0.1.1
580+{-# INLINE (.:) #-}
581+(.:) :: IsStream t => a -> t m a -> t m a
582+(.:) = cons
583+
584+{-# INLINE_NORMAL nil #-}
585+nil :: IsStream t => t m a
586+nil = fromStream K.nil
587+
588+{-# INLINE_NORMAL nilM #-}
589+nilM :: (IsStream t, Monad m) => m b -> t m a
590+nilM = fromStream . K.nilM
591+
592+{-# INLINE_NORMAL fromPure #-}
593+fromPure :: IsStream t => a -> t m a
594+fromPure = fromStream . K.fromPure
595+
596+{-# INLINE_NORMAL fromEffect #-}
597+fromEffect :: (Monad m, IsStream t) => m a -> t m a
598+fromEffect = fromStream . K.fromEffect
599+
600+{-# INLINE repeat #-}
601+repeat :: IsStream t => a -> t m a
602+repeat = fromStream . K.repeat
603+
604+-------------------------------------------------------------------------------
605+-- Bind/Concat
606+-------------------------------------------------------------------------------
607+
608+{-# INLINE bindWith #-}
609+bindWith
610+ :: IsStream t
611+ => (t m b -> t m b -> t m b)
612+ -> t m a
613+ -> (a -> t m b)
614+ -> t m b
615+bindWith par m1 f =
616+ fromStream
617+ $ K.bindWith
618+ (\s1 s2 -> toStream $ par (fromStream s1) (fromStream s2))
619+ (toStream m1)
620+ (toStream . f)
621+
622+-- | @concatMapWith mixer generator stream@ is a two dimensional looping
623+-- combinator. The @generator@ function is used to generate streams from the
624+-- elements in the input @stream@ and the @mixer@ function is used to merge
625+-- those streams.
626+--
627+-- Note we can merge streams concurrently by using a concurrent merge function.
628+--
629+-- /Since: 0.7.0/
630+--
631+-- /Since: 0.8.0 (signature change)/
632+{-# INLINE concatMapWith #-}
633+concatMapWith
634+ :: IsStream t
635+ => (t m b -> t m b -> t m b)
636+ -> (a -> t m b)
637+ -> t m a
638+ -> t m b
639+concatMapWith par f xs = bindWith par xs f
640+
641+-- | A variant of 'foldMap' that allows you to map a monadic streaming action
642+-- on a 'Foldable' container and then fold it using the specified stream merge
643+-- operation.
644+--
645+-- @concatMapFoldableWith 'async' return [1..3]@
646+--
647+-- Equivalent to:
648+--
649+-- @
650+-- concatMapFoldableWith f g = Prelude.foldr (f . g) S.nil
651+-- concatMapFoldableWith f g xs = S.concatMapWith f g (S.fromFoldable xs)
652+-- @
653+--
654+-- /Since: 0.8.0 (Renamed foldMapWith to concatMapFoldableWith)/
655+--
656+-- /Since: 0.1.0 ("Streamly")/
657+{-# INLINABLE concatMapFoldableWith #-}
658+concatMapFoldableWith :: (IsStream t, Foldable f)
659+ => (t m b -> t m b -> t m b) -> (a -> t m b) -> f a -> t m b
660+concatMapFoldableWith f g = Prelude.foldr (f . g) nil
661+
662+-- | Like 'concatMapFoldableWith' but with the last two arguments reversed i.e. the
663+-- monadic streaming function is the last argument.
664+--
665+-- Equivalent to:
666+--
667+-- @
668+-- concatForFoldableWith f xs g = Prelude.foldr (f . g) S.nil xs
669+-- concatForFoldableWith f = flip (S.concatMapFoldableWith f)
670+-- @
671+--
672+-- /Since: 0.8.0 (Renamed forEachWith to concatForFoldableWith)/
673+--
674+-- /Since: 0.1.0 ("Streamly")/
675+{-# INLINE concatForFoldableWith #-}
676+concatForFoldableWith :: (IsStream t, Foldable f)
677+ => (t m b -> t m b -> t m b) -> f a -> (a -> t m b) -> t m b
678+concatForFoldableWith f = flip (concatMapFoldableWith f)
679+
680+-- | A variant of 'Data.Foldable.fold' that allows you to fold a 'Foldable'
681+-- container of streams using the specified stream sum operation.
682+--
683+-- @concatFoldableWith 'async' $ map return [1..3]@
684+--
685+-- Equivalent to:
686+--
687+-- @
688+-- concatFoldableWith f = Prelude.foldr f S.nil
689+-- concatFoldableWith f = S.concatMapFoldableWith f id
690+-- @
691+--
692+-- /Since: 0.8.0 (Renamed foldWith to concatFoldableWith)/
693+--
694+-- /Since: 0.1.0 ("Streamly")/
695+{-# INLINE concatFoldableWith #-}
696+concatFoldableWith :: (IsStream t, Foldable f)
697+ => (t m a -> t m a -> t m a) -> f (t m a) -> t m a
698+concatFoldableWith f = concatMapFoldableWith f id
src/Streamly/Internal/Data/Stream/IsStream/Types.hsdeleted−74
@@ -1,74 +0,0 @@
1−-- |
2−-- Module : Streamly.Internal.Data.Stream.IsStream
3−-- Copyright : (c) 2017 Composewell Technologies
4−-- License : BSD-3-Clause
5−-- Maintainer : streamly@composewell.com
6−-- Stability : experimental
7−-- Portability : GHC
8−--
9−-- | This module contains different stream types and combinators to
10−-- interconvert between them.
11−
12−module Streamly.Internal.Data.Stream.IsStream.Types
13− (
14− -- * Stream Types
15− -- ** Serial Streams
16− SerialT
17− , Serial
18− , WSerialT
19− , WSerial
20−
21− -- ** Speculative Streams
22− , AheadT
23− , Ahead
24−
25− -- ** Asynchronous Streams
26− , AsyncT
27− , Async
28− , WAsyncT
29− , WAsync
30−
31− -- ** Parallel Streams
32− -- | Ahead, Async and WAsync schedule actions concurrently on demand.
33− -- Unlike those 'Parallel' streams schedule all actions concurrently
34− -- upfront.
35− , ParallelT
36− , Parallel
37− , mkAsync
38−
39− -- ** Zipping Streams
40− , ZipSerialM
41− , ZipSerial
42− , ZipAsyncM
43− , ZipAsync
44−
45− -- * Stream Type Adapters
46− , IsStream ()
47−
48− , fromSerial
49− , fromWSerial
50− , fromAsync
51− , fromAhead
52− , fromWAsync
53− , fromParallel
54− , fromZipSerial
55− , fromZipAsync
56− , adapt
57−
58− -- * Type Synonyms
59− , MonadAsync
60− )
61−where
62−
63−import Streamly.Internal.Data.Stream.Ahead (AheadT, Ahead, fromAhead)
64−import Streamly.Internal.Data.Stream.Async
65− ( AsyncT, Async, WAsyncT, WAsync, mkAsync, fromAsync
66− , fromWAsync)
67−import Streamly.Internal.Data.Stream.Parallel (ParallelT, Parallel, fromParallel)
68−import Streamly.Internal.Data.Stream.Serial
69− ( SerialT, WSerialT, Serial, WSerial, fromSerial
70− , fromWSerial)
71−import Streamly.Internal.Data.Stream.StreamK (IsStream(), adapt)
72−import Streamly.Internal.Data.Stream.Zip
73− (ZipSerialM, ZipSerial, ZipAsyncM, ZipAsync, fromZipSerial, fromZipAsync)
74−import Streamly.Internal.Control.Concurrent (MonadAsync)
src/Streamly/Internal/Data/Stream/Parallel.hs+70−161
@@ -1,7 +1,5 @@
1{-# LANGUAGE UndecidableInstances #-}
1{-# LANGUAGE UndecidableInstances #-}
2
2
3−#include "inline.hs"
4−
5-- |
3-- |
6-- Module : Streamly.Internal.Data.Stream.Parallel
4-- Module : Streamly.Internal.Data.Stream.Parallel
7-- Copyright : (c) 2017 Composewell Technologies
5-- Copyright : (c) 2017 Composewell Technologies
@@ -25,24 +23,22 @@
25module Streamly.Internal.Data.Stream.Parallel
23module Streamly.Internal.Data.Stream.Parallel
26 (
24 (
27 -- * Parallel Stream Type
25 -- * Parallel Stream Type
28− ParallelT
26+ ParallelT(..)
29 , Parallel
27 , Parallel
30− , fromParallel
28+ , consM
31
29
32 -- * Merge Concurrently
30 -- * Merge Concurrently
33− , parallel
31+ , parallelK
34− , parallelFst
32+ , parallelFstK
35− , parallelMin
33+ , parallelMinK
36
34
37 -- * Evaluate Concurrently
35 -- * Evaluate Concurrently
38− , mkParallel
39 , mkParallelD
36 , mkParallelD
40 , mkParallelK
37 , mkParallelK
41
38
42 -- * Tap Concurrently
39 -- * Tap Concurrently
43− , tapAsync
40+ , tapAsyncK
44 , tapAsyncF
41 , tapAsyncF
45− , distributeAsync_
46
42
47 -- * Callbacks
43 -- * Callbacks
48 , newCallbackStream
44 , newCallbackStream
@@ -70,11 +66,10 @@ import qualified Data.Set as Set
70
66
71import Streamly.Internal.Control.Concurrent (MonadAsync)
67import Streamly.Internal.Control.Concurrent (MonadAsync)
72import Streamly.Internal.Data.Fold.Type (Fold)
68import Streamly.Internal.Data.Fold.Type (Fold)
69+import Streamly.Internal.Data.Stream.Serial (SerialT(..))
73import Streamly.Internal.Data.Stream.StreamD.Type (Step(..))
70import Streamly.Internal.Data.Stream.StreamD.Type (Step(..))
74−import Streamly.Internal.Data.Stream.StreamK
71+import Streamly.Internal.Data.Stream.StreamK.Type (Stream)
75− (IsStream(..), Stream, mkStream, foldStream, foldStreamShared, adapt)
76
72
77−import qualified Streamly.Internal.Data.Stream.StreamK as K (withLocal)
78import qualified Streamly.Internal.Data.Stream.StreamK.Type as K
73import qualified Streamly.Internal.Data.Stream.StreamK.Type as K
79import qualified Streamly.Internal.Data.Stream.StreamD.Type as D
74import qualified Streamly.Internal.Data.Stream.StreamD.Type as D
80import qualified Streamly.Internal.Data.Stream.SVar.Generate as SVar
75import qualified Streamly.Internal.Data.Stream.SVar.Generate as SVar
@@ -82,6 +77,7 @@ import qualified Streamly.Internal.Data.Stream.SVar.Eliminate as SVar
82
77
83import Streamly.Internal.Data.SVar
78import Streamly.Internal.Data.SVar
84
79
80+#include "inline.hs"
85#include "Instances.hs"
81#include "Instances.hs"
86
82
87--
83--
@@ -116,7 +112,7 @@ runOne st m0 winfo =
116
112
117 go m = do
113 go m = do
118 liftIO $ decrementBufferLimit sv
114 liftIO $ decrementBufferLimit sv
119− foldStreamShared st yieldk single stop m
115+ K.foldStreamShared st yieldk single stop m
120
116
121 sv = fromJust $ streamVar st
117 sv = fromJust $ streamVar st
122
118
@@ -139,7 +135,7 @@ runOneLimited st m0 winfo = go m0
139 if yieldLimitOk
135 if yieldLimitOk
140 then do
136 then do
141 liftIO $ decrementBufferLimit sv
137 liftIO $ decrementBufferLimit sv
142− foldStreamShared st yieldk single stop m
138+ K.foldStreamShared st yieldk single stop m
143 else do
139 else do
144 liftIO $ cleanupSVarFromWorker sv
140 liftIO $ cleanupSVarFromWorker sv
145 liftIO $ sendStop sv winfo
141 liftIO $ sendStop sv winfo
@@ -165,23 +161,23 @@ runOneLimited st m0 winfo = go m0
165-- remember the past state.
161-- remember the past state.
166
162
167{-# NOINLINE forkSVarPar #-}
163{-# NOINLINE forkSVarPar #-}
168−forkSVarPar :: (IsStream t, MonadAsync m)
164+forkSVarPar :: MonadAsync m
169− => SVarStopStyle -> t m a -> t m a -> t m a
165+ => SVarStopStyle -> Stream m a -> Stream m a -> Stream m a
170−forkSVarPar ss m r = mkStream $ \st yld sng stp -> do
166+forkSVarPar ss m r = K.mkStream $ \st yld sng stp -> do
171 sv <- newParallelVar ss st
167 sv <- newParallelVar ss st
172− pushWorkerPar sv (runOne st{streamVar = Just sv} $ toStream m)
168+ pushWorkerPar sv (runOne st{streamVar = Just sv} m)
173 case ss of
169 case ss of
174 StopBy -> liftIO $ do
170 StopBy -> liftIO $ do
175 set <- readIORef (workerThreads sv)
171 set <- readIORef (workerThreads sv)
176 writeIORef (svarStopBy sv) $ Set.elemAt 0 set
172 writeIORef (svarStopBy sv) $ Set.elemAt 0 set
177 _ -> return ()
173 _ -> return ()
178− pushWorkerPar sv (runOne st{streamVar = Just sv} $ toStream r)
174+ pushWorkerPar sv (runOne st{streamVar = Just sv} r)
179− foldStream st yld sng stp (SVar.fromSVar sv)
175+ K.foldStream st yld sng stp $ getSerialT (SVar.fromSVar sv)
180
176
181{-# INLINE joinStreamVarPar #-}
177{-# INLINE joinStreamVarPar #-}
182−joinStreamVarPar :: (IsStream t, MonadAsync m)
178+joinStreamVarPar :: MonadAsync m
183− => SVarStyle -> SVarStopStyle -> t m a -> t m a -> t m a
179+ => SVarStyle -> SVarStopStyle -> Stream m a -> Stream m a -> Stream m a
184−joinStreamVarPar style ss m1 m2 = mkStream $ \st yld sng stp ->
180+joinStreamVarPar style ss m1 m2 = K.mkStream $ \st yld sng stp ->
185 case streamVar st of
181 case streamVar st of
186 Just sv | svarStyle sv == style && svarStopStyle sv == ss -> do
182 Just sv | svarStyle sv == style && svarStopStyle sv == ss -> do
187 -- Here, WE ARE IN THE WORKER/PRODUCER THREAD, we know that because
183 -- Here, WE ARE IN THE WORKER/PRODUCER THREAD, we know that because
@@ -217,56 +213,28 @@ joinStreamVarPar style ss m1 m2 = mkStream $ \st yld sng stp ->
217 -- worker spawned by that worker would fork, thus creating layer
213 -- worker spawned by that worker would fork, thus creating layer
218 -- over layer of workers and a chain of threads leading to a very
214 -- over layer of workers and a chain of threads leading to a very
219 -- inefficient execution.
215 -- inefficient execution.
220− pushWorkerPar sv (runOne st $ toStream m1)
216+ pushWorkerPar sv (runOne st m1)
221− foldStreamShared st yld sng stp m2
217+ K.foldStreamShared st yld sng stp m2
222 _ ->
218 _ ->
223 -- Here WE ARE IN THE CONSUMER THREAD, we create a new SVar, fork
219 -- Here WE ARE IN THE CONSUMER THREAD, we create a new SVar, fork
224 -- worker threads to execute m1 and m2 and this thread starts
220 -- worker threads to execute m1 and m2 and this thread starts
225 -- pulling the stream from the SVar.
221 -- pulling the stream from the SVar.
226− foldStreamShared st yld sng stp (forkSVarPar ss m1 m2)
222+ K.foldStreamShared st yld sng stp (forkSVarPar ss m1 m2)
227
223
228-------------------------------------------------------------------------------
224-------------------------------------------------------------------------------
229-- User facing APIs
225-- User facing APIs
230-------------------------------------------------------------------------------
226-------------------------------------------------------------------------------
231
227
228+{-# INLINE parallelK #-}
229+parallelK :: MonadAsync m => Stream m a -> Stream m a -> Stream m a
230+parallelK = joinStreamVarPar ParallelVar StopNone
231+
232-- | XXX we can implement it more efficienty by directly implementing instead
232-- | XXX we can implement it more efficienty by directly implementing instead
233-- of combining streams using parallel.
233-- of combining streams using parallel.
234−{-# INLINE consMParallel #-}
234+{-# INLINE consM #-}
235−{-# SPECIALIZE consMParallel :: IO a -> ParallelT IO a -> ParallelT IO a #-}
235+{-# SPECIALIZE consM :: IO a -> ParallelT IO a -> ParallelT IO a #-}
236−consMParallel :: MonadAsync m => m a -> ParallelT m a -> ParallelT m a
236+consM :: MonadAsync m => m a -> ParallelT m a -> ParallelT m a
237−consMParallel m r = fromStream $ K.fromEffect m `parallel` toStream r
237+consM m (ParallelT r) = ParallelT $ parallelK (K.fromEffect m) r
238−
239−infixr 6 `parallel`
240−
241−-- | Like 'Streamly.Prelude.async' except that the execution is much more
242−-- strict. There is no limit on the number of threads. While
243−-- 'Streamly.Prelude.async' may not schedule a stream if there is no demand
244−-- from the consumer, 'parallel' always evaluates both the streams immediately.
245−-- The only limit that applies to 'parallel' is 'Streamly.Prelude.maxBuffer'.
246−-- Evaluation may block if the output buffer becomes full.
247−--
248−-- >>> import Streamly.Prelude (parallel)
249−-- >>> stream = Stream.fromEffect (delay 2) `parallel` Stream.fromEffect (delay 1)
250−-- >>> Stream.toList stream -- IO [Int]
251−-- 1 sec
252−-- 2 sec
253−-- [1,2]
254−--
255−-- 'parallel' guarantees that all the streams are scheduled for execution
256−-- immediately, therefore, we could use things like starting timers inside the
257−-- streams and relying on the fact that all timers were started at the same
258−-- time.
259−--
260−-- Unlike 'async' this operation cannot be used to fold an infinite lazy
261−-- container of streams, because it schedules all the streams strictly
262−-- concurrently.
263−--
264−-- /Since: 0.2.0 ("Streamly")/
265−--
266−-- @since 0.8.0
267−{-# INLINE parallel #-}
268−parallel :: (IsStream t, MonadAsync m) => t m a -> t m a -> t m a
269−parallel = joinStreamVarPar ParallelVar StopNone
270
238
271-- This is a co-parallel like combinator for streams, where first stream is the
239-- This is a co-parallel like combinator for streams, where first stream is the
272-- main stream and the rest are just supporting it, when the first ends
240-- main stream and the rest are just supporting it, when the first ends
@@ -275,9 +243,9 @@ parallel = joinStreamVarPar ParallelVar StopNone
275-- | Like `parallel` but stops the output as soon as the first stream stops.
243-- | Like `parallel` but stops the output as soon as the first stream stops.
276--
244--
277-- /Pre-release/
245-- /Pre-release/
278−{-# INLINE parallelFst #-}
246+{-# INLINE parallelFstK #-}
279−parallelFst :: (IsStream t, MonadAsync m) => t m a -> t m a -> t m a
247+parallelFstK :: MonadAsync m => Stream m a -> Stream m a -> Stream m a
280−parallelFst = joinStreamVarPar ParallelVar StopBy
248+parallelFstK = joinStreamVarPar ParallelVar StopBy
281
249
282-- This is a race like combinator for streams.
250-- This is a race like combinator for streams.
283--
251--
@@ -285,9 +253,9 @@ parallelFst = joinStreamVarPar ParallelVar StopBy
285-- stops.
253-- stops.
286--
254--
287-- /Pre-release/
255-- /Pre-release/
288−{-# INLINE parallelMin #-}
256+{-# INLINE parallelMinK #-}
289−parallelMin :: (IsStream t, MonadAsync m) => t m a -> t m a -> t m a
257+parallelMinK :: MonadAsync m => Stream m a -> Stream m a -> Stream m a
290−parallelMin = joinStreamVarPar ParallelVar StopAny
258+parallelMinK = joinStreamVarPar ParallelVar StopAny
291
259
292------------------------------------------------------------------------------
260------------------------------------------------------------------------------
293-- Convert a stream to parallel
261-- Convert a stream to parallel
@@ -297,16 +265,12 @@ parallelMin = joinStreamVarPar ParallelVar StopAny
297--
265--
298-- /Pre-release/
266-- /Pre-release/
299--
267--
300−mkParallelK :: (IsStream t, MonadAsync m) => t m a -> t m a
268+mkParallelK :: MonadAsync m => Stream m a -> Stream m a
301−mkParallelK m = mkStream $ \st yld sng stp -> do
269+mkParallelK m = K.mkStream $ \st yld sng stp -> do
302 sv <- newParallelVar StopNone (adaptState st)
270 sv <- newParallelVar StopNone (adaptState st)
303 -- pushWorkerPar sv (runOne st{streamVar = Just sv} $ toStream m)
271 -- pushWorkerPar sv (runOne st{streamVar = Just sv} $ toStream m)
304− SVar.toSVarParallel st sv $ D.toStreamD m
272+ SVar.toSVarParallel st sv $ D.fromStreamK m
305− foldStream st yld sng stp $ SVar.fromSVar sv
273+ K.foldStream st yld sng stp $ getSerialT $ SVar.fromSVar sv
306−
307−-------------------------------------------------------------------------------
308−-- Concurrent application and fold
309−-------------------------------------------------------------------------------
310
274
311-- | Same as 'mkParallel' but for StreamD stream.
275-- | Same as 'mkParallel' but for StreamD stream.
312--
276--
@@ -328,25 +292,6 @@ mkParallelD m = D.Stream step Nothing
328 Skip s -> Skip (Just $ D.Stream step1 s)
292 Skip s -> Skip (Just $ D.Stream step1 s)
329 Stop -> Stop
293 Stop -> Stop
330
294
331−-- Compare with mkAsync. mkAsync uses an Async style SVar whereas this uses a
332−-- parallel style SVar for evaluation. Currently, parallel style cannot use
333−-- rate control whereas Async style can use rate control. In async style SVar
334−-- the worker thread terminates when the buffer is full whereas in Parallel
335−-- style it blocks.
336−--
337−-- | Make the stream producer and consumer run concurrently by introducing a
338−-- buffer between them. The producer thread evaluates the input stream until
339−-- the buffer fills, it blocks if the buffer is full until there is space in
340−-- the buffer. The consumer consumes the stream lazily from the buffer.
341−--
342−-- @mkParallel = D.fromStreamD . mkParallelD . D.toStreamD@
343−--
344−-- /Pre-release/
345−--
346−{-# INLINE_NORMAL mkParallel #-}
347−mkParallel :: (K.IsStream t, MonadAsync m) => t m a -> t m a
348−mkParallel = D.fromStreamD . mkParallelD . D.toStreamD
349−
350-------------------------------------------------------------------------------
295-------------------------------------------------------------------------------
351-- Concurrent tap
296-- Concurrent tap
352-------------------------------------------------------------------------------
297-------------------------------------------------------------------------------
@@ -392,11 +337,12 @@ mkParallel = D.fromStreamD . mkParallelD . D.toStreamD
392-- Compare with 'tap'.
337-- Compare with 'tap'.
393--
338--
394-- /Pre-release/
339-- /Pre-release/
395−{-# INLINE tapAsync #-}
340+{-# INLINE tapAsyncK #-}
396−tapAsync :: (IsStream t, MonadAsync m) => (t m a -> m b) -> t m a -> t m a
341+tapAsyncK :: MonadAsync m => (Stream m a -> m b) -> Stream m a -> Stream m a
397−tapAsync f m = mkStream $ \st yld sng stp -> do
342+tapAsyncK f m = K.mkStream $ \st yld sng stp -> do
398− sv <- SVar.newFoldSVar st f
343+ sv <- SVar.newFoldSVar st (f . getSerialT)
399− foldStreamShared st yld sng stp (SVar.teeToSVar sv m)
344+ K.foldStreamShared st yld sng stp
345+ $ getSerialT (SVar.teeToSVar sv $ SerialT m)
400
346
401data TapState fs st a = TapInit | Tapping !fs st | TapDone st
347data TapState fs st a = TapInit | Tapping !fs st | TapDone st
402
348
@@ -450,29 +396,6 @@ tapAsyncF f (D.Stream step1 state1) = D.Stream step TapInit
450 Skip s -> Skip (TapDone s)
396 Skip s -> Skip (TapDone s)
451 Stop -> Stop
397 Stop -> Stop
452
398
453−-- | Concurrently distribute a stream to a collection of fold functions,
454−-- discarding the outputs of the folds.
455−--
456−-- @
457−-- > Stream.drain $ Stream.distributeAsync_ [Stream.mapM_ print, Stream.mapM_ print] (Stream.enumerateFromTo 1 2)
458−-- 1
459−-- 2
460−-- 1
461−-- 2
462−--
463−-- @
464−--
465−-- @
466−-- distributeAsync_ = flip (foldr tapAsync)
467−-- @
468−--
469−-- /Pre-release/
470−--
471−{-# INLINE distributeAsync_ #-}
472−distributeAsync_ :: (Foldable f, IsStream t, MonadAsync m)
473− => f (t m a -> m b) -> t m a -> t m a
474−distributeAsync_ = flip (foldr tapAsync)
475−
476------------------------------------------------------------------------------
399------------------------------------------------------------------------------
477-- ParallelT
400-- ParallelT
478------------------------------------------------------------------------------
401------------------------------------------------------------------------------
@@ -504,44 +427,24 @@ newtype ParallelT m a = ParallelT {getParallelT :: Stream m a}
504-- @since 0.8.0
427-- @since 0.8.0
505type Parallel = ParallelT IO
428type Parallel = ParallelT IO
506
429
507−-- | Fix the type of a polymorphic stream as 'ParallelT'.
508−--
509−-- /Since: 0.1.0 ("Streamly")/
510−--
511−-- @since 0.8.0
512−fromParallel :: IsStream t => ParallelT m a -> t m a
513−fromParallel = adapt
514−
515−instance IsStream ParallelT where
516− toStream = getParallelT
517− fromStream = ParallelT
518−
519− {-# INLINE consM #-}
520− {-# SPECIALIZE consM :: IO a -> ParallelT IO a -> ParallelT IO a #-}
521− consM = consMParallel
522−
523− {-# INLINE (|:) #-}
524− {-# SPECIALIZE (|:) :: IO a -> ParallelT IO a -> ParallelT IO a #-}
525− (|:) = consM
526−
527------------------------------------------------------------------------------
430------------------------------------------------------------------------------
528-- Semigroup
431-- Semigroup
529------------------------------------------------------------------------------
432------------------------------------------------------------------------------
530
433
531−{-# INLINE mappendParallel #-}
434+{-# INLINE append #-}
532−{-# SPECIALIZE mappendParallel :: ParallelT IO a -> ParallelT IO a -> ParallelT IO a #-}
435+{-# SPECIALIZE append :: ParallelT IO a -> ParallelT IO a -> ParallelT IO a #-}
533−mappendParallel :: MonadAsync m => ParallelT m a -> ParallelT m a -> ParallelT m a
436+append :: MonadAsync m => ParallelT m a -> ParallelT m a -> ParallelT m a
534−mappendParallel m1 m2 = fromStream $ parallel (toStream m1) (toStream m2)
437+append (ParallelT m1) (ParallelT m2) = ParallelT $ parallelK m1 m2
535
438
536instance MonadAsync m => Semigroup (ParallelT m a) where
439instance MonadAsync m => Semigroup (ParallelT m a) where
537− (<>) = mappendParallel
440+ (<>) = append
538
441
539------------------------------------------------------------------------------
442------------------------------------------------------------------------------
540-- Monoid
443-- Monoid
541------------------------------------------------------------------------------
444------------------------------------------------------------------------------
542
445
543instance MonadAsync m => Monoid (ParallelT m a) where
446instance MonadAsync m => Monoid (ParallelT m a) where
544− mempty = K.nil
447+ mempty = ParallelT K.nil
545 mappend = (<>)
448 mappend = (<>)
546
449
547------------------------------------------------------------------------------
450------------------------------------------------------------------------------
@@ -549,15 +452,18 @@ instance MonadAsync m => Monoid (ParallelT m a) where
549------------------------------------------------------------------------------
452------------------------------------------------------------------------------
550
453
551{-# INLINE apParallel #-}
454{-# INLINE apParallel #-}
455+{-# SPECIALIZE apParallel ::
552−{-# SPECIALIZE apParallel :: ParallelT IO (a -> b) -> ParallelT IO a -> ParallelT IO b #-}
456+ ParallelT IO (a -> b) -> ParallelT IO a -> ParallelT IO b #-}
457+apParallel :: MonadAsync m =>
553−apParallel :: MonadAsync m => ParallelT m (a -> b) -> ParallelT m a -> ParallelT m b
458+ ParallelT m (a -> b) -> ParallelT m a -> ParallelT m b
554apParallel (ParallelT m1) (ParallelT m2) =
459apParallel (ParallelT m1) (ParallelT m2) =
555− let f x1 = K.concatMapBy parallel (pure . x1) m2
460+ let f x1 = K.concatMapWith parallelK (pure . x1) m2
556− in ParallelT $ K.concatMapBy parallel f m1
461+ in ParallelT $ K.concatMapWith parallelK f m1
557
462
558instance (Monad m, MonadAsync m) => Applicative (ParallelT m) where
463instance (Monad m, MonadAsync m) => Applicative (ParallelT m) where
559 {-# INLINE pure #-}
464 {-# INLINE pure #-}
560 pure = ParallelT . K.fromPure
465 pure = ParallelT . K.fromPure
466+
561 {-# INLINE (<*>) #-}
467 {-# INLINE (<*>) #-}
562 (<*>) = apParallel
468 (<*>) = apParallel
563
469
@@ -565,14 +471,17 @@ instance (Monad m, MonadAsync m) => Applicative (ParallelT m) where
565-- Monad
471-- Monad
566------------------------------------------------------------------------------
472------------------------------------------------------------------------------
567
473
568−{-# INLINE bindParallel #-}
474+{-# INLINE bind #-}
475+{-# SPECIALIZE bind ::
569−{-# SPECIALIZE bindParallel :: ParallelT IO a -> (a -> ParallelT IO b) -> ParallelT IO b #-}
476+ ParallelT IO a -> (a -> ParallelT IO b) -> ParallelT IO b #-}
570−bindParallel :: MonadAsync m => ParallelT m a -> (a -> ParallelT m b) -> ParallelT m b
477+bind :: MonadAsync m => ParallelT m a -> (a -> ParallelT m b) -> ParallelT m b
571−bindParallel m f = fromStream $ K.bindWith parallel (K.adapt m) (K.adapt . f)
478+bind (ParallelT m) f = ParallelT $ K.bindWith parallelK m (getParallelT . f)
572
479
573instance MonadAsync m => Monad (ParallelT m) where
480instance MonadAsync m => Monad (ParallelT m) where
574 return = pure
481 return = pure
575− (>>=) = bindParallel
482+
483+ {-# INLINE (>>=) #-}
484+ (>>=) = bind
576
485
577------------------------------------------------------------------------------
486------------------------------------------------------------------------------
578-- Other instances
487-- Other instances
@@ -594,7 +503,7 @@ MONAD_COMMON_INSTANCES(ParallelT, MONADPARALLEL)
594-- /Pre-release/
503-- /Pre-release/
595--
504--
596{-# INLINE_NORMAL newCallbackStream #-}
505{-# INLINE_NORMAL newCallbackStream #-}
597−newCallbackStream :: (K.IsStream t, MonadAsync m) => m (a -> m (), t m a)
506+newCallbackStream :: MonadAsync m => m (a -> m (), Stream m a)
598newCallbackStream = do
507newCallbackStream = do
599 sv <- newParallelVar StopNone defState
508 sv <- newParallelVar StopNone defState
600
509
@@ -606,4 +515,4 @@ newCallbackStream = do
606 let callback a = liftIO $ void $ send sv (ChildYield a)
515 let callback a = liftIO $ void $ send sv (ChildYield a)
607 -- XXX we can return an SVar and then the consumer can unfold from the
516 -- XXX we can return an SVar and then the consumer can unfold from the
608 -- SVar?
517 -- SVar?
609− return (callback, D.fromStreamD (SVar.fromSVarD sv))
518+ return (callback, D.toStreamK (SVar.fromSVarD sv))
src/Streamly/Internal/Data/Stream/Prelude.hs+13−308
@@ -1,25 +1,22 @@
1+{-# LANGUAGE UndecidableInstances #-}
1{-# OPTIONS_GHC -Wno-orphans #-}
2{-# OPTIONS_GHC -Wno-orphans #-}
2
3
3−#include "inline.hs"
4−
5-- |
4-- |
6-- Module : Streamly.Internal.Data.Stream.Prelude
5-- Module : Streamly.Internal.Data.Stream.Prelude
7-- Copyright : (c) 2017 Composewell Technologies
6-- Copyright : (c) 2017 Composewell Technologies
8−--
9−-- License : BSD3
7+-- License : BSD-3-Clause
10-- Maintainer : streamly@composewell.com
8-- Maintainer : streamly@composewell.com
11-- Stability : experimental
9-- Stability : experimental
12-- Portability : GHC
10-- Portability : GHC
13--
11--
12+-- Low level functions using StreamK as the intermediate stream type. These
13+-- functions are used in SerialT/AsyncT/AheadT/ParallelT stream modules to
14+-- implement their instances..
14--
15--
15module Streamly.Internal.Data.Stream.Prelude
16module Streamly.Internal.Data.Stream.Prelude
16 (
17 (
17− -- * Stream Conversion
18− fromStreamS
19− , toStreamS
20−
21 -- * Running Effects
18 -- * Running Effects
22− , drain
19+ drain
23
20
24 -- * Conversion operations
21 -- * Conversion operations
25 , fromList
22 , fromList
@@ -35,318 +32,26 @@ module Streamly.Internal.Data.Stream.Prelude
35 , foldl'
32 , foldl'
36 , fold
33 , fold
37
34
38− -- Lazy left folds are useful only for reversing the stream
39− , foldlS
40− , foldlT
41−
42− , scanlx'
43− , scanlMx'
44− , postscanlx'
45− , postscanlMx'
46− , postscanOnce
47− , scanOnce
48−
49 -- * Zip style operations
35 -- * Zip style operations
50 , eqBy
36 , eqBy
51 , cmpBy
37 , cmpBy
52−
53− -- * Foldable instance
54− , minimum
55− , maximum
56−
57− -- * Nesting
58− , K.concatMapBy
59− , K.concatMap
60−
61− -- * Fold Utilities
62− , concatFoldableWith
63− , concatMapFoldableWith
64− , concatForFoldableWith
65 )
38 )
66where
39where
67
40
68−import Control.Monad.Trans.Class (MonadTrans(..))
41+#include "inline.hs"
69−import Prelude hiding (foldr, minimum, maximum)
70−import qualified Prelude
71
42
72import Streamly.Internal.Data.Fold.Type (Fold (..))
43import Streamly.Internal.Data.Fold.Type (Fold (..))
73
44
74#ifdef USE_STREAMK_ONLY
45#ifdef USE_STREAMK_ONLY
75import qualified Streamly.Internal.Data.Stream.StreamK as S
46import qualified Streamly.Internal.Data.Stream.StreamK as S
47+import qualified Streamly.Internal.Data.Stream.StreamK.Type as S
76#else
48#else
77−import qualified Streamly.Internal.Data.Stream.StreamD as S
49+import qualified Streamly.Internal.Data.Stream.StreamD.Type as S
78#endif
50#endif
79
51
80−import Streamly.Internal.Data.Stream.StreamK (IsStream(..))
81−import qualified Streamly.Internal.Data.Stream.StreamK as K
52+import qualified Streamly.Internal.Data.Stream.StreamK.Type as K
82−import qualified Streamly.Internal.Data.Stream.StreamD as D
53+import qualified Streamly.Internal.Data.Stream.StreamD.Type as D
83−
84−------------------------------------------------------------------------------
85−-- Conversion to and from direct style stream
86−------------------------------------------------------------------------------
87−
88−-- These definitions are dependent on what is imported as S
89−{-# INLINE fromStreamS #-}
90−fromStreamS :: (IsStream t, Monad m) => S.Stream m a -> t m a
91−fromStreamS = fromStream . S.toStreamK
92−
93−{-# INLINE toStreamS #-}
94−toStreamS :: (IsStream t, Monad m) => t m a -> S.Stream m a
95−toStreamS = S.fromStreamK . toStream
96−
97−------------------------------------------------------------------------------
98−-- Conversions
99−------------------------------------------------------------------------------
100−
101−{-# INLINE_EARLY drain #-}
102−drain :: (IsStream t, Monad m) => t m a -> m ()
103−drain m = D.drain $ D.fromStreamK (toStream m)
104−{-# RULES "drain fallback to CPS" [1]
105− forall a. D.drain (D.fromStreamK a) = K.drain a #-}
106−
107−------------------------------------------------------------------------------
108−-- Conversions
109−------------------------------------------------------------------------------
110−
111−-- |
112−-- @
113−-- fromList = 'Prelude.foldr' 'K.cons' 'K.nil'
114−-- @
115−--
116−-- Construct a stream from a list of pure values. This is more efficient than
117−-- 'K.fromFoldable' for serial streams.
118−--
119−-- @since 0.4.0
120−{-# INLINE_EARLY fromList #-}
121−fromList :: (Monad m, IsStream t) => [a] -> t m a
122−fromList = fromStreamS . S.fromList
123−{-# RULES "fromList fallback to StreamK" [1]
124− forall a. S.toStreamK (S.fromList a) = K.fromFoldable a #-}
125−
126−-- | Convert a stream into a list in the underlying monad.
127−--
128−-- @since 0.1.0
129−{-# INLINE toList #-}
130−toList :: (Monad m, IsStream t) => t m a -> m [a]
131−toList m = S.toList $ toStreamS m
132−
133−------------------------------------------------------------------------------
134−-- Folds
135−------------------------------------------------------------------------------
136−
137−{-# INLINE foldrM #-}
138−foldrM :: (Monad m, IsStream t) => (a -> m b -> m b) -> m b -> t m a -> m b
139−foldrM step acc m = S.foldrM step acc $ toStreamS m
140−
141−{-# INLINE foldrMx #-}
142−foldrMx :: (Monad m, IsStream t)
143− => (a -> m x -> m x) -> m x -> (m x -> m b) -> t m a -> m b
144−foldrMx step final project m = D.foldrMx step final project $ D.toStreamD m
145−
146−{-# INLINE foldr #-}
147−foldr :: (Monad m, IsStream t) => (a -> b -> b) -> b -> t m a -> m b
148−foldr f z = foldrM (\a b -> f a <$> b) (return z)
149−
150−-- | Like 'foldlx'', but with a monadic step function.
151−--
152−-- @since 0.7.0
153−{-# INLINE foldlMx' #-}
154−foldlMx' :: (IsStream t, Monad m)
155− => (x -> a -> m x) -> m x -> (x -> m b) -> t m a -> m b
156−foldlMx' step begin done m = S.foldlMx' step begin done $ toStreamS m
157−
158−-- | Strict left fold with an extraction function. Like the standard strict
159−-- left fold, but applies a user supplied extraction function (the third
160−-- argument) to the folded value at the end. This is designed to work with the
161−-- @foldl@ library. The suffix @x@ is a mnemonic for extraction.
162−--
163−-- @since 0.7.0
164−{-# INLINE foldlx' #-}
165−foldlx' :: (IsStream t, Monad m)
166− => (x -> a -> x) -> x -> (x -> b) -> t m a -> m b
167−foldlx' step begin done m = S.foldlx' step begin done $ toStreamS m
168−
169−-- | Strict left associative fold.
170−--
171−-- @since 0.2.0
172−{-# INLINE foldl' #-}
173−foldl' :: (Monad m, IsStream t) => (b -> a -> b) -> b -> t m a -> m b
174−foldl' step begin m = S.foldl' step begin $ toStreamS m
175−
176−{-# INLINE foldlS #-}
177−foldlS :: IsStream t => (t m b -> a -> t m b) -> t m b -> t m a -> t m b
178−foldlS = K.foldlS
179−
180−-- | Lazy left fold to a transformer monad.
181−--
182−-- For example, to reverse a stream:
183−--
184−-- > S.toList $ S.foldlT (flip S.cons) S.nil $ (S.fromList [1..5] :: SerialT IO Int)
185−--
186−{-# INLINE foldlT #-}
187−foldlT :: (Monad m, IsStream t, Monad (s m), MonadTrans s)
188− => (s m b -> a -> s m b) -> s m b -> t m a -> s m b
189−foldlT f z s = S.foldlT f z (toStreamS s)
190−
191−{-# INLINE fold #-}
192−fold :: (Monad m, IsStream t) => Fold m a b -> t m a -> m b
193−fold fld m = S.fold fld $ toStreamS m
194
54
195−------------------------------------------------------------------------------
55+import Prelude hiding (foldr, repeat)
196−-- Scans
197−------------------------------------------------------------------------------
198
56
199−-- postscanlM' followed by mapM
57+#include "PreludeCommon.hs"
200−{-# INLINE postscanlMx' #-}
201−postscanlMx' :: (IsStream t, Monad m)
202− => (x -> a -> m x) -> m x -> (x -> m b) -> t m a -> t m b
203−postscanlMx' step begin done m =
204− D.fromStreamD $ D.postscanlMx' step begin done $ D.toStreamD m
205−
206−-- postscanl' followed by map
207−{-# INLINE postscanlx' #-}
208−postscanlx' :: (IsStream t, Monad m)
209− => (x -> a -> x) -> x -> (x -> b) -> t m a -> t m b
210−postscanlx' step begin done m =
211− D.fromStreamD $ D.postscanlx' step begin done $ D.toStreamD m
212−
213−-- scanlM' followed by mapM
214−--
215−{-# INLINE scanlMx' #-}
216−scanlMx' :: (IsStream t, Monad m)
217− => (x -> a -> m x) -> m x -> (x -> m b) -> t m a -> t m b
218−scanlMx' step begin done m =
219− D.fromStreamD $ D.scanlMx' step begin done $ D.toStreamD m
220−
221−{-# INLINE_NORMAL postscanOnce #-}
222−postscanOnce :: (IsStream t, Monad m)
223− => Fold m a b -> t m a -> t m b
224−postscanOnce fld m =
225− D.fromStreamD $ D.postscanOnce fld $ D.toStreamD m
226−
227−{-# INLINE scanOnce #-}
228−scanOnce :: (IsStream t, Monad m)
229− => Fold m a b -> t m a -> t m b
230−scanOnce fld m = D.fromStreamD $ D.scanOnce fld $ D.toStreamD m
231−
232−-- scanl followed by map
233−--
234−-- | Strict left scan with an extraction function. Like 'scanl'', but applies a
235−-- user supplied extraction function (the third argument) at each step. This is
236−-- designed to work with the @foldl@ library. The suffix @x@ is a mnemonic for
237−-- extraction.
238−--
239−-- @since 0.7.0
240−{-# INLINE scanlx' #-}
241−scanlx' :: (IsStream t, Monad m)
242− => (x -> a -> x) -> x -> (x -> b) -> t m a -> t m b
243−scanlx' step begin done m =
244− fromStreamS $ S.scanlx' step begin done $ toStreamS m
245−
246−------------------------------------------------------------------------------
247−-- Comparison
248−------------------------------------------------------------------------------
249−
250−-- | Compare two streams for equality
251−--
252−-- @since 0.5.3
253−{-# INLINE eqBy #-}
254−eqBy :: (IsStream t, Monad m) => (a -> b -> Bool) -> t m a -> t m b -> m Bool
255−eqBy f m1 m2 = D.eqBy f (D.toStreamD m1) (D.toStreamD m2)
256−
257−-- | Compare two streams
258−--
259−-- @since 0.5.3
260−{-# INLINE cmpBy #-}
261−cmpBy
262− :: (IsStream t, Monad m)
263− => (a -> b -> Ordering) -> t m a -> t m b -> m Ordering
264−cmpBy f m1 m2 = D.cmpBy f (D.toStreamD m1) (D.toStreamD m2)
265−
266−{-# INLINE minimum #-}
267−minimum :: (IsStream t, Monad m, Ord a) => t m a -> m (Maybe a)
268−minimum m = S.minimum (toStreamS m)
269−
270−{-# INLINE maximum #-}
271−maximum :: (IsStream t, Monad m, Ord a) => t m a -> m (Maybe a)
272−maximum m = S.maximum (toStreamS m)
273−
274−------------------------------------------------------------------------------
275−-- Fold Utilities
276−------------------------------------------------------------------------------
277−
278−{-
279−-- XXX do we have facilities in Foldable to fold any Foldable in this manner?
280−--
281−-- | Perform a pair wise bottom up hierarchical fold of elements in the
282−-- container using the given function as the merge function.
283−--
284−-- This will perform a balanced merge sort if the merge function is
285−-- 'mergeBy compare'.
286−--
287−-- @since 0.7.0
288−{-# INLINABLE foldbWith #-}
289−foldbWith :: IsStream t
290− => (t m a -> t m a -> t m a) -> SerialT Identity (t m a) -> t m a
291−foldbWith f = K.foldb f K.nil
292−-}
293−
294−
295−-- | A variant of 'Data.Foldable.fold' that allows you to fold a 'Foldable'
296−-- container of streams using the specified stream sum operation.
297−--
298−-- @concatFoldableWith 'async' $ map return [1..3]@
299−--
300−-- Equivalent to:
301−--
302−-- @
303−-- concatFoldableWith f = Prelude.foldr f S.nil
304−-- concatFoldableWith f = S.concatMapFoldableWith f id
305−-- @
306−--
307−-- /Since: 0.8.0 (Renamed foldWith to concatFoldableWith)/
308−--
309−-- /Since: 0.1.0 ("Streamly")/
310−{-# INLINABLE concatFoldableWith #-}
311−concatFoldableWith :: (IsStream t, Foldable f)
312− => (t m a -> t m a -> t m a) -> f (t m a) -> t m a
313−concatFoldableWith f = Prelude.foldr f K.nil
314−
315−-- | A variant of 'foldMap' that allows you to map a monadic streaming action
316−-- on a 'Foldable' container and then fold it using the specified stream merge
317−-- operation.
318−--
319−-- @concatMapFoldableWith 'async' return [1..3]@
320−--
321−-- Equivalent to:
322−--
323−-- @
324−-- concatMapFoldableWith f g = Prelude.foldr (f . g) S.nil
325−-- concatMapFoldableWith f g xs = S.concatMapWith f g (S.fromFoldable xs)
326−-- @
327−--
328−-- /Since: 0.8.0 (Renamed foldMapWith to concatMapFoldableWith)/
329−--
330−-- /Since: 0.1.0 ("Streamly")/
331−{-# INLINABLE concatMapFoldableWith #-}
332−concatMapFoldableWith :: (IsStream t, Foldable f)
333− => (t m b -> t m b -> t m b) -> (a -> t m b) -> f a -> t m b
334−concatMapFoldableWith f g = Prelude.foldr (f . g) K.nil
335−
336−-- | Like 'concatMapFoldableWith' but with the last two arguments reversed i.e. the
337−-- monadic streaming function is the last argument.
338−--
339−-- Equivalent to:
340−--
341−-- @
342−-- concatForFoldableWith f xs g = Prelude.foldr (f . g) S.nil xs
343−-- concatForFoldableWith = flip S.concatMapFoldableWith
344−-- @
345−--
346−-- /Since: 0.8.0 (Renamed forEachWith to concatForFoldableWith)/
347−--
348−-- /Since: 0.1.0 ("Streamly")/
349−{-# INLINABLE concatForFoldableWith #-}
350−concatForFoldableWith :: (IsStream t, Foldable f)
351− => (t m b -> t m b -> t m b) -> f a -> (a -> t m b) -> t m b
352−concatForFoldableWith f xs g = Prelude.foldr (f . g) K.nil xs
src/Streamly/Internal/Data/Stream/PreludeCommon.hsnew file+139
@@ -0,0 +1,139 @@
1+------------------------------------------------------------------------------
2+-- Conversion to and from direct style stream
3+------------------------------------------------------------------------------
4+
5+#ifdef USE_IS_STREAM
6+#define IS_STREAM IsStream t,
7+#define FROM_STREAM fromStream
8+#define TO_STREAM toStream
9+#define STREAM t
10+#else
11+#define IS_STREAM
12+#define FROM_STREAM id
13+#define TO_STREAM id
14+#define STREAM K.Stream
15+#endif
16+
17+-- These definitions are dependent on what is imported as S
18+{-# INLINE fromStreamS #-}
19+fromStreamS :: (IS_STREAM Monad m) => S.Stream m a -> STREAM m a
20+fromStreamS = FROM_STREAM . S.toStreamK
21+
22+{-# INLINE toStreamS #-}
23+toStreamS :: (IS_STREAM Monad m) => STREAM m a -> S.Stream m a
24+toStreamS = S.fromStreamK . TO_STREAM
25+
26+{-# INLINE toStreamD #-}
27+toStreamD :: (IS_STREAM Monad m) => STREAM m a -> D.Stream m a
28+toStreamD = D.fromStreamK . TO_STREAM
29+
30+------------------------------------------------------------------------------
31+-- Conversions
32+------------------------------------------------------------------------------
33+
34+{-# INLINE_EARLY drain #-}
35+drain :: (IS_STREAM Monad m) => STREAM m a -> m ()
36+drain m = D.drain $ D.fromStreamK (TO_STREAM m)
37+{-# RULES "drain fallback to CPS" [1]
38+ forall a. D.drain (D.fromStreamK a) = K.drain a #-}
39+
40+------------------------------------------------------------------------------
41+-- Conversions
42+------------------------------------------------------------------------------
43+
44+-- |
45+-- @
46+-- fromList = 'Prelude.foldr' 'K.cons' 'K.nil'
47+-- @
48+--
49+-- Construct a stream from a list of pure values. This is more efficient than
50+-- 'K.fromFoldable' for serial streams.
51+--
52+-- @since 0.4.0
53+{-# INLINE_EARLY fromList #-}
54+#ifdef USE_IS_STREAM
55+fromList :: (Monad m, IsStream t) => [a] -> STREAM m a
56+#else
57+fromList :: Monad m => [a] -> STREAM m a
58+#endif
59+fromList = fromStreamS . S.fromList
60+{-# RULES "fromList fallback to StreamK" [1]
61+ forall a. S.toStreamK (S.fromList a) = K.fromFoldable a #-}
62+
63+-- | Convert a stream into a list in the underlying monad.
64+--
65+-- @since 0.1.0
66+{-# INLINE toList #-}
67+toList :: (IS_STREAM Monad m) => STREAM m a -> m [a]
68+toList m = S.toList $ toStreamS m
69+
70+------------------------------------------------------------------------------
71+-- Folds
72+------------------------------------------------------------------------------
73+
74+{-# INLINE foldrM #-}
75+foldrM :: (IS_STREAM Monad m) => (a -> m b -> m b) -> m b -> STREAM m a -> m b
76+foldrM step acc m = S.foldrM step acc $ toStreamS m
77+
78+{-# INLINE foldrMx #-}
79+foldrMx :: (IS_STREAM Monad m)
80+ => (a -> m x -> m x) -> m x -> (m x -> m b) -> STREAM m a -> m b
81+foldrMx step final project m = D.foldrMx step final project $ toStreamD m
82+
83+{-# INLINE foldr #-}
84+foldr :: (IS_STREAM Monad m) => (a -> b -> b) -> b -> STREAM m a -> m b
85+foldr f z = foldrM (\a b -> f a <$> b) (return z)
86+
87+-- | Like 'foldlx'', but with a monadic step function.
88+--
89+-- @since 0.7.0
90+{-# INLINE foldlMx' #-}
91+foldlMx' ::
92+ (IS_STREAM Monad m)
93+ => (x -> a -> m x) -> m x -> (x -> m b) -> STREAM m a -> m b
94+foldlMx' step begin done m = S.foldlMx' step begin done $ toStreamS m
95+
96+-- | Strict left fold with an extraction function. Like the standard strict
97+-- left fold, but applies a user supplied extraction function (the third
98+-- argument) to the folded value at the end. This is designed to work with the
99+-- @foldl@ library. The suffix @x@ is a mnemonic for extraction.
100+--
101+-- @since 0.7.0
102+{-# INLINE foldlx' #-}
103+foldlx' ::
104+ (IS_STREAM Monad m) => (x -> a -> x) -> x -> (x -> b) -> STREAM m a -> m b
105+foldlx' step begin done m = S.foldlx' step begin done $ toStreamS m
106+
107+-- | Strict left associative fold.
108+--
109+-- @since 0.2.0
110+{-# INLINE foldl' #-}
111+foldl' ::
112+ (IS_STREAM Monad m) => (b -> a -> b) -> b -> STREAM m a -> m b
113+foldl' step begin m = S.foldl' step begin $ toStreamS m
114+
115+
116+{-# INLINE fold #-}
117+fold :: (IS_STREAM Monad m) => Fold m a b -> STREAM m a -> m b
118+fold fld m = S.fold fld $ toStreamS m
119+
120+------------------------------------------------------------------------------
121+-- Comparison
122+------------------------------------------------------------------------------
123+
124+-- | Compare two streams for equality
125+--
126+-- @since 0.5.3
127+{-# INLINE eqBy #-}
128+eqBy :: (IS_STREAM Monad m) =>
129+ (a -> b -> Bool) -> STREAM m a -> STREAM m b -> m Bool
130+eqBy f m1 m2 = D.eqBy f (toStreamD m1) (toStreamD m2)
131+
132+-- | Compare two streams
133+--
134+-- @since 0.5.3
135+{-# INLINE cmpBy #-}
136+cmpBy
137+ :: (IS_STREAM Monad m)
138+ => (a -> b -> Ordering) -> STREAM m a -> STREAM m b -> m Ordering
139+cmpBy f m1 m2 = D.cmpBy f (toStreamD m1) (toStreamD m2)
src/Streamly/Internal/Data/Stream/SVar/Eliminate.hs+7−6
@@ -35,6 +35,7 @@ import Streamly.Internal.Control.Concurrent (MonadAsync, doFork)
35import Streamly.Internal.Data.Atomics (atomicModifyIORefCAS_)
35import Streamly.Internal.Data.Atomics (atomicModifyIORefCAS_)
36import Streamly.Internal.Data.Fold.SVar (write, writeLimited)
36import Streamly.Internal.Data.Fold.SVar (write, writeLimited)
37import Streamly.Internal.Data.Fold.Type (Fold(..))
37import Streamly.Internal.Data.Fold.Type (Fold(..))
38+import Streamly.Internal.Data.Stream.Serial (SerialT(..))
38import Streamly.Internal.Data.Time.Clock (Clock(Monotonic), getTime)
39import Streamly.Internal.Data.Time.Clock (Clock(Monotonic), getTime)
39
40
40import qualified Streamly.Internal.Data.Stream.StreamD.Type as D
41import qualified Streamly.Internal.Data.Stream.StreamD.Type as D
@@ -203,8 +204,8 @@ fromProducer sv = K.mkStream $ \st yld sng stp -> do
203-- function.
204-- function.
204--
205--
205{-# INLINE newFoldSVar #-}
206{-# INLINE newFoldSVar #-}
206−newFoldSVar :: (K.IsStream t, MonadAsync m)
207+newFoldSVar :: MonadAsync m
207− => State K.Stream m a -> (t m a -> m b) -> m (SVar K.Stream m a)
208+ => State K.Stream m a -> (SerialT m a -> m b) -> m (SVar K.Stream m a)
208newFoldSVar stt f = do
209newFoldSVar stt f = do
209 -- Buffer size for the SVar is derived from the current state
210 -- Buffer size for the SVar is derived from the current state
210 sv <- newParallelVar StopAny (adaptState stt)
211 sv <- newParallelVar StopAny (adaptState stt)
@@ -212,7 +213,7 @@ newFoldSVar stt f = do
212 -- Add the producer thread-id to the SVar.
213 -- Add the producer thread-id to the SVar.
213 liftIO myThreadId >>= modifyThread sv
214 liftIO myThreadId >>= modifyThread sv
214
215
215− void $ doFork (void $ f $ K.fromStream $ fromProducer sv)
216+ void $ doFork (void $ f $ SerialT $ fromProducer sv)
216 (svarMrun sv)
217 (svarMrun sv)
217 (handleFoldException sv)
218 (handleFoldException sv)
218 return sv
219 return sv
@@ -365,9 +366,9 @@ pushToFold sv a = do
365-- @
366-- @
366--
367--
367{-# INLINE teeToSVar #-}
368{-# INLINE teeToSVar #-}
368−teeToSVar :: (K.IsStream t, MonadAsync m) =>
369+teeToSVar :: MonadAsync m =>
369− SVar K.Stream m a -> t m a -> t m a
370+ SVar K.Stream m a -> SerialT m a -> SerialT m a
370−teeToSVar svr m = K.mkStream $ \st yld sng stp -> do
371+teeToSVar svr (SerialT m) = SerialT $ K.mkStream $ \st yld sng stp -> do
371 K.foldStreamShared st yld sng stp (go False m)
372 K.foldStreamShared st yld sng stp (go False m)
372
373
373 where
374 where
src/Streamly/Internal/Data/Stream/SVar/Generate.hs+7−13
@@ -19,8 +19,7 @@
19module Streamly.Internal.Data.Stream.SVar.Generate
19module Streamly.Internal.Data.Stream.SVar.Generate
20 (
20 (
21 -- * Write to SVar
21 -- * Write to SVar
22− toStreamVar
23− , toSVar
22+ toSVar
24
23
25 -- * Read from SVar
24 -- * Read from SVar
26 -- $concurrentEval
25 -- $concurrentEval
@@ -39,6 +38,7 @@ import Control.Monad.IO.Class (MonadIO(liftIO))
39import Data.IORef (newIORef, readIORef, mkWeakIORef, writeIORef)
38import Data.IORef (newIORef, readIORef, mkWeakIORef, writeIORef)
40import Data.Maybe (isNothing)
39import Data.Maybe (isNothing)
41import Streamly.Internal.Control.Concurrent (MonadAsync, captureMonadState)
40import Streamly.Internal.Control.Concurrent (MonadAsync, captureMonadState)
41+import Streamly.Internal.Data.Stream.Serial (SerialT(..))
42import Streamly.Internal.Data.Time.Clock (Clock(Monotonic), getTime)
42import Streamly.Internal.Data.Time.Clock (Clock(Monotonic), getTime)
43import System.Mem (performMajorGC)
43import System.Mem (performMajorGC)
44
44
@@ -88,8 +88,8 @@ import Test.Inspection (inspect, hasNoTypeClassesExcept)
88-- XXX this errors out for Parallel/Ahead SVars
88-- XXX this errors out for Parallel/Ahead SVars
89-- | Write a stream to an 'SVar' in a non-blocking manner. The stream can then
89-- | Write a stream to an 'SVar' in a non-blocking manner. The stream can then
90-- be read back from the SVar using 'fromSVar'.
90-- be read back from the SVar using 'fromSVar'.
91−toStreamVar :: MonadAsync m => SVar t m a -> t m a -> m ()
91+toSVar :: MonadAsync m => SVar SerialT m a -> SerialT m a -> m ()
92−toStreamVar sv m = do
92+toSVar sv m = do
93 runIn <- captureMonadState
93 runIn <- captureMonadState
94 liftIO $ enqueue sv (runIn, m)
94 liftIO $ enqueue sv (runIn, m)
95 done <- allThreadsDone sv
95 done <- allThreadsDone sv
@@ -103,12 +103,6 @@ toStreamVar sv m = do
103 Nothing -> pushWorker 0 sv
103 Nothing -> pushWorker 0 sv
104 Just _ -> pushWorker 1 sv
104 Just _ -> pushWorker 1 sv
105
105
106−-- | Write a stream to an 'SVar' in a non-blocking manner. The stream is
107−-- evaluated concurrently as it is read back from the SVar using 'fromSVar'.
108−--
109−toSVar :: (K.IsStream t, MonadAsync m) => SVar K.Stream m a -> t m a -> m ()
110−toSVar sv m = toStreamVar sv $ K.toStream m
111−
112-------------------------------------------------------------------------------
106-------------------------------------------------------------------------------
113-- Read a stream from an SVar
107-- Read a stream from an SVar
114-------------------------------------------------------------------------------
108-------------------------------------------------------------------------------
@@ -191,16 +185,16 @@ inspect $ hasNoTypeClassesExcept 'fromStreamVar
191-- combinators.
185-- combinators.
192--
186--
193{-# INLINE fromSVar #-}
187{-# INLINE fromSVar #-}
194−fromSVar :: (MonadAsync m, K.IsStream t) => SVar K.Stream m a -> t m a
188+fromSVar :: MonadAsync m => SVar K.Stream m a -> SerialT m a
195fromSVar sv =
189fromSVar sv =
196− K.mkStream $ \st yld sng stp -> do
190+ SerialT $ K.mkStream $ \st yld sng stp -> do
197 ref <- liftIO $ newIORef ()
191 ref <- liftIO $ newIORef ()
198 _ <- liftIO $ mkWeakIORef ref hook
192 _ <- liftIO $ mkWeakIORef ref hook
199 -- We pass a copy of sv to fromStreamVar, so that we know that it has
193 -- We pass a copy of sv to fromStreamVar, so that we know that it has
200 -- no other references, when that copy gets garbage collected "ref"
194 -- no other references, when that copy gets garbage collected "ref"
201 -- will get garbage collected and our hook will be called.
195 -- will get garbage collected and our hook will be called.
202 K.foldStreamShared st yld sng stp $
196 K.foldStreamShared st yld sng stp $
203− K.fromStream $ fromStreamVar sv{svarRef = Just ref}
197+ fromStreamVar sv{svarRef = Just ref}
204 where
198 where
205
199
206 hook = do
200 hook = do
src/Streamly/Internal/Data/Stream/Serial.hs+85−114
@@ -16,21 +16,28 @@
16module Streamly.Internal.Data.Stream.Serial
16module Streamly.Internal.Data.Stream.Serial
17 (
17 (
18 -- * Serial appending stream
18 -- * Serial appending stream
19− SerialT
19+ SerialT(..)
20 , Serial
20 , Serial
21− , K.serial
21+ , serial
22− , fromSerial
23
22
24 -- * Serial interleaving stream
23 -- * Serial interleaving stream
25− , WSerialT
24+ , WSerialT(..)
26 , WSerial
25 , WSerial
26+ , wSerialK
27 , wSerial
27 , wSerial
28 , wSerialFst
28 , wSerialFst
29 , wSerialMin
29 , wSerialMin
30− , fromWSerial
30+ , consMWSerial
31
31
32 -- * Construction
32 -- * Construction
33+ , cons
34+ , consM
35+ , repeat
33 , unfoldrM
36 , unfoldrM
37+ , fromList
38+
39+ -- * Elimination
40+ , toList
34
41
35 -- * Transformation
42 -- * Transformation
36 , map
43 , map
@@ -39,8 +46,6 @@ module Streamly.Internal.Data.Stream.Serial
39 -- * Deprecated
46 -- * Deprecated
40 , StreamT
47 , StreamT
41 , InterleavedT
48 , InterleavedT
42− , (<=>)
43− , interleaving
44 )
49 )
45where
50where
46
51
@@ -67,18 +72,16 @@ import Text.Read
67 ( Lexeme(Ident), lexP, parens, prec, readPrec, readListPrec
72 ( Lexeme(Ident), lexP, parens, prec, readPrec, readListPrec
68 , readListPrecDefault)
73 , readListPrecDefault)
69import Streamly.Internal.BaseCompat ((#.), errorWithoutStackTrace, oneShot)
74import Streamly.Internal.BaseCompat ((#.), errorWithoutStackTrace, oneShot)
70−import Streamly.Internal.Data.Stream.StreamK.Type
71− (IsStream(..), adapt, Stream, mkStream, foldStream)
72import Streamly.Internal.Data.Maybe.Strict (Maybe'(..), toMaybe)
75import Streamly.Internal.Data.Maybe.Strict (Maybe'(..), toMaybe)
76+import Streamly.Internal.Data.Stream.StreamK.Type
77+ (Stream, mkStream, foldStream)
73
78
74import qualified Streamly.Internal.Data.Stream.Prelude as P
79import qualified Streamly.Internal.Data.Stream.Prelude as P
75− (cmpBy, foldl', foldr, eqBy, fromList, toList)
76−import qualified Streamly.Internal.Data.Stream.StreamK as K (withLocal)
77−import qualified Streamly.Internal.Data.Stream.StreamK.Type as K
78−import qualified Streamly.Internal.Data.Stream.StreamD.Generate as D (unfoldrM)
80+import qualified Streamly.Internal.Data.Stream.StreamD.Generate as D
79import qualified Streamly.Internal.Data.Stream.StreamD.Type as D
81import qualified Streamly.Internal.Data.Stream.StreamD.Type as D
82+import qualified Streamly.Internal.Data.Stream.StreamK.Type as K
80
83
81−import Prelude hiding (map, mapM, errorWithoutStackTrace)
84+import Prelude hiding (map, mapM, errorWithoutStackTrace, repeat)
82
85
83#include "Instances.hs"
86#include "Instances.hs"
84#include "inline.hs"
87#include "inline.hs"
@@ -136,24 +139,33 @@ type Serial = SerialT IO
136{-# DEPRECATED StreamT "Please use 'SerialT' instead." #-}
139{-# DEPRECATED StreamT "Please use 'SerialT' instead." #-}
137type StreamT = SerialT
140type StreamT = SerialT
138
141
139−-- | Fix the type of a polymorphic stream as 'SerialT'.
142+------------------------------------------------------------------------------
140−--
143+-- Generation
141−-- /Since: 0.1.0 ("Streamly")/
144+------------------------------------------------------------------------------
145+
146+{-# INLINE cons #-}
147+cons :: a -> SerialT m a -> SerialT m a
148+cons x (SerialT ms) = SerialT $ K.cons x ms
149+
150+{-# INLINE consM #-}
151+{-# SPECIALIZE consM :: IO a -> SerialT IO a -> SerialT IO a #-}
152+consM :: Monad m => m a -> SerialT m a -> SerialT m a
153+consM m (SerialT ms) = SerialT $ K.consM m ms
154+
155+-- |
156+-- Generate an infinite stream by repeating a pure value.
142--
157--
143−-- @since 0.8.0
158+{-# INLINE_NORMAL repeat #-}
144−fromSerial :: IsStream t => SerialT m a -> t m a
159+repeat :: Monad m => a -> SerialT m a
145−fromSerial = adapt
160+repeat = SerialT . D.toStreamK . D.repeat
146
161
147−{-# INLINE consMSerial #-}
162+------------------------------------------------------------------------------
148−{-# SPECIALIZE consMSerial :: IO a -> SerialT IO a -> SerialT IO a #-}
163+-- Combining
149−consMSerial :: Monad m => m a -> SerialT m a -> SerialT m a
164+------------------------------------------------------------------------------
150−consMSerial m ms = fromStream $ K.consMStream m (toStream ms)
151
165
152−instance IsStream SerialT where
166+{-# INLINE serial #-}
153− toStream = getSerialT
167+serial :: SerialT m a -> SerialT m a -> SerialT m a
154− fromStream = SerialT
168+serial = (<>)
155− consM = consMSerial
156− (|:) = consMSerial
157
169
158------------------------------------------------------------------------------
170------------------------------------------------------------------------------
159-- Monad
171-- Monad
@@ -173,7 +185,7 @@ instance Monad m => Monad (SerialT m) where
173 -- n binds, breakAfterSome, filterAllIn, state transformer (~2x)
185 -- n binds, breakAfterSome, filterAllIn, state transformer (~2x)
174 --
186 --
175 {-# INLINE (>>=) #-}
187 {-# INLINE (>>=) #-}
176− (>>=) = K.bindWith K.serial
188+ (>>=) (SerialT m) f = SerialT $ K.bindWith K.serial m (getSerialT . f)
177
189
178 {-# INLINE (>>) #-}
190 {-# INLINE (>>) #-}
179 (>>) = (*>)
191 (>>) = (*>)
@@ -183,8 +195,8 @@ instance Monad m => Monad (SerialT m) where
183------------------------------------------------------------------------------
195------------------------------------------------------------------------------
184
196
185{-# INLINE mapM #-}
197{-# INLINE mapM #-}
186−mapM :: (IsStream t, Monad m) => (a -> m b) -> t m a -> t m b
198+mapM :: Monad m => (a -> m b) -> SerialT m a -> SerialT m b
187−mapM f m = D.fromStreamD $ D.mapM f $ D.toStreamD m
199+mapM f (SerialT m) = SerialT $ D.toStreamK $ D.mapM f $ D.fromStreamK m
188
200
189-- |
201-- |
190-- @
202-- @
@@ -200,23 +212,23 @@ mapM f m = D.fromStreamD $ D.mapM f $ D.toStreamD m
200--
212--
201-- @since 0.4.0
213-- @since 0.4.0
202{-# INLINE map #-}
214{-# INLINE map #-}
203−map :: (IsStream t, Monad m) => (a -> b) -> t m a -> t m b
215+map :: Monad m => (a -> b) -> SerialT m a -> SerialT m b
204map f = mapM (return . f)
216map f = mapM (return . f)
205
217
206{-# INLINE apSerial #-}
218{-# INLINE apSerial #-}
207apSerial :: Monad m => SerialT m (a -> b) -> SerialT m a -> SerialT m b
219apSerial :: Monad m => SerialT m (a -> b) -> SerialT m a -> SerialT m b
208apSerial (SerialT m1) (SerialT m2) =
220apSerial (SerialT m1) (SerialT m2) =
209− D.fromStreamD $ D.toStreamD m1 <*> D.toStreamD m2
221+ SerialT $ D.toStreamK $ D.fromStreamK m1 <*> D.fromStreamK m2
210
222
211{-# INLINE apSequence #-}
223{-# INLINE apSequence #-}
212apSequence :: Monad m => SerialT m a -> SerialT m b -> SerialT m b
224apSequence :: Monad m => SerialT m a -> SerialT m b -> SerialT m b
213apSequence (SerialT m1) (SerialT m2) =
225apSequence (SerialT m1) (SerialT m2) =
214− D.fromStreamD $ D.toStreamD m1 *> D.toStreamD m2
226+ SerialT $ D.toStreamK $ D.fromStreamK m1 *> D.fromStreamK m2
215
227
216{-# INLINE apDiscardSnd #-}
228{-# INLINE apDiscardSnd #-}
217apDiscardSnd :: Monad m => SerialT m a -> SerialT m b -> SerialT m a
229apDiscardSnd :: Monad m => SerialT m a -> SerialT m b -> SerialT m a
218apDiscardSnd (SerialT m1) (SerialT m2) =
230apDiscardSnd (SerialT m1) (SerialT m2) =
219− D.fromStreamD $ D.toStreamD m1 <* D.toStreamD m2
231+ SerialT $ D.toStreamK $ D.fromStreamK m1 <* D.fromStreamK m2
220
232
221-- Note: we need to define all the typeclass operations because we want to
233-- Note: we need to define all the typeclass operations because we want to
222-- INLINE them.
234-- INLINE them.
@@ -285,7 +297,7 @@ TRAVERSABLE_INSTANCE(SerialT)
285-- @2@:
297-- @2@:
286--
298--
287-- >>> import Streamly.Prelude (wSerial)
299-- >>> import Streamly.Prelude (wSerial)
288−-- >>> Stream.toList $ Stream.fromList [(1,3),(1,4)] `wSerial` Stream.fromList [(2,3),(2,4)]
300+-- >>> Stream.toList $ Stream.fromList [(1,3),(1,4)] `Stream.wSerial` Stream.fromList [(2,3),(2,4)]
289-- [(1,3),(2,3),(1,4),(2,4)]
301-- [(1,3),(2,3),(1,4),(2,4)]
290--
302--
291-- The @W@ in the name stands for @wide@ or breadth wise scheduling in
303-- The @W@ in the name stands for @wide@ or breadth wise scheduling in
@@ -310,37 +322,10 @@ type WSerial = WSerialT IO
310{-# DEPRECATED InterleavedT "Please use 'WSerialT' instead." #-}
322{-# DEPRECATED InterleavedT "Please use 'WSerialT' instead." #-}
311type InterleavedT = WSerialT
323type InterleavedT = WSerialT
312
324
313−-- | Fix the type of a polymorphic stream as 'WSerialT'.
325+{-# INLINE consMWSerial #-}
314−--
326+{-# SPECIALIZE consMWSerial :: IO a -> WSerialT IO a -> WSerialT IO a #-}
315−-- /Since: 0.2.0 ("Streamly")/
316−--
317−-- @since 0.8.0
318−fromWSerial :: IsStream t => WSerialT m a -> t m a
319−fromWSerial = adapt
320−
321−-- | Same as 'fromWSerial'.
322−--
323−-- @since 0.1.0
324−{-# DEPRECATED interleaving "Please use fromWSerial instead." #-}
325−interleaving :: IsStream t => WSerialT m a -> t m a
326−interleaving = fromWSerial
327−
328consMWSerial :: Monad m => m a -> WSerialT m a -> WSerialT m a
327consMWSerial :: Monad m => m a -> WSerialT m a -> WSerialT m a
329−consMWSerial m ms = fromStream $ K.consMStream m (toStream ms)
328+consMWSerial m (WSerialT ms) = WSerialT $ K.consM m ms
330−
331−instance IsStream WSerialT where
332− toStream = getWSerialT
333− fromStream = WSerialT
334−
335− {-# INLINE consM #-}
336− {-# SPECIALIZE consM :: IO a -> WSerialT IO a -> WSerialT IO a #-}
337− consM :: Monad m => m a -> WSerialT m a -> WSerialT m a
338− consM = consMWSerial
339−
340− {-# INLINE (|:) #-}
341− {-# SPECIALIZE (|:) :: IO a -> WSerialT IO a -> WSerialT IO a #-}
342− (|:) :: Monad m => m a -> WSerialT m a -> WSerialT m a
343− (|:) = consMWSerial
344
329
345------------------------------------------------------------------------------
330------------------------------------------------------------------------------
346-- Semigroup
331-- Semigroup
@@ -355,25 +340,17 @@ infixr 6 `wSerial`
355--
340--
356-- Similar combinators can be implemented using WAhead style.
341-- Similar combinators can be implemented using WAhead style.
357
342
343+{-# INLINE wSerialK #-}
344+wSerialK :: Stream m a -> Stream m a -> Stream m a
345+wSerialK m1 m2 = mkStream $ \st yld sng stp -> do
346+ let stop = foldStream st yld sng stp m2
347+ single a = yld a m2
348+ yieldk a r = yld a (wSerialK m2 r)
349+ foldStream st yieldk single stop m1
350+
358-- | Interleaves two streams, yielding one element from each stream
351-- | Interleaves two streams, yielding one element from each stream
359-- alternately. When one stream stops the rest of the other stream is used in
352-- alternately. When one stream stops the rest of the other stream is used in
360-- the output stream.
353-- the output stream.
361−--
362−-- >>> import Streamly.Prelude (wSerial)
363−-- >>> stream1 = Stream.fromList [1,2]
364−-- >>> stream2 = Stream.fromList [3,4]
365−-- >>> Stream.toList $ Stream.fromWSerial $ stream1 `wSerial` stream2
366−-- [1,3,2,4]
367−--
368−-- Note, for singleton streams 'wSerial' and 'serial' are identical.
369−--
370−-- Note that this operation cannot be used to fold a container of infinite
371−-- streams but it can be used for very large streams as the state that it needs
372−-- to maintain is proportional to the logarithm of the number of streams.
373−--
374−-- @since 0.8.0
375−--
376−-- /Since: 0.2.0 ("Streamly")/
377
354
378-- Scheduling Notes:
355-- Scheduling Notes:
379--
356--
@@ -387,19 +364,15 @@ infixr 6 `wSerial`
387-- each subexpression on the right.
364-- each subexpression on the right.
388--
365--
389{-# INLINE wSerial #-}
366{-# INLINE wSerial #-}
390−wSerial :: IsStream t => t m a -> t m a -> t m a
367+wSerial :: WSerialT m a -> WSerialT m a -> WSerialT m a
391−wSerial m1 m2 = mkStream $ \st yld sng stp -> do
368+wSerial (WSerialT m1) (WSerialT m2) = WSerialT $ wSerialK m1 m2
392− let stop = foldStream st yld sng stp m2
393− single a = yld a m2
394− yieldk a r = yld a (wSerial m2 r)
395− foldStream st yieldk single stop m1
396
369
397-- | Like `wSerial` but stops interleaving as soon as the first stream stops.
370-- | Like `wSerial` but stops interleaving as soon as the first stream stops.
398--
371--
399-- @since 0.7.0
372-- @since 0.7.0
400−{-# INLINE wSerialFst #-}
373+{-# INLINE wSerialFstK #-}
401−wSerialFst :: IsStream t => t m a -> t m a -> t m a
374+wSerialFstK :: Stream m a -> Stream m a -> Stream m a
402−wSerialFst m1 m2 = mkStream $ \st yld sng stp -> do
375+wSerialFstK m1 m2 = mkStream $ \st yld sng stp -> do
403 let yieldFirst a r = yld a (yieldSecond r m2)
376 let yieldFirst a r = yld a (yieldSecond r m2)
404 in foldStream st yieldFirst sng stp m1
377 in foldStream st yieldFirst sng stp m1
405
378
@@ -408,49 +381,47 @@ wSerialFst m1 m2 = mkStream $ \st yld sng stp -> do
408 yieldSecond s1 s2 = mkStream $ \st yld sng stp -> do
381 yieldSecond s1 s2 = mkStream $ \st yld sng stp -> do
409 let stop = foldStream st yld sng stp s1
382 let stop = foldStream st yld sng stp s1
410 single a = yld a s1
383 single a = yld a s1
411− yieldk a r = yld a (wSerial s1 r)
384+ yieldk a r = yld a (wSerialK s1 r)
412 in foldStream st yieldk single stop s2
385 in foldStream st yieldk single stop s2
413
386
387+{-# INLINE wSerialFst #-}
388+wSerialFst :: WSerialT m a -> WSerialT m a -> WSerialT m a
389+wSerialFst (WSerialT m1) (WSerialT m2) = WSerialT $ wSerialFstK m1 m2
390+
414-- | Like `wSerial` but stops interleaving as soon as any of the two streams
391-- | Like `wSerial` but stops interleaving as soon as any of the two streams
415-- stops.
392-- stops.
416--
393--
417-- @since 0.7.0
394-- @since 0.7.0
418−{-# INLINE wSerialMin #-}
395+{-# INLINE wSerialMinK #-}
419−wSerialMin :: IsStream t => t m a -> t m a -> t m a
396+wSerialMinK :: Stream m a -> Stream m a -> Stream m a
420−wSerialMin m1 m2 = mkStream $ \st yld _ stp -> do
397+wSerialMinK m1 m2 = mkStream $ \st yld _ stp -> do
421 let stop = stp
398 let stop = stp
422 -- "single a" is defined as "yld a (wSerialMin m2 K.nil)" instead of
399 -- "single a" is defined as "yld a (wSerialMin m2 K.nil)" instead of
423 -- "sng a" to keep the behaviour consistent with the yield continuation.
400 -- "sng a" to keep the behaviour consistent with the yield continuation.
424− single a = yld a (wSerialMin m2 K.nil)
401+ single a = yld a (wSerialMinK m2 K.nil)
425− yieldk a r = yld a (wSerialMin m2 r)
402+ yieldk a r = yld a (wSerialMinK m2 r)
426 foldStream st yieldk single stop m1
403 foldStream st yieldk single stop m1
427
404
405+{-# INLINE wSerialMin #-}
406+wSerialMin :: WSerialT m a -> WSerialT m a -> WSerialT m a
407+wSerialMin (WSerialT m1) (WSerialT m2) = WSerialT $ wSerialMinK m1 m2
408+
428instance Semigroup (WSerialT m a) where
409instance Semigroup (WSerialT m a) where
429 (<>) = wSerial
410 (<>) = wSerial
430
411
431−infixr 5 <=>
432−
433−-- | Same as 'wSerial'.
434−--
435−-- @since 0.1.0
436−{-# DEPRECATED (<=>) "Please use 'wSerial' instead." #-}
437−{-# INLINE (<=>) #-}
438−(<=>) :: IsStream t => t m a -> t m a -> t m a
439−(<=>) = wSerial
440−
441------------------------------------------------------------------------------
412------------------------------------------------------------------------------
442-- Monoid
413-- Monoid
443------------------------------------------------------------------------------
414------------------------------------------------------------------------------
444
415
445instance Monoid (WSerialT m a) where
416instance Monoid (WSerialT m a) where
446− mempty = K.nil
417+ mempty = WSerialT K.nil
447 mappend = (<>)
418 mappend = (<>)
448
419
449{-# INLINE apWSerial #-}
420{-# INLINE apWSerial #-}
450apWSerial :: Monad m => WSerialT m (a -> b) -> WSerialT m a -> WSerialT m b
421apWSerial :: Monad m => WSerialT m (a -> b) -> WSerialT m a -> WSerialT m b
451apWSerial (WSerialT m1) (WSerialT m2) =
422apWSerial (WSerialT m1) (WSerialT m2) =
452− let f x1 = K.concatMapBy wSerial (pure . x1) m2
423+ let f x1 = K.concatMapWith wSerialK (pure . x1) m2
453− in WSerialT $ K.concatMapBy wSerial f m1
424+ in WSerialT $ K.concatMapWith wSerialK f m1
454
425
455instance Monad m => Applicative (WSerialT m) where
426instance Monad m => Applicative (WSerialT m) where
456 {-# INLINE pure #-}
427 {-# INLINE pure #-}
@@ -465,7 +436,7 @@ instance Monad m => Applicative (WSerialT m) where
465instance Monad m => Monad (WSerialT m) where
436instance Monad m => Monad (WSerialT m) where
466 return = pure
437 return = pure
467 {-# INLINE (>>=) #-}
438 {-# INLINE (>>=) #-}
468− (>>=) = K.bindWith wSerial
439+ (>>=) (WSerialT m) f = WSerialT $ K.bindWith wSerialK m (getWSerialT . f)
469
440
470------------------------------------------------------------------------------
441------------------------------------------------------------------------------
471-- Other instances
442-- Other instances
@@ -503,5 +474,5 @@ TRAVERSABLE_INSTANCE(WSerialT)
503-- /Pre-release/
474-- /Pre-release/
504--
475--
505{-# INLINE unfoldrM #-}
476{-# INLINE unfoldrM #-}
506−unfoldrM :: (IsStream t, Monad m) => (b -> m (Maybe (a, b))) -> b -> t m a
477+unfoldrM :: Monad m => (b -> m (Maybe (a, b))) -> b -> SerialT m a
507−unfoldrM step seed = D.fromStreamD (D.unfoldrM step seed)
478+unfoldrM step seed = SerialT $ D.toStreamK (D.unfoldrM step seed)
src/Streamly/Internal/Data/Stream/StreamD/Eliminate.hs−13
@@ -228,19 +228,6 @@ parse_ (PRD.Parser pstep initial extract) stream@(Stream step state) = do
228-- Specialized Folds
228-- Specialized Folds
229------------------------------------------------------------------------------
229------------------------------------------------------------------------------
230
230
231−-- | Run a streaming composition, discard the results.
232−{-# INLINE_LATE drain #-}
233−drain :: Monad m => Stream m a -> m ()
234−-- drain = foldrM (\_ xs -> xs) (return ())
235−drain (Stream step state) = go SPEC state
236− where
237− go !_ st = do
238− r <- step defState st
239− case r of
240− Yield _ s -> go SPEC s
241− Skip s -> go SPEC s
242− Stop -> return ()
243−
244{-# INLINE_NORMAL null #-}
231{-# INLINE_NORMAL null #-}
245null :: Monad m => Stream m a -> m Bool
232null :: Monad m => Stream m a -> m Bool
246null = foldrM (\_ _ -> return False) (return True)
233null = foldrM (\_ _ -> return False) (return True)
src/Streamly/Internal/Data/Stream/StreamD/Generate.hs−2
@@ -82,8 +82,6 @@ module Streamly.Internal.Data.Stream.StreamD.Generate
82 -- * Conversions
82 -- * Conversions
83 , fromStreamK
83 , fromStreamK
84 , toStreamK
84 , toStreamK
85− , fromStreamD
86− , toStreamD
87 )
85 )
88where
86where
89
87
src/Streamly/Internal/Data/Stream/StreamD/Transform.hs+3−13
@@ -99,7 +99,7 @@ module Streamly.Internal.Data.Stream.StreamD.Transform
99 -- * Reordering
99 -- * Reordering
100 -- | Produce strictly the same set but reordered.
100 -- | Produce strictly the same set but reordered.
101 , reverse
101 , reverse
102− , reverse'
102+ -- , reverse'
103
103
104 -- * Position Indexing
104 -- * Position Indexing
105 , indexed
105 , indexed
@@ -129,7 +129,6 @@ import Control.Monad.IO.Class (MonadIO(..))
129import Control.Monad.Trans.Class (MonadTrans(lift))
129import Control.Monad.Trans.Class (MonadTrans(lift))
130import Data.IORef (newIORef, mkWeakIORef)
130import Data.IORef (newIORef, mkWeakIORef)
131import Data.Maybe (fromJust, isJust)
131import Data.Maybe (fromJust, isJust)
132−import Foreign.Storable (Storable(..))
133import GHC.Types (SPEC(..))
132import GHC.Types (SPEC(..))
134import qualified Control.Monad.Catch as MC
133import qualified Control.Monad.Catch as MC
135
134
@@ -140,13 +139,10 @@ import Streamly.Internal.Data.SVar.Type (defState, adaptState)
140import Streamly.Internal.Data.Time.Clock (Clock(Monotonic), getTime)
139import Streamly.Internal.Data.Time.Clock (Clock(Monotonic), getTime)
141import Streamly.Internal.Data.Time.Units
140import Streamly.Internal.Data.Time.Units
142 (TimeUnit64, toRelTime64, diffAbsTime64)
141 (TimeUnit64, toRelTime64, diffAbsTime64)
143−import Streamly.Internal.System.IO (defaultChunkSize)
144
142
145−import qualified Streamly.Internal.Data.Array.Foreign.Type as A
146import qualified Streamly.Internal.Data.Fold.Type as FL
143import qualified Streamly.Internal.Data.Fold.Type as FL
147import qualified Streamly.Internal.Data.IORef.Prim as Prim
144import qualified Streamly.Internal.Data.IORef.Prim as Prim
148import qualified Streamly.Internal.Data.Pipe.Type as Pipe
145import qualified Streamly.Internal.Data.Pipe.Type as Pipe
149−import qualified Streamly.Internal.Data.Stream.StreamK as K
150
146
151import Prelude hiding
147import Prelude hiding
152 ( drop, dropWhile, filter, map, mapM, reverse
148 ( drop, dropWhile, filter, map, mapM, reverse
@@ -1100,12 +1096,12 @@ reverse m = Stream step Nothing
1100 step _ (Just []) = return Stop
1096 step _ (Just []) = return Stop
1101
1097
1102-- Much faster reverse for Storables
1098-- Much faster reverse for Storables
1099+{-
1103{-# INLINE_NORMAL reverse' #-}
1100{-# INLINE_NORMAL reverse' #-}
1104reverse' :: forall m a. (MonadIO m, Storable a) => Stream m a -> Stream m a
1101reverse' :: forall m a. (MonadIO m, Storable a) => Stream m a -> Stream m a
1105−{-
1106-- This commented implementation copies the whole stream into one single array
1102-- This commented implementation copies the whole stream into one single array
1107-- and then streams from that array, this has exactly the same performance as
1103-- and then streams from that array, this has exactly the same performance as
1108−-- the chunked code that follows. Though this could be problematic due to
1104+-- the chunked code in IsStream.Common.reverse' . Though this could be problematic due to
1109-- unbounded large allocations. However, if we use an idiomatic implementation
1105-- unbounded large allocations. However, if we use an idiomatic implementation
1110-- of arraysOf instead of the custom implementation then the chunked code
1106-- of arraysOf instead of the custom implementation then the chunked code
1111-- becomes worse by 6 times. Need to investigate if that can be improved.
1107-- becomes worse by 6 times. Need to investigate if that can be improved.
@@ -1130,12 +1126,6 @@ reverse' m = Stream step Nothing
1130 next = p `plusPtr` negate (sizeOf (undefined :: a))
1126 next = p `plusPtr` negate (sizeOf (undefined :: a))
1131 return $ Yield x (Just (start, next))
1127 return $ Yield x (Just (start, next))
1132-}
1128-}
1133−reverse' =
1134− A.flattenArraysRev -- unfoldMany A.readRev
1135− . fromStreamK
1136− . K.reverse
1137− . toStreamK
1138− . A.arraysOf defaultChunkSize
1139
1129
1140------------------------------------------------------------------------------
1130------------------------------------------------------------------------------
1141-- Position Indexing
1131-- Position Indexing
src/Streamly/Internal/Data/Stream/StreamD/Type.hs+21−13
@@ -39,8 +39,6 @@ module Streamly.Internal.Data.Stream.StreamD.Type
39 -- * Conversions From/To
39 -- * Conversions From/To
40 , fromStreamK
40 , fromStreamK
41 , toStreamK
41 , toStreamK
42− , toStreamD
43− , fromStreamD
44
42
45 -- * Running a 'Fold'
43 -- * Running a 'Fold'
46 , fold
44 , fold
@@ -59,6 +57,9 @@ module Streamly.Internal.Data.Stream.StreamD.Type
59 , foldlx'
57 , foldlx'
60 , foldlMx'
58 , foldlMx'
61
59
60+ -- * Special Folds
61+ , drain
62+
62 -- * To Containers
63 -- * To Containers
63 , toList
64 , toList
64
65
@@ -239,7 +240,7 @@ fromStreamK = Stream step
239toStreamK :: Monad m => Stream m a -> K.Stream m a
240toStreamK :: Monad m => Stream m a -> K.Stream m a
240toStreamK (Stream step state) = go state
241toStreamK (Stream step state) = go state
241 where
242 where
242− go st = K.mkStream $ \gst yld _ stp ->
243+ go st = K.MkStream $ \gst yld _ stp ->
243 let go' ss = do
244 let go' ss = do
244 r <- step gst ss
245 r <- step gst ss
245 case r of
246 case r of
@@ -255,16 +256,6 @@ toStreamK (Stream step state) = go state
255 forall s. fromStreamK (toStreamK s) = s #-}
256 forall s. fromStreamK (toStreamK s) = s #-}
256#endif
257#endif
257
258
258−-- XXX Rename to toStream or move to some IsStream common module
259−{-# INLINE fromStreamD #-}
260−fromStreamD :: (K.IsStream t, Monad m) => Stream m a -> t m a
261−fromStreamD = K.fromStream . toStreamK
262−
263−-- XXX Rename to toStream or move to some IsStream common module
264−{-# INLINE toStreamD #-}
265−toStreamD :: (K.IsStream t, Monad m) => t m a -> Stream m a
266−toStreamD = fromStreamK . K.toStream
267−
268------------------------------------------------------------------------------
259------------------------------------------------------------------------------
269-- Running a 'Fold'
260-- Running a 'Fold'
270------------------------------------------------------------------------------
261------------------------------------------------------------------------------
@@ -443,6 +434,23 @@ foldlM' fstep mbegin (Stream step state) = do
443foldl' :: Monad m => (b -> a -> b) -> b -> Stream m a -> m b
434foldl' :: Monad m => (b -> a -> b) -> b -> Stream m a -> m b
444foldl' fstep begin = foldlM' (\b a -> return (fstep b a)) (return begin)
435foldl' fstep begin = foldlM' (\b a -> return (fstep b a)) (return begin)
445
436
437+------------------------------------------------------------------------------
438+-- Special folds
439+------------------------------------------------------------------------------
440+
441+-- | Run a streaming composition, discard the results.
442+{-# INLINE_LATE drain #-}
443+drain :: Monad m => Stream m a -> m ()
444+-- drain = foldrM (\_ xs -> xs) (return ())
445+drain (Stream step state) = go SPEC state
446+ where
447+ go !_ st = do
448+ r <- step defState st
449+ case r of
450+ Yield _ s -> go SPEC s
451+ Skip s -> go SPEC s
452+ Stop -> return ()
453+
446------------------------------------------------------------------------------
454------------------------------------------------------------------------------
447-- To Containers
455-- To Containers
448------------------------------------------------------------------------------
456------------------------------------------------------------------------------
src/Streamly/Internal/Data/Stream/StreamK.hs+82−343
@@ -21,12 +21,8 @@
21--
21--
22module Streamly.Internal.Data.Stream.StreamK
22module Streamly.Internal.Data.Stream.StreamK
23 (
23 (
24− -- * A class for streams
25− IsStream (..)
26− , adapt
27−
28 -- * The stream type
24 -- * The stream type
29− , Stream(..)
25+ Stream(..)
30
26
31 -- * Construction Primitives
27 -- * Construction Primitives
32 , mkStream
28 , mkStream
@@ -65,15 +61,12 @@ module Streamly.Internal.Data.Stream.StreamK
65 , fromEffect
61 , fromEffect
66 , fromFoldable
62 , fromFoldable
67 , fromList
63 , fromList
68− , fromStreamK
69
64
70 -- * foldr/build
65 -- * foldr/build
71 , foldrS
66 , foldrS
72 , foldrSM
67 , foldrSM
73 , buildS
68 , buildS
74− , buildM
75 , augmentS
69 , augmentS
76− , augmentSM
77
70
78 -- * Elimination
71 -- * Elimination
79 -- ** General Folds
72 -- ** General Folds
@@ -116,7 +109,6 @@ module Streamly.Internal.Data.Stream.StreamK
116
109
117 -- ** Conversions
110 -- ** Conversions
118 , toList
111 , toList
119− , toStreamK
120 , hoist
112 , hoist
121
113
122 -- * Transformation
114 -- * Transformation
@@ -134,7 +126,6 @@ module Streamly.Internal.Data.Stream.StreamK
134 -- ** Mapping
126 -- ** Mapping
135 , map
127 , map
136 , mapM
128 , mapM
137− , mapMSerial
138 , sequence
129 , sequence
139
130
140 -- ** Inserting
131 -- ** Inserting
@@ -160,7 +151,7 @@ module Streamly.Internal.Data.Stream.StreamK
160 , mergeByM
151 , mergeByM
161
152
162 -- ** Nesting
153 -- ** Nesting
163− , concatMapBy
154+ , concatMapWith
164 , concatMap
155 , concatMap
165 , bindWith
156 , bindWith
166 , concatPairsWith
157 , concatPairsWith
@@ -176,24 +167,16 @@ module Streamly.Internal.Data.Stream.StreamK
176 , serial
167 , serial
177
168
178 -- * Utilities
169 -- * Utilities
179− , consMStream
170+ , consM
180 , withLocal
171 , withLocal
181 , mfix
172 , mfix
182−
183− -- * Deprecated
184− , Streaming -- deprecated
185− , once -- deprecated
186 )
173 )
187where
174where
188
175
189import Control.Monad.Trans.Class (MonadTrans(lift))
176import Control.Monad.Trans.Class (MonadTrans(lift))
190import Control.Monad (void, join)
177import Control.Monad (void, join)
191−import Control.Monad.Reader.Class (MonadReader(..))
192−import Data.Function (fix)
193−import Streamly.Internal.Control.Concurrent (MonadAsync)
194import Streamly.Internal.Data.SVar.Type (adaptState, defState)
178import Streamly.Internal.Data.SVar.Type (adaptState, defState)
195
179
196−import qualified Prelude
197import qualified Streamly.Internal.Data.Fold.Type as FL
180import qualified Streamly.Internal.Data.Fold.Type as FL
198
181
199import Prelude
182import Prelude
@@ -207,41 +190,13 @@ import Streamly.Internal.Data.Stream.StreamK.Type
207-- $setup
190-- $setup
208-- >>> :m
191-- >>> :m
209
192
210−-------------------------------------------------------------------------------
211−-- Deconstruction
212−-------------------------------------------------------------------------------
213−
214−{-# INLINE uncons #-}
215−uncons :: (IsStream t, Monad m) => t m a -> m (Maybe (a, t m a))
216−uncons m =
217− let stop = return Nothing
218− single a = return (Just (a, nil))
219− yieldk a r = return (Just (a, r))
220− in foldStream defState yieldk single stop m
221−
222-------------------------------------------------------------------------------
193-------------------------------------------------------------------------------
223-- Generation
194-- Generation
224-------------------------------------------------------------------------------
195-------------------------------------------------------------------------------
225
196
226−{-# INLINE unfoldr #-}
227−unfoldr :: IsStream t => (b -> Maybe (a, b)) -> b -> t m a
228−unfoldr next s0 = build $ \yld stp ->
229− let go s =
230− case next s of
231− Just (a, b) -> yld a (go b)
232− Nothing -> stp
233− in go s0
234−
235{-# INLINE unfoldrM #-}
197{-# INLINE unfoldrM #-}
236−unfoldrM :: (IsStream t, MonadAsync m) => (b -> m (Maybe (a, b))) -> b -> t m a
198+unfoldrM :: Monad m => (b -> m (Maybe (a, b))) -> b -> Stream m a
237−unfoldrM step = go
199+unfoldrM = unfoldrMWith consM
238− where
239− go s = sharedM $ \yld _ stp -> do
240− r <- step s
241− case r of
242− Just (a, b) -> yld a (go b)
243− Nothing -> stp
244−
245{-
200{-
246-- Generalization of concurrent streams/SVar via unfoldr.
201-- Generalization of concurrent streams/SVar via unfoldr.
247--
202--
@@ -255,7 +210,8 @@ unfoldrM step = go
255-- concurrent version could be async or ahead etc. Depending on how we queue
210-- concurrent version could be async or ahead etc. Depending on how we queue
256-- back the feedback portion b, it could be DFS or BFS style.
211-- back the feedback portion b, it could be DFS or BFS style.
257--
212--
258−unfoldrA :: (IsStream t, MonadAsync m) => (b -> Maybe (m a, b)) -> b -> t m a
213+unfoldrA :: (IsStream t, MonadAsync m) =>
214+ (b -> Maybe (m a, b)) -> b -> Stream m a
259unfoldrA = undefined
215unfoldrA = undefined
260-}
216-}
261
217
@@ -263,110 +219,58 @@ unfoldrA = undefined
263-- Special generation
219-- Special generation
264-------------------------------------------------------------------------------
220-------------------------------------------------------------------------------
265
221
266−-- | Same as fromEffect
267−--
268−-- @since 0.2.0
269−{-# DEPRECATED once "Please use fromEffect instead." #-}
270−{-# INLINE once #-}
271−once :: (Monad m, IsStream t) => m a -> t m a
222+repeatM :: Monad m => m a -> Stream m a
272−once = fromEffect
223+repeatM = repeatMWith consM
273−
274−-- |
275−-- @
276−-- repeatM = fix . cons
277−-- repeatM = cycle1 . fromPure
278−-- @
279−--
280−-- Generate an infinite stream by repeating a monadic value.
281−--
282−-- /Pre-release/
283−repeatM :: (IsStream t, MonadAsync m) => m a -> t m a
284−repeatM = go
285− where go m = m |: go m
286−
287−-- Generate an infinite stream by repeating a pure value.
288−--
289−-- /Pre-release/
290−{-# INLINE repeat #-}
291−repeat :: IsStream t => a -> t m a
292−repeat a = let x = cons a x in x
293
224
294{-# INLINE replicateM #-}
225{-# INLINE replicateM #-}
295−replicateM :: (IsStream t, MonadAsync m) => Int -> m a -> t m a
226+replicateM :: Monad m => Int -> m a -> Stream m a
296−replicateM n m = go n
227+replicateM = replicateMWith consM
297− where
298− go cnt = if cnt <= 0 then nil else m |: go (cnt - 1)
299−
300{-# INLINE replicate #-}
228{-# INLINE replicate #-}
301−replicate :: IsStream t => Int -> a -> t m a
229+replicate :: Int -> a -> Stream m a
302replicate n a = go n
230replicate n a = go n
303 where
231 where
304 go cnt = if cnt <= 0 then nil else a `cons` go (cnt - 1)
232 go cnt = if cnt <= 0 then nil else a `cons` go (cnt - 1)
305
233
306{-# INLINE fromIndicesM #-}
234{-# INLINE fromIndicesM #-}
307−fromIndicesM :: (IsStream t, MonadAsync m) => (Int -> m a) -> t m a
235+fromIndicesM :: Monad m => (Int -> m a) -> Stream m a
308−fromIndicesM gen = go 0
236+fromIndicesM = fromIndicesMWith consM
309− where
310− go i = mkStream $ \st stp sng yld -> do
311− foldStreamShared st stp sng yld (gen i |: go (i + 1))
312−
313{-# INLINE fromIndices #-}
237{-# INLINE fromIndices #-}
314−fromIndices :: IsStream t => (Int -> a) -> t m a
238+fromIndices :: (Int -> a) -> Stream m a
315fromIndices gen = go 0
239fromIndices gen = go 0
316 where
240 where
317 go n = gen n `cons` go (n + 1)
241 go n = gen n `cons` go (n + 1)
318
242
319{-# INLINE iterate #-}
243{-# INLINE iterate #-}
320−iterate :: IsStream t => (a -> a) -> a -> t m a
244+iterate :: (a -> a) -> a -> Stream m a
321iterate step = go
245iterate step = go
322 where
246 where
323 go !s = cons s (go (step s))
247 go !s = cons s (go (step s))
324
248
325{-# INLINE iterateM #-}
249{-# INLINE iterateM #-}
326−iterateM :: (IsStream t, MonadAsync m) => (a -> m a) -> m a -> t m a
250+iterateM :: Monad m => (a -> m a) -> m a -> Stream m a
327−iterateM step = go
251+iterateM = iterateMWith consM
328− where
329− go s = mkStream $ \st stp sng yld -> do
330− !next <- s
331− foldStreamShared st stp sng yld (return next |: go (step next))
332
252
333-------------------------------------------------------------------------------
253-------------------------------------------------------------------------------
334-- Conversions
254-- Conversions
335-------------------------------------------------------------------------------
255-------------------------------------------------------------------------------
336
256
337−-- |
338−-- @
339−-- fromFoldable = 'Prelude.foldr' 'cons' 'nil'
340−-- @
341−--
342−-- Construct a stream from a 'Foldable' containing pure values:
343−--
344−-- @since 0.2.0
345−{-# INLINE fromFoldable #-}
346−fromFoldable :: (IsStream t, Foldable f) => f a -> t m a
347−fromFoldable = Prelude.foldr cons nil
348−
349{-# INLINE fromList #-}
257{-# INLINE fromList #-}
350−fromList :: IsStream t => [a] -> t m a
258+fromList :: [a] -> Stream m a
351fromList = fromFoldable
259fromList = fromFoldable
352
260
353−{-# INLINE fromStreamK #-}
354−fromStreamK :: IsStream t => Stream m a -> t m a
355−fromStreamK = fromStream
356−
357-------------------------------------------------------------------------------
261-------------------------------------------------------------------------------
358-- Elimination by Folding
262-- Elimination by Folding
359-------------------------------------------------------------------------------
263-------------------------------------------------------------------------------
360
264
361-- | Lazy right associative fold.
265-- | Lazy right associative fold.
362{-# INLINE foldr #-}
266{-# INLINE foldr #-}
363−foldr :: (IsStream t, Monad m) => (a -> b -> b) -> b -> t m a -> m b
267+foldr :: Monad m => (a -> b -> b) -> b -> Stream m a -> m b
364foldr step acc = foldrM (\x xs -> xs >>= \b -> return (step x b)) (return acc)
268foldr step acc = foldrM (\x xs -> xs >>= \b -> return (step x b)) (return acc)
365
269
366-- | Right associative fold to an arbitrary transformer monad.
270-- | Right associative fold to an arbitrary transformer monad.
367{-# INLINE foldrT #-}
271{-# INLINE foldrT #-}
368−foldrT :: (IsStream t, Monad m, Monad (s m), MonadTrans s)
272+foldrT :: (Monad m, Monad (s m), MonadTrans s)
369− => (a -> s m b -> s m b) -> s m b -> t m a -> s m b
273+ => (a -> s m b -> s m b) -> s m b -> Stream m a -> s m b
370foldrT step final = go
274foldrT step final = go
371 where
275 where
372 go m1 = do
276 go m1 = do
@@ -376,7 +280,7 @@ foldrT step final = go
376 Nothing -> final
280 Nothing -> final
377
281
378{-# INLINE foldr1 #-}
282{-# INLINE foldr1 #-}
379−foldr1 :: (IsStream t, Monad m) => (a -> a -> a) -> t m a -> m (Maybe a)
283+foldr1 :: Monad m => (a -> a -> a) -> Stream m a -> m (Maybe a)
380foldr1 step m = do
284foldr1 step m = do
381 r <- uncons m
285 r <- uncons m
382 case r of
286 case r of
@@ -392,8 +296,8 @@ foldr1 step m = do
392-- XXX replace the recursive "go" with explicit continuations.
296-- XXX replace the recursive "go" with explicit continuations.
393-- | Like 'foldx', but with a monadic step function.
297-- | Like 'foldx', but with a monadic step function.
394{-# INLINABLE foldlMx' #-}
298{-# INLINABLE foldlMx' #-}
395−foldlMx' :: (IsStream t, Monad m)
299+foldlMx' :: Monad m
396− => (x -> a -> m x) -> m x -> (x -> m b) -> t m a -> m b
300+ => (x -> a -> m x) -> m x -> (x -> m b) -> Stream m a -> m b
397foldlMx' step begin done = go begin
301foldlMx' step begin done = go begin
398 where
302 where
399 go !acc m1 =
303 go !acc m1 =
@@ -403,7 +307,7 @@ foldlMx' step begin done = go begin
403 in foldStream defState yieldk single stop m1
307 in foldStream defState yieldk single stop m1
404
308
405{-# INLINABLE fold #-}
309{-# INLINABLE fold #-}
406−fold :: (IsStream t, Monad m) => FL.Fold m a b -> t m a -> m b
310+fold :: Monad m => FL.Fold m a b -> Stream m a -> m b
407fold (FL.Fold step begin done) m = do
311fold (FL.Fold step begin done) m = do
408 res <- begin
312 res <- begin
409 case res of
313 case res of
@@ -425,25 +329,13 @@ fold (FL.Fold step begin done) m = do
425
329
426-- | Like 'foldl'' but with a monadic step function.
330-- | Like 'foldl'' but with a monadic step function.
427{-# INLINE foldlM' #-}
331{-# INLINE foldlM' #-}
428−foldlM' :: (IsStream t, Monad m) => (b -> a -> m b) -> m b -> t m a -> m b
332+foldlM' :: Monad m => (b -> a -> m b) -> m b -> Stream m a -> m b
429foldlM' step begin = foldlMx' step begin return
333foldlM' step begin = foldlMx' step begin return
430
334
431−-- | Lazy left fold to a stream.
432−{-# INLINE foldlS #-}
433−foldlS :: IsStream t => (t m b -> a -> t m b) -> t m b -> t m a -> t m b
434−foldlS step = go
435− where
436− go acc rest = mkStream $ \st yld sng stp ->
437− let run x = foldStream st yld sng stp x
438− stop = run acc
439− single a = run $ step acc a
440− yieldk a r = run $ go (step acc a) r
441− in foldStream (adaptState st) yieldk single stop rest
442−
443-- | Lazy left fold to an arbitrary transformer monad.
335-- | Lazy left fold to an arbitrary transformer monad.
444{-# INLINE foldlT #-}
336{-# INLINE foldlT #-}
445−foldlT :: (IsStream t, Monad m, Monad (s m), MonadTrans s)
337+foldlT :: (Monad m, Monad (s m), MonadTrans s)
446− => (s m b -> a -> s m b) -> s m b -> t m a -> s m b
338+ => (s m b -> a -> s m b) -> s m b -> Stream m a -> s m b
447foldlT step = go
339foldlT step = go
448 where
340 where
449 go acc m1 = do
341 go acc m1 = do
@@ -456,39 +348,8 @@ foldlT step = go
456-- Specialized folds
348-- Specialized folds
457------------------------------------------------------------------------------
349------------------------------------------------------------------------------
458
350
459−-- XXX use foldrM to implement folds where possible
460−-- XXX This (commented) definition of drain and mapM_ perform much better on
461−-- some benchmarks but worse on others. Need to investigate why, may there is
462−-- an optimization opportunity that we can exploit.
463−-- drain = foldrM (\_ xs -> return () >> xs) (return ())
464−
465−-- |
466−-- > drain = foldl' (\_ _ -> ()) ()
467−-- > drain = mapM_ (\_ -> return ())
468−{-# INLINE drain #-}
469−drain :: (Monad m, IsStream t) => t m a -> m ()
470−drain = foldrM (\_ xs -> xs) (return ())
471−{-
472−drain = go
473− where
474− go m1 =
475− let stop = return ()
476− single _ = return ()
477− yieldk _ r = go r
478− in foldStream defState yieldk single stop m1
479−-}
480−
481−{-# INLINE null #-}
482−null :: (IsStream t, Monad m) => t m a -> m Bool
483−-- null = foldrM (\_ _ -> return True) (return False)
484−null m =
485− let stop = return True
486− single _ = return False
487− yieldk _ _ = return False
488− in foldStream defState yieldk single stop m
489−
490{-# INLINE head #-}
351{-# INLINE head #-}
491−head :: (IsStream t, Monad m) => t m a -> m (Maybe a)
352+head :: Monad m => Stream m a -> m (Maybe a)
492-- head = foldrM (\x _ -> return $ Just x) (return Nothing)
353-- head = foldrM (\x _ -> return $ Just x) (return Nothing)
493head m =
354head m =
494 let stop = return Nothing
355 let stop = return Nothing
@@ -496,112 +357,8 @@ head m =
496 yieldk a _ = return (Just a)
357 yieldk a _ = return (Just a)
497 in foldStream defState yieldk single stop m
358 in foldStream defState yieldk single stop m
498
359
499−{-# INLINE tail #-}
500−tail :: (IsStream t, Monad m) => t m a -> m (Maybe (t m a))
501−tail m =
502− let stop = return Nothing
503− single _ = return $ Just nil
504− yieldk _ r = return $ Just r
505− in foldStream defState yieldk single stop m
506−
507−{-# INLINE headPartial #-}
508−headPartial :: (IsStream t, Monad m) => t m a -> m a
509−headPartial = foldrM (\x _ -> return x) (error "head of nil")
510−
511−{-# INLINE tailPartial #-}
512−tailPartial :: IsStream t => t m a -> t m a
513−tailPartial m = mkStream $ \st yld sng stp ->
514− let stop = error "tail of nil"
515− single _ = stp
516− yieldk _ r = foldStream st yld sng stp r
517− in foldStream st yieldk single stop m
518−
519−-- | We can define cyclic structures using @let@:
520−--
521−-- >>> let (a, b) = ([1, b], head a) in (a, b)
522−-- ([1,1],1)
523−--
524−-- The function @fix@ defined as:
525−--
526−-- > fix f = let x = f x in x
527−--
528−-- ensures that the argument of a function and its output refer to the same
529−-- lazy value @x@ i.e. the same location in memory. Thus @x@ can be defined
530−-- in terms of itself, creating structures with cyclic references.
531−--
532−-- >>> import Data.Function (fix)
533−-- >>> f ~(a, b) = ([1, b], head a)
534−-- >>> fix f
535−-- ([1,1],1)
536−--
537−-- 'Control.Monad.mfix' is essentially the same as @fix@ but for monadic
538−-- values.
539−--
540−-- Using 'mfix' for streams we can construct a stream in which each element of
541−-- the stream is defined in a cyclic fashion. The argument of the function
542−-- being fixed represents the current element of the stream which is being
543−-- returned by the stream monad. Thus, we can use the argument to construct
544−-- itself.
545−--
546−-- In the following example, the argument @action@ of the function @f@
547−-- represents the tuple @(x,y)@ returned by it in a given iteration. We define
548−-- the first element of the tuple in terms of the second.
549−--
550−-- @
551−-- import Streamly.Internal.Data.Stream.IsStream as Stream
552−-- import System.IO.Unsafe (unsafeInterleaveIO)
553−--
554−-- main = do
555−-- Stream.mapM_ print $ Stream.mfix f
556−--
557−-- where
558−--
559−-- f action = do
560−-- let incr n act = fmap ((+n) . snd) $ unsafeInterleaveIO act
561−-- x <- Stream.fromListM [incr 1 action, incr 2 action]
562−-- y <- Stream.fromList [4,5]
563−-- return (x, y)
564−-- @
565−--
566−-- Note: you cannot achieve this by just changing the order of the monad
567−-- statements because that would change the order in which the stream elements
568−-- are generated.
569−--
570−-- Note that the function @f@ must be lazy in its argument, that's why we use
571−-- 'unsafeInterleaveIO' on @action@ because IO monad is strict.
572−--
573−-- /Pre-release/
574−
575−mfix :: (IsStream t, Monad m) => (m a -> t m a) -> t m a
576−mfix f = mkStream $ \st yld sng stp ->
577− let single a = foldStream st yld sng stp $ a `cons` ys
578− yieldk a _ = foldStream st yld sng stp $ a `cons` ys
579− in foldStream st yieldk single stp xs
580−
581− where
582−
583− -- fix the head element of the stream
584− xs = fix (f . headPartial)
585−
586− -- now fix the tail recursively
587− ys = mfix (tailPartial . f)
588−
589−{-# INLINE init #-}
590−init :: (IsStream t, Monad m) => t m a -> m (Maybe (t m a))
591−init = go1
592− where
593− go1 m1 = do
594− r <- uncons m1
595− case r of
596− Nothing -> return Nothing
597− Just (h, t) -> return . Just $ go h t
598− go p m1 = mkStream $ \_ yld sng stp ->
599− let single _ = sng p
600− yieldk a x = yld p $ go a x
601− in foldStream defState yieldk single stp m1
602−
603{-# INLINE elem #-}
360{-# INLINE elem #-}
604−elem :: (IsStream t, Monad m, Eq a) => a -> t m a -> m Bool
361+elem :: (Monad m, Eq a) => a -> Stream m a -> m Bool
605elem e = go
362elem e = go
606 where
363 where
607 go m1 =
364 go m1 =
@@ -611,7 +368,7 @@ elem e = go
611 in foldStream defState yieldk single stop m1
368 in foldStream defState yieldk single stop m1
612
369
613{-# INLINE notElem #-}
370{-# INLINE notElem #-}
614−notElem :: (IsStream t, Monad m, Eq a) => a -> t m a -> m Bool
371+notElem :: (Monad m, Eq a) => a -> Stream m a -> m Bool
615notElem e = go
372notElem e = go
616 where
373 where
617 go m1 =
374 go m1 =
@@ -621,7 +378,7 @@ notElem e = go
621 in foldStream defState yieldk single stop m1
378 in foldStream defState yieldk single stop m1
622
379
623{-# INLINABLE all #-}
380{-# INLINABLE all #-}
624−all :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> m Bool
381+all :: Monad m => (a -> Bool) -> Stream m a -> m Bool
625all p = go
382all p = go
626 where
383 where
627 go m1 =
384 go m1 =
@@ -632,7 +389,7 @@ all p = go
632 in foldStream defState yieldk single (return True) m1
389 in foldStream defState yieldk single (return True) m1
633
390
634{-# INLINABLE any #-}
391{-# INLINABLE any #-}
635−any :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> m Bool
392+any :: Monad m => (a -> Bool) -> Stream m a -> m Bool
636any p = go
393any p = go
637 where
394 where
638 go m1 =
395 go m1 =
@@ -644,11 +401,11 @@ any p = go
644
401
645-- | Extract the last element of the stream, if any.
402-- | Extract the last element of the stream, if any.
646{-# INLINE last #-}
403{-# INLINE last #-}
647−last :: (IsStream t, Monad m) => t m a -> m (Maybe a)
404+last :: Monad m => Stream m a -> m (Maybe a)
648last = foldlx' (\_ y -> Just y) Nothing id
405last = foldlx' (\_ y -> Just y) Nothing id
649
406
650{-# INLINE minimum #-}
407{-# INLINE minimum #-}
651−minimum :: (IsStream t, Monad m, Ord a) => t m a -> m (Maybe a)
408+minimum :: (Monad m, Ord a) => Stream m a -> m (Maybe a)
652minimum = go Nothing
409minimum = go Nothing
653 where
410 where
654 go Nothing m1 =
411 go Nothing m1 =
@@ -671,8 +428,8 @@ minimum = go Nothing
671
428
672{-# INLINE minimumBy #-}
429{-# INLINE minimumBy #-}
673minimumBy
430minimumBy
674− :: (IsStream t, Monad m)
431+ :: (Monad m)
675− => (a -> a -> Ordering) -> t m a -> m (Maybe a)
432+ => (a -> a -> Ordering) -> Stream m a -> m (Maybe a)
676minimumBy cmp = go Nothing
433minimumBy cmp = go Nothing
677 where
434 where
678 go Nothing m1 =
435 go Nothing m1 =
@@ -692,7 +449,7 @@ minimumBy cmp = go Nothing
692 in foldStream defState yieldk single stop m1
449 in foldStream defState yieldk single stop m1
693
450
694{-# INLINE maximum #-}
451{-# INLINE maximum #-}
695−maximum :: (IsStream t, Monad m, Ord a) => t m a -> m (Maybe a)
452+maximum :: (Monad m, Ord a) => Stream m a -> m (Maybe a)
696maximum = go Nothing
453maximum = go Nothing
697 where
454 where
698 go Nothing m1 =
455 go Nothing m1 =
@@ -714,7 +471,7 @@ maximum = go Nothing
714 in foldStream defState yieldk single stop m1
471 in foldStream defState yieldk single stop m1
715
472
716{-# INLINE maximumBy #-}
473{-# INLINE maximumBy #-}
717−maximumBy :: (IsStream t, Monad m) => (a -> a -> Ordering) -> t m a -> m (Maybe a)
474+maximumBy :: Monad m => (a -> a -> Ordering) -> Stream m a -> m (Maybe a)
718maximumBy cmp = go Nothing
475maximumBy cmp = go Nothing
719 where
476 where
720 go Nothing m1 =
477 go Nothing m1 =
@@ -734,7 +491,7 @@ maximumBy cmp = go Nothing
734 in foldStream defState yieldk single stop m1
491 in foldStream defState yieldk single stop m1
735
492
736{-# INLINE (!!) #-}
493{-# INLINE (!!) #-}
737−(!!) :: (IsStream t, Monad m) => t m a -> Int -> m (Maybe a)
494+(!!) :: Monad m => Stream m a -> Int -> m (Maybe a)
738m !! i = go i m
495m !! i = go i m
739 where
496 where
740 go n m1 =
497 go n m1 =
@@ -746,7 +503,7 @@ m !! i = go i m
746 in foldStream defState yieldk single (return Nothing) m1
503 in foldStream defState yieldk single (return Nothing) m1
747
504
748{-# INLINE lookup #-}
505{-# INLINE lookup #-}
749−lookup :: (IsStream t, Monad m, Eq a) => a -> t m (a, b) -> m (Maybe b)
506+lookup :: (Monad m, Eq a) => a -> Stream m (a, b) -> m (Maybe b)
750lookup e = go
507lookup e = go
751 where
508 where
752 go m1 =
509 go m1 =
@@ -757,7 +514,7 @@ lookup e = go
757 in foldStream defState yieldk single (return Nothing) m1
514 in foldStream defState yieldk single (return Nothing) m1
758
515
759{-# INLINE findM #-}
516{-# INLINE findM #-}
760−findM :: (IsStream t, Monad m) => (a -> m Bool) -> t m a -> m (Maybe a)
517+findM :: Monad m => (a -> m Bool) -> Stream m a -> m (Maybe a)
761findM p = go
518findM p = go
762 where
519 where
763 go m1 =
520 go m1 =
@@ -770,11 +527,11 @@ findM p = go
770 in foldStream defState yieldk single (return Nothing) m1
527 in foldStream defState yieldk single (return Nothing) m1
771
528
772{-# INLINE find #-}
529{-# INLINE find #-}
773−find :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> m (Maybe a)
530+find :: Monad m => (a -> Bool) -> Stream m a -> m (Maybe a)
774find p = findM (return . p)
531find p = findM (return . p)
775
532
776{-# INLINE findIndices #-}
533{-# INLINE findIndices #-}
777−findIndices :: IsStream t => (a -> Bool) -> t m a -> t m Int
534+findIndices :: (a -> Bool) -> Stream m a -> Stream m Int
778findIndices p = go 0
535findIndices p = go 0
779 where
536 where
780 go offset m1 = mkStream $ \st yld sng stp ->
537 go offset m1 = mkStream $ \st yld sng stp ->
@@ -792,7 +549,7 @@ findIndices p = go 0
792-- | Apply a monadic action to each element of the stream and discard the
549-- | Apply a monadic action to each element of the stream and discard the
793-- output of the action.
550-- output of the action.
794{-# INLINE mapM_ #-}
551{-# INLINE mapM_ #-}
795−mapM_ :: (IsStream t, Monad m) => (a -> m b) -> t m a -> m ()
552+mapM_ :: Monad m => (a -> m b) -> Stream m a -> m ()
796mapM_ f = go
553mapM_ f = go
797 where
554 where
798 go m1 =
555 go m1 =
@@ -801,22 +558,22 @@ mapM_ f = go
801 yieldk a r = f a >> go r
558 yieldk a r = f a >> go r
802 in foldStream defState yieldk single stop m1
559 in foldStream defState yieldk single stop m1
803
560
561+{-# INLINE mapM #-}
562+mapM :: Monad m => (a -> m b) -> Stream m a -> Stream m b
563+mapM = mapMWith consM
564+
804------------------------------------------------------------------------------
565------------------------------------------------------------------------------
805-- Converting folds
566-- Converting folds
806------------------------------------------------------------------------------
567------------------------------------------------------------------------------
807
568
808{-# INLINABLE toList #-}
569{-# INLINABLE toList #-}
809−toList :: (IsStream t, Monad m) => t m a -> m [a]
570+toList :: Monad m => Stream m a -> m [a]
810toList = foldr (:) []
571toList = foldr (:) []
811
572
812−{-# INLINE toStreamK #-}
813−toStreamK :: Stream m a -> Stream m a
814−toStreamK = id
815−
816-- Based on suggestions by David Feuer and Pranay Sashank
573-- Based on suggestions by David Feuer and Pranay Sashank
817{-# INLINE hoist #-}
574{-# INLINE hoist #-}
818−hoist :: (IsStream t, Monad m, Monad n)
575+hoist :: (Monad m, Monad n)
819− => (forall x. m x -> n x) -> t m a -> t n a
576+ => (forall x. m x -> n x) -> Stream m a -> Stream n a
820hoist f str =
577hoist f str =
821 mkStream $ \st yld sng stp ->
578 mkStream $ \st yld sng stp ->
822 let single = return . sng
579 let single = return . sng
@@ -830,7 +587,7 @@ hoist f str =
830-------------------------------------------------------------------------------
587-------------------------------------------------------------------------------
831
588
832{-# INLINE scanlx' #-}
589{-# INLINE scanlx' #-}
833−scanlx' :: IsStream t => (x -> a -> x) -> x -> (x -> b) -> t m a -> t m b
590+scanlx' :: (x -> a -> x) -> x -> (x -> b) -> Stream m a -> Stream m b
834scanlx' step begin done m =
591scanlx' step begin done m =
835 cons (done begin) $ go m begin
592 cons (done begin) $ go m begin
836 where
593 where
@@ -842,7 +599,7 @@ scanlx' step begin done m =
842 in foldStream (adaptState st) yieldk single stp m1
599 in foldStream (adaptState st) yieldk single stp m1
843
600
844{-# INLINE scanl' #-}
601{-# INLINE scanl' #-}
845−scanl' :: IsStream t => (b -> a -> b) -> b -> t m a -> t m b
602+scanl' :: (b -> a -> b) -> b -> Stream m a -> Stream m b
846scanl' step begin = scanlx' step begin id
603scanl' step begin = scanlx' step begin id
847
604
848-------------------------------------------------------------------------------
605-------------------------------------------------------------------------------
@@ -850,7 +607,7 @@ scanl' step begin = scanlx' step begin id
850-------------------------------------------------------------------------------
607-------------------------------------------------------------------------------
851
608
852{-# INLINE filter #-}
609{-# INLINE filter #-}
853−filter :: IsStream t => (a -> Bool) -> t m a -> t m a
610+filter :: (a -> Bool) -> Stream m a -> Stream m a
854filter p = go
611filter p = go
855 where
612 where
856 go m1 = mkStream $ \st yld sng stp ->
613 go m1 = mkStream $ \st yld sng stp ->
@@ -861,7 +618,7 @@ filter p = go
861 in foldStream st yieldk single stp m1
618 in foldStream st yieldk single stp m1
862
619
863{-# INLINE take #-}
620{-# INLINE take #-}
864−take :: IsStream t => Int -> t m a -> t m a
621+take :: Int -> Stream m a -> Stream m a
865take = go
622take = go
866 where
623 where
867 go n1 m1 = mkStream $ \st yld sng stp ->
624 go n1 m1 = mkStream $ \st yld sng stp ->
@@ -871,7 +628,7 @@ take = go
871 else foldStream st yieldk sng stp m1
628 else foldStream st yieldk sng stp m1
872
629
873{-# INLINE takeWhile #-}
630{-# INLINE takeWhile #-}
874−takeWhile :: IsStream t => (a -> Bool) -> t m a -> t m a
631+takeWhile :: (a -> Bool) -> Stream m a -> Stream m a
875takeWhile p = go
632takeWhile p = go
876 where
633 where
877 go m1 = mkStream $ \st yld sng stp ->
634 go m1 = mkStream $ \st yld sng stp ->
@@ -882,8 +639,8 @@ takeWhile p = go
882 in foldStream st yieldk single stp m1
639 in foldStream st yieldk single stp m1
883
640
884{-# INLINE drop #-}
641{-# INLINE drop #-}
885−drop :: IsStream t => Int -> t m a -> t m a
642+drop :: Int -> Stream m a -> Stream m a
886−drop n m = fromStream $ unShare (go n (toStream m))
643+drop n m = unShare (go n m)
887 where
644 where
888 go n1 m1 = mkStream $ \st yld sng stp ->
645 go n1 m1 = mkStream $ \st yld sng stp ->
889 let single _ = stp
646 let single _ = stp
@@ -894,7 +651,7 @@ drop n m = fromStream $ unShare (go n (toStream m))
894 else foldStreamShared st yieldk single stp m1
651 else foldStreamShared st yieldk single stp m1
895
652
896{-# INLINE dropWhile #-}
653{-# INLINE dropWhile #-}
897−dropWhile :: IsStream t => (a -> Bool) -> t m a -> t m a
654+dropWhile :: (a -> Bool) -> Stream m a -> Stream m a
898dropWhile p = go
655dropWhile p = go
899 where
656 where
900 go m1 = mkStream $ \st yld sng stp ->
657 go m1 = mkStream $ \st yld sng stp ->
@@ -911,12 +668,12 @@ dropWhile p = go
911-- Be careful when modifying this, this uses a consM (|:) deliberately to allow
668-- Be careful when modifying this, this uses a consM (|:) deliberately to allow
912-- other stream types to overload it.
669-- other stream types to overload it.
913{-# INLINE sequence #-}
670{-# INLINE sequence #-}
914−sequence :: (IsStream t, MonadAsync m) => t m (m a) -> t m a
671+sequence :: Monad m => Stream m (m a) -> Stream m a
915sequence = go
672sequence = go
916 where
673 where
917 go m1 = mkStream $ \st yld sng stp ->
674 go m1 = mkStream $ \st yld sng stp ->
918 let single ma = ma >>= sng
675 let single ma = ma >>= sng
919− yieldk ma r = foldStreamShared st yld sng stp $ ma |: go r
676+ yieldk ma r = foldStreamShared st yld sng stp $ ma `consM` go r
920 in foldStream (adaptState st) yieldk single stp m1
677 in foldStream (adaptState st) yieldk single stp m1
921
678
922-------------------------------------------------------------------------------
679-------------------------------------------------------------------------------
@@ -924,23 +681,26 @@ sequence = go
924-------------------------------------------------------------------------------
681-------------------------------------------------------------------------------
925
682
926{-# INLINE intersperseM #-}
683{-# INLINE intersperseM #-}
927−intersperseM :: (IsStream t, MonadAsync m) => m a -> t m a -> t m a
684+intersperseM :: Monad m => m a -> Stream m a -> Stream m a
928intersperseM a = prependingStart
685intersperseM a = prependingStart
929 where
686 where
930 prependingStart m1 = mkStream $ \st yld sng stp ->
687 prependingStart m1 = mkStream $ \st yld sng stp ->
688+ let yieldk i x =
931− let yieldk i x = foldStreamShared st yld sng stp $ return i |: go x
689+ foldStreamShared st yld sng stp $ return i `consM` go x
932 in foldStream st yieldk sng stp m1
690 in foldStream st yieldk sng stp m1
933 go m2 = mkStream $ \st yld sng stp ->
691 go m2 = mkStream $ \st yld sng stp ->
934− let single i = foldStreamShared st yld sng stp $ a |: fromPure i
692+ let single i = foldStreamShared st yld sng stp $ a `consM` fromPure i
693+ yieldk i x =
694+ foldStreamShared
935− yieldk i x = foldStreamShared st yld sng stp $ a |: return i |: go x
695+ st yld sng stp $ a `consM` return i `consM` go x
936 in foldStream st yieldk single stp m2
696 in foldStream st yieldk single stp m2
937
697
938{-# INLINE intersperse #-}
698{-# INLINE intersperse #-}
939−intersperse :: (IsStream t, MonadAsync m) => a -> t m a -> t m a
699+intersperse :: Monad m => a -> Stream m a -> Stream m a
940intersperse a = intersperseM (return a)
700intersperse a = intersperseM (return a)
941
701
942{-# INLINE insertBy #-}
702{-# INLINE insertBy #-}
943−insertBy :: IsStream t => (a -> a -> Ordering) -> a -> t m a -> t m a
703+insertBy :: (a -> a -> Ordering) -> a -> Stream m a -> Stream m a
944insertBy cmp x = go
704insertBy cmp x = go
945 where
705 where
946 go m1 = mkStream $ \st yld _ _ ->
706 go m1 = mkStream $ \st yld _ _ ->
@@ -958,7 +718,7 @@ insertBy cmp x = go
958------------------------------------------------------------------------------
718------------------------------------------------------------------------------
959
719
960{-# INLINE deleteBy #-}
720{-# INLINE deleteBy #-}
961−deleteBy :: IsStream t => (a -> a -> Bool) -> a -> t m a -> t m a
721+deleteBy :: (a -> a -> Bool) -> a -> Stream m a -> Stream m a
962deleteBy eq x = go
722deleteBy eq x = go
963 where
723 where
964 go m1 = mkStream $ \st yld sng stp ->
724 go m1 = mkStream $ \st yld sng stp ->
@@ -968,20 +728,12 @@ deleteBy eq x = go
968 else yld a (go r)
728 else yld a (go r)
969 in foldStream st yieldk single stp m1
729 in foldStream st yieldk single stp m1
970
730
971−------------------------------------------------------------------------------
972−-- Reordering
973−------------------------------------------------------------------------------
974−
975−{-# INLINE reverse #-}
976−reverse :: IsStream t => t m a -> t m a
977−reverse = foldlS (flip cons) nil
978−
979-------------------------------------------------------------------------------
731-------------------------------------------------------------------------------
980-- Map and Filter
732-- Map and Filter
981-------------------------------------------------------------------------------
733-------------------------------------------------------------------------------
982
734
983{-# INLINE mapMaybe #-}
735{-# INLINE mapMaybe #-}
984−mapMaybe :: IsStream t => (a -> Maybe b) -> t m a -> t m b
736+mapMaybe :: (a -> Maybe b) -> Stream m a -> Stream m b
985mapMaybe f = go
737mapMaybe f = go
986 where
738 where
987 go m1 = mkStream $ \st yld sng stp ->
739 go m1 = mkStream $ \st yld sng stp ->
@@ -999,7 +751,7 @@ mapMaybe f = go
999--
751--
1000-- @since 0.1.0
752-- @since 0.1.0
1001{-# INLINABLE zipWith #-}
753{-# INLINABLE zipWith #-}
1002−zipWith :: IsStream t => (a -> b -> c) -> t m a -> t m b -> t m c
754+zipWith :: (a -> b -> c) -> Stream m a -> Stream m b -> Stream m c
1003zipWith f = go
755zipWith f = go
1004 where
756 where
1005 go mx my = mkStream $ \st yld sng stp -> do
757 go mx my = mkStream $ \st yld sng stp -> do
@@ -1015,7 +767,8 @@ zipWith f = go
1015--
767--
1016-- @since 0.1.0
768-- @since 0.1.0
1017{-# INLINABLE zipWithM #-}
769{-# INLINABLE zipWithM #-}
1018−zipWithM :: (IsStream t, Monad m) => (a -> b -> m c) -> t m a -> t m b -> t m c
770+zipWithM :: Monad m =>
771+ (a -> b -> m c) -> Stream m a -> Stream m b -> Stream m c
1019zipWithM f = go
772zipWithM f = go
1020 where
773 where
1021 go mx my = mkStream $ \st yld sng stp -> do
774 go mx my = mkStream $ \st yld sng stp -> do
@@ -1033,9 +786,8 @@ zipWithM f = go
1033------------------------------------------------------------------------------
786------------------------------------------------------------------------------
1034
787
1035{-# INLINE mergeByM #-}
788{-# INLINE mergeByM #-}
1036−mergeByM
789+mergeByM :: Monad m =>
1037− :: (IsStream t, Monad m)
1038− => (a -> a -> m Ordering) -> t m a -> t m a -> t m a
790+ (a -> a -> m Ordering) -> Stream m a -> Stream m a -> Stream m a
1039mergeByM cmp = go
791mergeByM cmp = go
1040 where
792 where
1041 go mx my = mkStream $ \st yld sng stp -> do
793 go mx my = mkStream $ \st yld sng stp -> do
@@ -1058,9 +810,8 @@ mergeByM cmp = go
1058 foldStream st yieldX singleX stopX mx
810 foldStream st yieldX singleX stopX mx
1059
811
1060{-# INLINABLE mergeBy #-}
812{-# INLINABLE mergeBy #-}
1061−mergeBy
813+mergeBy :: Monad m =>
1062− :: (IsStream t, Monad m)
1063− => (a -> a -> Ordering) -> t m a -> t m a -> t m a
814+ (a -> a -> Ordering) -> Stream m a -> Stream m a -> Stream m a
1064mergeBy cmp = mergeByM (\a b -> return $ cmp a b)
815mergeBy cmp = mergeByM (\a b -> return $ cmp a b)
1065
816
1066------------------------------------------------------------------------------
817------------------------------------------------------------------------------
@@ -1068,7 +819,7 @@ mergeBy cmp = mergeByM (\a b -> return $ cmp a b)
1068------------------------------------------------------------------------------
819------------------------------------------------------------------------------
1069
820
1070{-# INLINE the #-}
821{-# INLINE the #-}
1071−the :: (Eq a, IsStream t, Monad m) => t m a -> m (Maybe a)
822+the :: (Eq a, Monad m) => Stream m a -> m (Maybe a)
1072the m = do
823the m = do
1073 r <- uncons m
824 r <- uncons m
1074 case r of
825 case r of
@@ -1091,18 +842,6 @@ _alt m1 m2 = mkStream $ \st yld sng stp ->
1091 let stop = foldStream st yld sng stp m2
842 let stop = foldStream st yld sng stp m2
1092 in foldStream st yld sng stop m1
843 in foldStream st yld sng stop m1
1093
844
1094−------------------------------------------------------------------------------
1095−-- MonadReader
1096−------------------------------------------------------------------------------
1097−
1098−{-# INLINABLE withLocal #-}
1099−withLocal :: MonadReader r m => (r -> r) -> Stream m a -> Stream m a
1100−withLocal f m =
1101− mkStream $ \st yld sng stp ->
1102− let single = local f . sng
1103− yieldk a r = local f $ yld a (withLocal f r)
1104− in foldStream st yieldk single (local f stp) m
1105−
1106------------------------------------------------------------------------------
845------------------------------------------------------------------------------
1107-- MonadError
846-- MonadError
1108------------------------------------------------------------------------------
847------------------------------------------------------------------------------
src/Streamly/Internal/Data/Stream/StreamK/Type.hs+479−371
@@ -17,26 +17,15 @@
17--
17--
18module Streamly.Internal.Data.Stream.StreamK.Type
18module Streamly.Internal.Data.Stream.StreamK.Type
19 (
19 (
20− -- * A class for streams
21− IsStream (..)
22− , adapt
23−
24 -- * The stream type
20 -- * The stream type
25− , Stream (..)
21+ Stream (..)
22+ , toStreamK
23+ , fromStreamK
26
24
27− -- * Construction
25+ -- * foldr/build
28 , mkStream
26 , mkStream
29− , fromStopK
30− , fromYieldK
31− , consK
32−
33− -- * Elimination
34 , foldStream
27 , foldStream
35 , foldStreamShared
28 , foldStreamShared
36− , foldl'
37− , foldlx'
38−
39− -- * foldr/build
40 , foldrM
29 , foldrM
41 , foldrS
30 , foldrS
42 , foldrSShared
31 , foldrSShared
@@ -45,27 +34,51 @@ module Streamly.Internal.Data.Stream.StreamK.Type
45 , buildS
34 , buildS
46 , buildM
35 , buildM
47 , buildSM
36 , buildSM
48− , sharedM
49 , augmentS
37 , augmentS
50 , augmentSM
38 , augmentSM
51
39
52− -- instances
40+ -- * Construction
41+ , fromStopK
42+ , fromYieldK
43+ , consK
53 , cons
44 , cons
54 , (.:)
45 , (.:)
55− , consMStream
46+ , consM
56 , consMBy
47 , consMBy
48+ , nil
49+ , nilM
50+
51+ -- * Generation
57 , fromEffect
52 , fromEffect
58 , fromPure
53 , fromPure
54+ , unfoldr
55+ , unfoldrMWith
56+ , repeat
57+ , repeatMWith
58+ , replicateMWith
59+ , fromIndicesMWith
60+ , iterateMWith
61+ , fromFoldable
62+ , fromFoldableM
63+ , mfix
59
64
60− , nil
65+ -- * Elimination
61− , nilM
66+ , uncons
67+ , foldl'
68+ , foldlx'
69+ , drain
70+ , null
71+ , tail
72+ , init
73+
74+ -- * Transformation
62 , conjoin
75 , conjoin
63 , serial
76 , serial
64 , map
77 , map
65− , mapM
78+ , mapMWith
66 , mapMSerial
79 , mapMSerial
67 , unShare
80 , unShare
68− , concatMapBy
81+ , concatMapWith
69 , concatMap
82 , concatMap
70 , bindWith
83 , bindWith
71 , concatPairsWith
84 , concatPairsWith
@@ -73,23 +86,25 @@ module Streamly.Internal.Data.Stream.StreamK.Type
73 , apSerial
86 , apSerial
74 , apSerialDiscardFst
87 , apSerialDiscardFst
75 , apSerialDiscardSnd
88 , apSerialDiscardSnd
89+ , foldlS
90+ , reverse
76
91
77− , Streaming -- deprecated
92+ -- * Reader
93+ , withLocal
78 )
94 )
79where
95where
80
96
81import Control.Monad (ap, (>=>))
97import Control.Monad (ap, (>=>))
98+import Control.Monad.Reader.Class (MonadReader(..))
82import Control.Monad.Trans.Class (MonadTrans(lift))
99import Control.Monad.Trans.Class (MonadTrans(lift))
83−import Data.Kind (Type)
100+import Data.Function (fix)
84−#if __GLASGOW_HASKELL__ < 808
101+#if __GLASGOW_HASKELL__ < 804
85import Data.Semigroup (Semigroup(..))
102import Data.Semigroup (Semigroup(..))
86#endif
103#endif
87−import Streamly.Internal.Control.Concurrent (MonadAsync)
88import Streamly.Internal.Data.SVar.Type (State, adaptState, defState)
104import Streamly.Internal.Data.SVar.Type (State, adaptState, defState)
89−import Prelude hiding (map, mapM, concatMap, foldr)
105+import Prelude hiding
90−
106+ (map, mapM, concatMap, foldr, repeat, null, reverse, tail, init)
91−-- $setup
107+import qualified Prelude
92−-- >>> import Streamly.Prelude as Stream
93
108
94------------------------------------------------------------------------------
109------------------------------------------------------------------------------
95-- Basic stream type
110-- Basic stream type
@@ -124,140 +139,22 @@ newtype Stream m a =
124 -> m r
139 -> m r
125 )
140 )
126
141
127−------------------------------------------------------------------------------
142+{-# INLINE fromStreamK #-}
128−-- Types that can behave as a Stream
143+fromStreamK :: Stream m a -> Stream m a
129−------------------------------------------------------------------------------
144+fromStreamK = id
130−
131−infixr 5 `consM`
132−infixr 5 |:
133−
134−-- XXX Use a different SVar based on the stream type. But we need to make sure
135−-- that we do not lose performance due to polymorphism.
136−--
137−-- | Class of types that can represent a stream of elements of some type 'a' in
138−-- some monad 'm'.
139−--
140−-- /Since: 0.2.0 ("Streamly")/
141−--
142−-- @since 0.8.0
143−class
144−#if __GLASGOW_HASKELL__ >= 806
145− ( forall m a. MonadAsync m => Semigroup (t m a)
146− , forall m a. MonadAsync m => Monoid (t m a)
147− , forall m. Monad m => Functor (t m)
148− , forall m. MonadAsync m => Applicative (t m)
149− ) =>
150−#endif
151− IsStream t where
152− toStream :: t m a -> Stream m a
153− fromStream :: Stream m a -> t m a
154− -- | Constructs a stream by adding a monadic action at the head of an
155− -- existing stream. For example:
156− --
157− -- @
158− -- > toList $ getLine \`consM` getLine \`consM` nil
159− -- hello
160− -- world
161− -- ["hello","world"]
162− -- @
163− --
164− -- /Concurrent (do not use 'fromParallel' to construct infinite streams)/
165− --
166− -- @since 0.2.0
167− consM :: MonadAsync m => m a -> t m a -> t m a
168− -- | Operator equivalent of 'consM'. We can read it as "@parallel colon@"
169− -- to remember that @|@ comes before ':'.
170− --
171− -- @
172− -- > toList $ getLine |: getLine |: nil
173− -- hello
174− -- world
175− -- ["hello","world"]
176− -- @
177− --
178− -- @
179− -- let delay = threadDelay 1000000 >> print 1
180− -- drain $ fromSerial $ delay |: delay |: delay |: nil
181− -- drain $ fromParallel $ delay |: delay |: delay |: nil
182− -- @
183− --
184− -- /Concurrent (do not use 'fromParallel' to construct infinite streams)/
185− --
186− -- @since 0.2.0
187− (|:) :: MonadAsync m => m a -> t m a -> t m a
188− -- We can define (|:) just as 'consM' but it is defined explicitly for each
189− -- type because we want to use SPECIALIZE pragma on the definition.
190−
191−-- | Same as 'IsStream'.
192−--
193−-- @since 0.1.0
194−{-# DEPRECATED Streaming "Please use IsStream instead." #-}
195−type Streaming = IsStream
196−
197−-------------------------------------------------------------------------------
198−-- Type adapting combinators
199−-------------------------------------------------------------------------------
200−
201−-- XXX Move/reset the State here by reconstructing the stream with cleared
202−-- state. Can we make sure we do not do that when t1 = t2? If we do this then
203−-- we do not need to do that explicitly using svarStyle. It would act as
204−-- unShare when the stream type is the same.
205−--
206−-- | Adapt any specific stream type to any other specific stream type.
207−--
208−-- /Since: 0.1.0 ("Streamly")/
209−--
210−-- @since 0.8.0
211−adapt :: (IsStream t1, IsStream t2) => t1 m a -> t2 m a
212−adapt = fromStream . toStream
213−
214−------------------------------------------------------------------------------
215−-- Building a stream
216−------------------------------------------------------------------------------
217
145
218−-- XXX The State is always parameterized by "Stream" which means State is not
146+{-# INLINE toStreamK #-}
219−-- different for different stream types. So we have to manually make sure that
147+toStreamK :: Stream m a -> Stream m a
220−-- when converting from one stream to another we migrate the state correctly.
148+toStreamK = id
221−-- This can be fixed if we use a different SVar type for different streams.
222−-- Currently we always use "SVar Stream" and therefore a different State type
223−-- parameterized by that stream.
224−--
225−-- XXX Since t is coercible we should be able to coerce k
226−-- mkStream k = fromStream $ MkStream $ coerce k
227−--
228−-- | Build a stream from an 'SVar', a stop continuation, a singleton stream
229−-- continuation and a yield continuation.
230−{-# INLINE_EARLY mkStream #-}
231−mkStream :: IsStream t
232− => (forall r. State Stream m a
233− -> (a -> t m a -> m r)
234− -> (a -> m r)
235− -> m r
236− -> m r)
237− -> t m a
238−mkStream k = fromStream $ MkStream $ \st yld sng stp ->
239− let yieldk a r = yld a (toStream r)
240− in k st yieldk sng stp
241−
242−{-# RULES "mkStream from stream" mkStream = mkStreamFromStream #-}
243−mkStreamFromStream :: IsStream t
244− => (forall r. State Stream m a
245− -> (a -> Stream m a -> m r)
246− -> (a -> m r)
247− -> m r
248− -> m r)
249− -> t m a
250−mkStreamFromStream k = fromStream $ MkStream k
251
149
252−{-# RULES "mkStream stream" mkStream = mkStreamStream #-}
150+mkStream
253−mkStreamStream
254 :: (forall r. State Stream m a
151 :: (forall r. State Stream m a
255 -> (a -> Stream m a -> m r)
152 -> (a -> Stream m a -> m r)
256 -> (a -> m r)
153 -> (a -> m r)
257 -> m r
154 -> m r
258 -> m r)
155 -> m r)
259 -> Stream m a
156 -> Stream m a
260−mkStreamStream = MkStream
157+mkStream = MkStream
261
158
262-- | A terminal function that has no continuation to follow.
159-- | A terminal function that has no continuation to follow.
263type StopK m = forall r. m r -> m r
160type StopK m = forall r. m r -> m r
@@ -272,17 +169,17 @@ _wrapM :: Monad m => m a -> YieldK m a
272_wrapM m = (m >>=)
169_wrapM m = (m >>=)
273
170
274-- | Make an empty stream from a stop function.
171-- | Make an empty stream from a stop function.
275−fromStopK :: IsStream t => StopK m -> t m a
172+fromStopK :: StopK m -> Stream m a
276fromStopK k = mkStream $ \_ _ _ stp -> k stp
173fromStopK k = mkStream $ \_ _ _ stp -> k stp
277
174
278-- | Make a singleton stream from a callback function. The callback function
175-- | Make a singleton stream from a callback function. The callback function
279-- calls the one-shot yield continuation to yield an element.
176-- calls the one-shot yield continuation to yield an element.
280−fromYieldK :: IsStream t => YieldK m a -> t m a
177+fromYieldK :: YieldK m a -> Stream m a
281fromYieldK k = mkStream $ \_ _ sng _ -> k sng
178fromYieldK k = mkStream $ \_ _ sng _ -> k sng
282
179
283-- | Add a yield function at the head of the stream.
180-- | Add a yield function at the head of the stream.
284−consK :: IsStream t => YieldK m a -> t m a -> t m a
181+consK :: YieldK m a -> Stream m a -> Stream m a
285−consK k r = mkStream $ \_ yld _ _ -> k (`yld` r)
182+consK k r = mkStream $ \_ yld _ _ -> k (\x -> yld x r)
286
183
287-- XXX Build a stream from a repeating callback function.
184-- XXX Build a stream from a repeating callback function.
288
185
@@ -305,8 +202,8 @@ infixr 5 `cons`
305--
202--
306-- @since 0.1.0
203-- @since 0.1.0
307{-# INLINE_NORMAL cons #-}
204{-# INLINE_NORMAL cons #-}
308−cons :: IsStream t => a -> t m a -> t m a
205+cons :: a -> Stream m a -> Stream m a
309−cons a r = mkStream $ \_ yld _ _ -> yld a r
206+cons a r = mkStream $ \_ yield _ _ -> yield a r
310
207
311infixr 5 .:
208infixr 5 .:
312
209
@@ -319,7 +216,7 @@ infixr 5 .:
319--
216--
320-- @since 0.1.1
217-- @since 0.1.1
321{-# INLINE (.:) #-}
218{-# INLINE (.:) #-}
322−(.:) :: IsStream t => a -> t m a -> t m a
219+(.:) :: a -> Stream m a -> Stream m a
323(.:) = cons
220(.:) = cons
324
221
325-- | An empty stream.
222-- | An empty stream.
@@ -331,7 +228,7 @@ infixr 5 .:
331--
228--
332-- @since 0.1.0
229-- @since 0.1.0
333{-# INLINE_NORMAL nil #-}
230{-# INLINE_NORMAL nil #-}
334−nil :: IsStream t => t m a
231+nil :: Stream m a
335nil = mkStream $ \_ _ _ stp -> stp
232nil = mkStream $ \_ _ _ stp -> stp
336
233
337-- | An empty stream producing a side effect.
234-- | An empty stream producing a side effect.
@@ -344,22 +241,32 @@ nil = mkStream $ \_ _ _ stp -> stp
344--
241--
345-- /Pre-release/
242-- /Pre-release/
346{-# INLINE_NORMAL nilM #-}
243{-# INLINE_NORMAL nilM #-}
347−nilM :: (IsStream t, Monad m) => m b -> t m a
244+nilM :: Monad m => m b -> Stream m a
348nilM m = mkStream $ \_ _ _ stp -> m >> stp
245nilM m = mkStream $ \_ _ _ stp -> m >> stp
349
246
350{-# INLINE_NORMAL fromPure #-}
247{-# INLINE_NORMAL fromPure #-}
351−fromPure :: IsStream t => a -> t m a
248+fromPure :: a -> Stream m a
352fromPure a = mkStream $ \_ _ single _ -> single a
249fromPure a = mkStream $ \_ _ single _ -> single a
353
250
354{-# INLINE_NORMAL fromEffect #-}
251{-# INLINE_NORMAL fromEffect #-}
355−fromEffect :: (Monad m, IsStream t) => m a -> t m a
252+fromEffect :: Monad m => m a -> Stream m a
356−fromEffect m = fromStream $ mkStream $ \_ _ single _ -> m >>= single
253+fromEffect m = mkStream $ \_ _ single _ -> m >>= single
254+
255+infixr 5 `consM`
256+
257+-- NOTE: specializing the function outside the instance definition seems to
258+-- improve performance quite a bit at times, even if we have the same
259+-- SPECIALIZE in the instance definition.
260+{-# INLINE consM #-}
261+{-# SPECIALIZE consM :: IO a -> Stream IO a -> Stream IO a #-}
262+consM :: (Monad m) => m a -> Stream m a -> Stream m a
263+consM m r = MkStream $ \_ yld _ _ -> m >>= \a -> yld a r
357
264
358-- XXX specialize to IO?
265-- XXX specialize to IO?
359{-# INLINE consMBy #-}
266{-# INLINE consMBy #-}
360−consMBy :: (IsStream t, MonadAsync m) => (t m a -> t m a -> t m a)
267+consMBy :: Monad m =>
361− -> m a -> t m a -> t m a
268+ (Stream m a -> Stream m a -> Stream m a) -> m a -> Stream m a -> Stream m a
362−consMBy f m r = fromStream (fromEffect m) `f` r
269+consMBy f m r = fromEffect m `f` r
363
270
364------------------------------------------------------------------------------
271------------------------------------------------------------------------------
365-- Folding a stream
272-- Folding a stream
@@ -370,78 +277,27 @@ consMBy f m r = fromStream (fromEffect m) `f` r
370-- SVar passed via the State.
277-- SVar passed via the State.
371{-# INLINE_EARLY foldStreamShared #-}
278{-# INLINE_EARLY foldStreamShared #-}
372foldStreamShared
279foldStreamShared
373− :: IsStream t
374− => State Stream m a
375− -> (a -> t m a -> m r)
376− -> (a -> m r)
377− -> m r
378− -> t m a
379− -> m r
380−foldStreamShared st yld sng stp m =
381− let yieldk a x = yld a (fromStream x)
382− MkStream k = toStream m
383− in k st yieldk sng stp
384−
385−-- XXX write a similar rule for foldStream as well?
386−{-# RULES "foldStreamShared from stream"
387− foldStreamShared = foldStreamSharedStream #-}
388−foldStreamSharedStream
389 :: State Stream m a
280 :: State Stream m a
390 -> (a -> Stream m a -> m r)
281 -> (a -> Stream m a -> m r)
391 -> (a -> m r)
282 -> (a -> m r)
392 -> m r
283 -> m r
393 -> Stream m a
284 -> Stream m a
394 -> m r
285 -> m r
395−foldStreamSharedStream st yld sng stp m =
286+foldStreamShared s yield single stop (MkStream k) = k s yield single stop
396− let MkStream k = toStream m
397− in k st yld sng stp
398
287
399-- | Fold a stream by providing a State, stop continuation, a singleton
288-- | Fold a stream by providing a State, stop continuation, a singleton
400-- continuation and a yield continuation. The stream will not use the SVar
289-- continuation and a yield continuation. The stream will not use the SVar
401-- passed via State.
290-- passed via State.
402{-# INLINE foldStream #-}
291{-# INLINE foldStream #-}
403foldStream
292foldStream
404− :: IsStream t
405− => State Stream m a
293+ :: State Stream m a
406− -> (a -> t m a -> m r)
294+ -> (a -> Stream m a -> m r)
407 -> (a -> m r)
295 -> (a -> m r)
408 -> m r
296 -> m r
409− -> t m a
297+ -> Stream m a
410 -> m r
298 -> m r
411−foldStream st yld sng stp m =
299+foldStream s yield single stop (MkStream k) =
412− let yieldk a x = yld a (fromStream x)
413− MkStream k = toStream m
414− in k (adaptState st) yieldk sng stp
300+ k (adaptState s) yield single stop
415−
416−-------------------------------------------------------------------------------
417−-- Instances
418−-------------------------------------------------------------------------------
419−
420−-- NOTE: specializing the function outside the instance definition seems to
421−-- improve performance quite a bit at times, even if we have the same
422−-- SPECIALIZE in the instance definition.
423−{-# INLINE consMStream #-}
424−{-# SPECIALIZE consMStream :: IO a -> Stream IO a -> Stream IO a #-}
425−consMStream :: (Monad m) => m a -> Stream m a -> Stream m a
426−consMStream m r = MkStream $ \_ yld _ _ -> m >>= \a -> yld a r
427−
428−-------------------------------------------------------------------------------
429−-- IsStream Stream
430−-------------------------------------------------------------------------------
431−
432−instance IsStream Stream where
433− toStream = id
434− fromStream = id
435−
436− {-# INLINE consM #-}
437− {-# SPECIALIZE consM :: IO a -> Stream IO a -> Stream IO a #-}
438− consM :: Monad m => m a -> Stream m a -> Stream m a
439− consM = consMStream
440−
441− {-# INLINE (|:) #-}
442− {-# SPECIALIZE (|:) :: IO a -> Stream IO a -> Stream IO a #-}
443− (|:) :: Monad m => m a -> Stream m a -> Stream m a
444− (|:) = consMStream
445
301
446-------------------------------------------------------------------------------
302-------------------------------------------------------------------------------
447-- foldr/build fusion
303-- foldr/build fusion
@@ -454,15 +310,18 @@ instance IsStream Stream where
454-- reconstruct using a shared state (SVar) or without sharing the state.
310-- reconstruct using a shared state (SVar) or without sharing the state.
455--
311--
456{-# INLINE foldrSWith #-}
312{-# INLINE foldrSWith #-}
457−foldrSWith :: IsStream t
313+foldrSWith ::
458− => (forall r. State Stream m b
314+ (forall r. State Stream m b
459− -> (b -> t m b -> m r)
315+ -> (b -> Stream m b -> m r)
460 -> (b -> m r)
316 -> (b -> m r)
461 -> m r
317 -> m r
462− -> t m b
318+ -> Stream m b
463 -> m r)
319 -> m r)
464− -> (a -> t m b -> t m b) -> t m b -> t m a -> t m b
320+ -> (a -> Stream m b -> Stream m b)
321+ -> Stream m b
322+ -> Stream m a
323+ -> Stream m b
465−foldrSWith f step final = go
324+foldrSWith f step final m = go m
466 where
325 where
467 go m1 = mkStream $ \st yld sng stp ->
326 go m1 = mkStream $ \st yld sng stp ->
468 let run x = f st yld sng stp x
327 let run x = f st yld sng stp x
@@ -480,7 +339,11 @@ foldrSWith f step final = go
480
339
481-- | Fold sharing the SVar state within the reconstructed stream
340-- | Fold sharing the SVar state within the reconstructed stream
482{-# INLINE_NORMAL foldrSShared #-}
341{-# INLINE_NORMAL foldrSShared #-}
483−foldrSShared :: IsStream t => (a -> t m b -> t m b) -> t m b -> t m a -> t m b
342+foldrSShared ::
343+ (a -> Stream m b -> Stream m b)
344+ -> Stream m b
345+ -> Stream m a
346+ -> Stream m b
484foldrSShared = foldrSWith foldStreamShared
347foldrSShared = foldrSWith foldStreamShared
485
348
486-- XXX consM is a typeclass method, therefore rewritten already. Instead maybe
349-- XXX consM is a typeclass method, therefore rewritten already. Instead maybe
@@ -495,7 +358,11 @@ foldrSShared = foldrSWith foldStreamShared
495
358
496-- | Lazy right associative fold to a stream.
359-- | Lazy right associative fold to a stream.
497{-# INLINE_NORMAL foldrS #-}
360{-# INLINE_NORMAL foldrS #-}
498−foldrS :: IsStream t => (a -> t m b -> t m b) -> t m b -> t m a -> t m b
361+foldrS ::
362+ (a -> Stream m b -> Stream m b)
363+ -> Stream m b
364+ -> Stream m a
365+ -> Stream m b
499foldrS = foldrSWith foldStream
366foldrS = foldrSWith foldStream
500
367
501{-# RULES "foldrS/id" foldrS cons nil = \x -> x #-}
368{-# RULES "foldrS/id" foldrS cons nil = \x -> x #-}
@@ -512,15 +379,18 @@ foldrS = foldrSWith foldStream
512-------------------------------------------------------------------------------
379-------------------------------------------------------------------------------
513
380
514{-# INLINE foldrSMWith #-}
381{-# INLINE foldrSMWith #-}
515−foldrSMWith :: (IsStream t, Monad m)
382+foldrSMWith :: Monad m
516 => (forall r. State Stream m b
383 => (forall r. State Stream m b
517− -> (b -> t m b -> m r)
384+ -> (b -> Stream m b -> m r)
518 -> (b -> m r)
385 -> (b -> m r)
519 -> m r
386 -> m r
520− -> t m b
387+ -> Stream m b
521 -> m r)
388 -> m r)
522− -> (m a -> t m b -> t m b) -> t m b -> t m a -> t m b
389+ -> (m a -> Stream m b -> Stream m b)
390+ -> Stream m b
391+ -> Stream m a
392+ -> Stream m b
523−foldrSMWith f step final = go
393+foldrSMWith f step final m = go m
524 where
394 where
525 go m1 = mkStream $ \st yld sng stp ->
395 go m1 = mkStream $ \st yld sng stp ->
526 let run x = f st yld sng stp x
396 let run x = f st yld sng stp x
@@ -530,8 +400,11 @@ foldrSMWith f step final = go
530 in foldStream (adaptState st) yieldk single stop m1
400 in foldStream (adaptState st) yieldk single stop m1
531
401
532{-# INLINE_NORMAL foldrSM #-}
402{-# INLINE_NORMAL foldrSM #-}
533−foldrSM :: (IsStream t, Monad m)
403+foldrSM :: Monad m
534− => (m a -> t m b -> t m b) -> t m b -> t m a -> t m b
404+ => (m a -> Stream m b -> Stream m b)
405+ -> Stream m b
406+ -> Stream m a
407+ -> Stream m b
535foldrSM = foldrSMWith foldStream
408foldrSM = foldrSMWith foldStream
536
409
537-- {-# RULES "foldrSM/id" foldrSM consM nil = \x -> x #-}
410-- {-# RULES "foldrSM/id" foldrSM consM nil = \x -> x #-}
@@ -542,8 +415,11 @@ foldrSM = foldrSMWith foldStream
542
415
543-- Like foldrSM but sharing the SVar state within the recostructed stream.
416-- Like foldrSM but sharing the SVar state within the recostructed stream.
544{-# INLINE_NORMAL foldrSMShared #-}
417{-# INLINE_NORMAL foldrSMShared #-}
545−foldrSMShared :: (IsStream t, Monad m)
418+foldrSMShared :: Monad m
546− => (m a -> t m b -> t m b) -> t m b -> t m a -> t m b
419+ => (m a -> Stream m b -> Stream m b)
420+ -> Stream m b
421+ -> Stream m a
422+ -> Stream m b
547foldrSMShared = foldrSMWith foldStreamShared
423foldrSMShared = foldrSMWith foldStreamShared
548
424
549-- {-# RULES "foldrSM/id" foldrSM consM nil = \x -> x #-}
425-- {-# RULES "foldrSM/id" foldrSM consM nil = \x -> x #-}
@@ -559,7 +435,7 @@ foldrSMShared = foldrSMWith foldStreamShared
559-------------------------------------------------------------------------------
435-------------------------------------------------------------------------------
560
436
561{-# INLINE_NORMAL build #-}
437{-# INLINE_NORMAL build #-}
562−build :: IsStream t => forall a. (forall b. (a -> b -> b) -> b -> b) -> t m a
438+build :: forall m a. (forall b. (a -> b -> b) -> b -> b) -> Stream m a
563build g = g cons nil
439build g = g cons nil
564
440
565{-# RULES "foldrM/build"
441{-# RULES "foldrM/build"
@@ -584,37 +460,46 @@ build g = g cons nil
584
460
585-- build a stream by applying cons and nil to a build function
461-- build a stream by applying cons and nil to a build function
586{-# INLINE_NORMAL buildS #-}
462{-# INLINE_NORMAL buildS #-}
587−buildS :: IsStream t => ((a -> t m a -> t m a) -> t m a -> t m a) -> t m a
463+buildS ::
464+ ((a -> Stream m a -> Stream m a) -> Stream m a -> Stream m a)
465+ -> Stream m a
588buildS g = g cons nil
466buildS g = g cons nil
589
467
590{-# RULES "foldrS/buildS"
468{-# RULES "foldrS/buildS"
591− forall k z (g :: (a -> t m a -> t m a) -> t m a -> t m a).
469+ forall k z
470+ (g :: (a -> Stream m a -> Stream m a) -> Stream m a -> Stream m a).
592 foldrS k z (buildS g) = g k z #-}
471 foldrS k z (buildS g) = g k z #-}
593
472
594{-# RULES "foldrS/cons/buildS"
473{-# RULES "foldrS/cons/buildS"
595− forall k z x (g :: (a -> t m a -> t m a) -> t m a -> t m a).
474+ forall k z x
475+ (g :: (a -> Stream m a -> Stream m a) -> Stream m a -> Stream m a).
596 foldrS k z (x `cons` buildS g) = k x (g k z) #-}
476 foldrS k z (x `cons` buildS g) = k x (g k z) #-}
597
477
598{-# RULES "foldrSShared/buildS"
478{-# RULES "foldrSShared/buildS"
599− forall k z (g :: (a -> t m a -> t m a) -> t m a -> t m a).
479+ forall k z
480+ (g :: (a -> Stream m a -> Stream m a) -> Stream m a -> Stream m a).
600 foldrSShared k z (buildS g) = g k z #-}
481 foldrSShared k z (buildS g) = g k z #-}
601
482
602{-# RULES "foldrSShared/cons/buildS"
483{-# RULES "foldrSShared/cons/buildS"
603− forall k z x (g :: (a -> t m a -> t m a) -> t m a -> t m a).
484+ forall k z x
485+ (g :: (a -> Stream m a -> Stream m a) -> Stream m a -> Stream m a).
604 foldrSShared k z (x `cons` buildS g) = k x (g k z) #-}
486 foldrSShared k z (x `cons` buildS g) = k x (g k z) #-}
605
487
606-- build a stream by applying consM and nil to a build function
488-- build a stream by applying consM and nil to a build function
607{-# INLINE_NORMAL buildSM #-}
489{-# INLINE_NORMAL buildSM #-}
608−buildSM :: (IsStream t, MonadAsync m)
490+buildSM :: Monad m
609− => ((m a -> t m a -> t m a) -> t m a -> t m a) -> t m a
491+ => ((m a -> Stream m a -> Stream m a) -> Stream m a -> Stream m a)
492+ -> Stream m a
610buildSM g = g consM nil
493buildSM g = g consM nil
611
494
612{-# RULES "foldrSM/buildSM"
495{-# RULES "foldrSM/buildSM"
613− forall k z (g :: (m a -> t m a -> t m a) -> t m a -> t m a).
496+ forall k z
497+ (g :: (m a -> Stream m a -> Stream m a) -> Stream m a -> Stream m a).
614 foldrSM k z (buildSM g) = g k z #-}
498 foldrSM k z (buildSM g) = g k z #-}
615
499
616{-# RULES "foldrSMShared/buildSM"
500{-# RULES "foldrSMShared/buildSM"
617− forall k z (g :: (m a -> t m a -> t m a) -> t m a -> t m a).
501+ forall k z
502+ (g :: (m a -> Stream m a -> Stream m a) -> Stream m a -> Stream m a).
618 foldrSMShared k z (buildSM g) = g k z #-}
503 foldrSMShared k z (buildSM g) = g k z #-}
619
504
620-- Disabled because this may not fire as consM is a class Op
505-- Disabled because this may not fire as consM is a class Op
@@ -629,71 +514,79 @@ buildSM g = g consM nil
629-- Build using monadic build functions (continuations) instead of
514-- Build using monadic build functions (continuations) instead of
630-- reconstructing a stream.
515-- reconstructing a stream.
631{-# INLINE_NORMAL buildM #-}
516{-# INLINE_NORMAL buildM #-}
632−buildM :: (IsStream t, MonadAsync m)
517+buildM :: Monad m
633− => (forall r. (a -> t m a -> m r)
518+ => (forall r. (a -> Stream m a -> m r)
634 -> (a -> m r)
519 -> (a -> m r)
635 -> m r
520 -> m r
636 -> m r
521 -> m r
637 )
522 )
638− -> t m a
523+ -> Stream m a
639buildM g = mkStream $ \st yld sng stp ->
524buildM g = mkStream $ \st yld sng stp ->
640 g (\a r -> foldStream st yld sng stp (return a `consM` r)) sng stp
525 g (\a r -> foldStream st yld sng stp (return a `consM` r)) sng stp
641
526
642-- | Like 'buildM' but shares the SVar state across computations.
527-- | Like 'buildM' but shares the SVar state across computations.
643−{-# INLINE_NORMAL sharedM #-}
528+{-# INLINE_NORMAL sharedMWith #-}
644−sharedM :: (IsStream t, MonadAsync m)
529+sharedMWith :: Monad m
530+ => (m a -> Stream m a -> Stream m a)
645− => (forall r. (a -> t m a -> m r)
531+ -> (forall r. (a -> Stream m a -> m r)
646 -> (a -> m r)
532 -> (a -> m r)
647 -> m r
533 -> m r
648 -> m r
534 -> m r
649 )
535 )
650− -> t m a
536+ -> Stream m a
651−sharedM g = mkStream $ \st yld sng stp ->
537+sharedMWith cns g = mkStream $ \st yld sng stp ->
652− g (\a r -> foldStreamShared st yld sng stp (return a `consM` r)) sng stp
538+ g (\a r -> foldStreamShared st yld sng stp (return a `cns` r)) sng stp
653
539
654-------------------------------------------------------------------------------
540-------------------------------------------------------------------------------
655-- augment
541-- augment
656-------------------------------------------------------------------------------
542-------------------------------------------------------------------------------
657
543
658{-# INLINE_NORMAL augmentS #-}
544{-# INLINE_NORMAL augmentS #-}
659−augmentS :: IsStream t
545+augmentS ::
660− => ((a -> t m a -> t m a) -> t m a -> t m a) -> t m a -> t m a
546+ ((a -> Stream m a -> Stream m a) -> Stream m a -> Stream m a)
547+ -> Stream m a
548+ -> Stream m a
661−augmentS g = g cons
549+augmentS g xs = g cons xs
662
550
663{-# RULES "augmentS/nil"
551{-# RULES "augmentS/nil"
664− forall (g :: (a -> t m a -> t m a) -> t m a -> t m a).
552+ forall (g :: (a -> Stream m a -> Stream m a) -> Stream m a -> Stream m a).
665 augmentS g nil = buildS g
553 augmentS g nil = buildS g
666 #-}
554 #-}
667
555
668{-# RULES "foldrS/augmentS"
556{-# RULES "foldrS/augmentS"
669− forall k z xs (g :: (a -> t m a -> t m a) -> t m a -> t m a).
557+ forall k z xs
558+ (g :: (a -> Stream m a -> Stream m a) -> Stream m a -> Stream m a).
670 foldrS k z (augmentS g xs) = g k (foldrS k z xs)
559 foldrS k z (augmentS g xs) = g k (foldrS k z xs)
671 #-}
560 #-}
672
561
673{-# RULES "augmentS/buildS"
562{-# RULES "augmentS/buildS"
674− forall (g :: (a -> t m a -> t m a) -> t m a -> t m a)
563+ forall (g :: (a -> Stream m a -> Stream m a) -> Stream m a -> Stream m a)
675− (h :: (a -> t m a -> t m a) -> t m a -> t m a).
564+ (h :: (a -> Stream m a -> Stream m a) -> Stream m a -> Stream m a).
676 augmentS g (buildS h) = buildS (\c n -> g c (h c n))
565 augmentS g (buildS h) = buildS (\c n -> g c (h c n))
677 #-}
566 #-}
678
567
679{-# INLINE_NORMAL augmentSM #-}
568{-# INLINE_NORMAL augmentSM #-}
680−augmentSM :: (IsStream t, MonadAsync m)
569+augmentSM :: Monad m =>
681− => ((m a -> t m a -> t m a) -> t m a -> t m a) -> t m a -> t m a
570+ ((m a -> Stream m a -> Stream m a) -> Stream m a -> Stream m a)
571+ -> Stream m a -> Stream m a
682−augmentSM g = g consM
572+augmentSM g xs = g consM xs
683
573
684{-# RULES "augmentSM/nil"
574{-# RULES "augmentSM/nil"
685− forall (g :: (m a -> t m a -> t m a) -> t m a -> t m a).
575+ forall
576+ (g :: (m a -> Stream m a -> Stream m a) -> Stream m a -> Stream m a).
686 augmentSM g nil = buildSM g
577 augmentSM g nil = buildSM g
687 #-}
578 #-}
688
579
689{-# RULES "foldrSM/augmentSM"
580{-# RULES "foldrSM/augmentSM"
690− forall k z xs (g :: (m a -> t m a -> t m a) -> t m a -> t m a).
581+ forall k z xs
582+ (g :: (m a -> Stream m a -> Stream m a) -> Stream m a -> Stream m a).
691 foldrSM k z (augmentSM g xs) = g k (foldrSM k z xs)
583 foldrSM k z (augmentSM g xs) = g k (foldrSM k z xs)
692 #-}
584 #-}
693
585
694{-# RULES "augmentSM/buildSM"
586{-# RULES "augmentSM/buildSM"
695− forall (g :: (m a -> t m a -> t m a) -> t m a -> t m a)
587+ forall
588+ (g :: (m a -> Stream m a -> Stream m a) -> Stream m a -> Stream m a)
696− (h :: (m a -> t m a -> t m a) -> t m a -> t m a).
589+ (h :: (m a -> Stream m a -> Stream m a) -> Stream m a -> Stream m a).
697 augmentSM g (buildSM h) = buildSM (\c n -> g c (h c n))
590 augmentSM g (buildSM h) = buildSM (\c n -> g c (h c n))
698 #-}
591 #-}
699
592
@@ -703,8 +596,8 @@ augmentSM g = g consM
703
596
704-- | Lazy right fold with a monadic step function.
597-- | Lazy right fold with a monadic step function.
705{-# INLINE_NORMAL foldrM #-}
598{-# INLINE_NORMAL foldrM #-}
706−foldrM :: IsStream t => (a -> m b -> m b) -> m b -> t m a -> m b
599+foldrM :: (a -> m b -> m b) -> m b -> Stream m a -> m b
707−foldrM step acc = go
600+foldrM step acc m = go m
708 where
601 where
709 go m1 =
602 go m1 =
710 let stop = acc
603 let stop = acc
@@ -715,14 +608,14 @@ foldrM step acc = go
715{-# INLINE_NORMAL foldrMKWith #-}
608{-# INLINE_NORMAL foldrMKWith #-}
716foldrMKWith
609foldrMKWith
717 :: (State Stream m a
610 :: (State Stream m a
718− -> (a -> t m a -> m b)
611+ -> (a -> Stream m a -> m b)
719 -> (a -> m b)
612 -> (a -> m b)
720 -> m b
613 -> m b
721− -> t m a
614+ -> Stream m a
722 -> m b)
615 -> m b)
723 -> (a -> m b -> m b)
616 -> (a -> m b -> m b)
724 -> m b
617 -> m b
725− -> ((a -> t m a -> m b) -> (a -> m b) -> m b -> m b)
618+ -> ((a -> Stream m a -> m b) -> (a -> m b) -> m b -> m b)
726 -> m b
619 -> m b
727foldrMKWith f step acc = go
620foldrMKWith f step acc = go
728 where
621 where
@@ -742,7 +635,7 @@ foldrMKWith f step acc = go
742-- XXX in which case will foldrM/buildM fusion be useful?
635-- XXX in which case will foldrM/buildM fusion be useful?
743{-# RULES "foldrM/buildM"
636{-# RULES "foldrM/buildM"
744 forall step acc (g :: (forall r.
637 forall step acc (g :: (forall r.
745− (a -> t m a -> m r)
638+ (a -> Stream m a -> m r)
746 -> (a -> m r)
639 -> (a -> m r)
747 -> m r
640 -> m r
748 -> m r
641 -> m r
@@ -750,15 +643,17 @@ foldrMKWith f step acc = go
750 foldrM step acc (buildM g) = foldrMKWith foldStream step acc g
643 foldrM step acc (buildM g) = foldrMKWith foldStream step acc g
751 #-}
644 #-}
752
645
646+{-
753{-# RULES "foldrM/sharedM"
647{-# RULES "foldrM/sharedM"
754 forall step acc (g :: (forall r.
648 forall step acc (g :: (forall r.
755− (a -> t m a -> m r)
649+ (a -> Stream m a -> m r)
756 -> (a -> m r)
650 -> (a -> m r)
757 -> m r
651 -> m r
758 -> m r
652 -> m r
759 )).
653 )).
760 foldrM step acc (sharedM g) = foldrMKWith foldStreamShared step acc g
654 foldrM step acc (sharedM g) = foldrMKWith foldStreamShared step acc g
761 #-}
655 #-}
656+-}
762
657
763------------------------------------------------------------------------------
658------------------------------------------------------------------------------
764-- Left fold
659-- Left fold
@@ -771,12 +666,12 @@ foldrMKWith f step acc = go
771--
666--
772-- Note that the accumulator is always evaluated including the initial value.
667-- Note that the accumulator is always evaluated including the initial value.
773{-# INLINE foldlx' #-}
668{-# INLINE foldlx' #-}
774−foldlx' :: forall t m a b x. (IsStream t, Monad m)
669+foldlx' :: forall m a b x. Monad m
775− => (x -> a -> x) -> x -> (x -> b) -> t m a -> m b
670+ => (x -> a -> x) -> x -> (x -> b) -> Stream m a -> m b
776foldlx' step begin done m = get $ go m begin
671foldlx' step begin done m = get $ go m begin
777 where
672 where
778 {-# NOINLINE get #-}
673 {-# NOINLINE get #-}
779− get :: t m x -> m b
674+ get :: Stream m x -> m b
780 get m1 =
675 get m1 =
781 -- XXX we are not strictly evaluating the accumulator here. Is this
676 -- XXX we are not strictly evaluating the accumulator here. Is this
782 -- okay?
677 -- okay?
@@ -788,7 +683,7 @@ foldlx' step begin done m = get $ go m begin
788 -- however that is more expensive because of unnecessary recursion
683 -- however that is more expensive because of unnecessary recursion
789 -- that cannot be tail call optimized. Unfolding recursion explicitly via
684 -- that cannot be tail call optimized. Unfolding recursion explicitly via
790 -- continuations is much more efficient.
685 -- continuations is much more efficient.
791− go :: t m a -> x -> t m x
686+ go :: Stream m a -> x -> Stream m x
792 go m1 !acc = mkStream $ \_ yld sng _ ->
687 go m1 !acc = mkStream $ \_ yld sng _ ->
793 let stop = sng acc
688 let stop = sng acc
794 single a = sng $ step acc a
689 single a = sng $ step acc a
@@ -799,9 +694,44 @@ foldlx' step begin done m = get $ go m begin
799
694
800-- | Strict left associative fold.
695-- | Strict left associative fold.
801{-# INLINE foldl' #-}
696{-# INLINE foldl' #-}
802−foldl' :: (IsStream t, Monad m) => (b -> a -> b) -> b -> t m a -> m b
697+foldl' :: Monad m => (b -> a -> b) -> b -> Stream m a -> m b
803foldl' step begin = foldlx' step begin id
698foldl' step begin = foldlx' step begin id
804
699
700+------------------------------------------------------------------------------
701+-- Specialized folds
702+------------------------------------------------------------------------------
703+
704+-- XXX use foldrM to implement folds where possible
705+-- XXX This (commented) definition of drain and mapM_ perform much better on
706+-- some benchmarks but worse on others. Need to investigate why, may there is
707+-- an optimization opportunity that we can exploit.
708+-- drain = foldrM (\_ xs -> return () >> xs) (return ())
709+
710+-- |
711+-- > drain = foldl' (\_ _ -> ()) ()
712+-- > drain = mapM_ (\_ -> return ())
713+{-# INLINE drain #-}
714+drain :: Monad m => Stream m a -> m ()
715+drain = foldrM (\_ xs -> xs) (return ())
716+{-
717+drain = go
718+ where
719+ go m1 =
720+ let stop = return ()
721+ single _ = return ()
722+ yieldk _ r = go r
723+ in foldStream defState yieldk single stop m1
724+-}
725+
726+{-# INLINE null #-}
727+null :: Monad m => Stream m a -> m Bool
728+-- null = foldrM (\_ _ -> return True) (return False)
729+null m =
730+ let stop = return True
731+ single _ = return False
732+ yieldk _ _ = return False
733+ in foldStream defState yieldk single stop m
734+
805------------------------------------------------------------------------------
735------------------------------------------------------------------------------
806-- Semigroup
736-- Semigroup
807------------------------------------------------------------------------------
737------------------------------------------------------------------------------
@@ -811,19 +741,8 @@ infixr 6 `serial`
811-- | Appends two streams sequentially, yielding all elements from the first
741-- | Appends two streams sequentially, yielding all elements from the first
812-- stream, and then all elements from the second stream.
742-- stream, and then all elements from the second stream.
813--
743--
814−-- >>> import Streamly.Prelude (serial)
815−-- >>> stream1 = Stream.fromList [1,2]
816−-- >>> stream2 = Stream.fromList [3,4]
817−-- >>> Stream.toList $ stream1 `serial` stream2
818−-- [1,2,3,4]
819−--
820−-- This operation can be used to fold an infinite lazy container of streams.
821−--
822−-- /Since: 0.2.0 ("Streamly")/
823−--
824−-- @since 0.8.0
825{-# INLINE serial #-}
744{-# INLINE serial #-}
826−serial :: IsStream t => t m a -> t m a -> t m a
745+serial :: Stream m a -> Stream m a -> Stream m a
827-- XXX This doubles the time of toNullAp benchmark, may not be fusing properly
746-- XXX This doubles the time of toNullAp benchmark, may not be fusing properly
828-- serial xs ys = augmentS (\c n -> foldrS c n xs) ys
747-- serial xs ys = augmentS (\c n -> foldrS c n xs) ys
829serial m1 m2 = go m1
748serial m1 m2 = go m1
@@ -836,7 +755,7 @@ serial m1 m2 = go m1
836
755
837-- join/merge/append streams depending on consM
756-- join/merge/append streams depending on consM
838{-# INLINE conjoin #-}
757{-# INLINE conjoin #-}
839−conjoin :: (IsStream t, MonadAsync m) => t m a -> t m a -> t m a
758+conjoin :: Monad m => Stream m a -> Stream m a -> Stream m a
840conjoin xs = augmentSM (\c n -> foldrSM c n xs)
759conjoin xs = augmentSM (\c n -> foldrSM c n xs)
841
760
842instance Semigroup (Stream m a) where
761instance Semigroup (Stream m a) where
@@ -856,10 +775,13 @@ instance Monoid (Stream m a) where
856
775
857-- Note eta expanded
776-- Note eta expanded
858{-# INLINE_LATE mapFB #-}
777{-# INLINE_LATE mapFB #-}
859−mapFB :: forall (t :: (Type -> Type) -> Type -> Type) b m a.
778+mapFB :: forall b m a.
860− (b -> t m b -> t m b) -> (a -> b) -> a -> t m b -> t m b
779+ (b -> Stream m b -> Stream m b)
780+ -> (a -> b)
781+ -> a
782+ -> Stream m b
783+ -> Stream m b
861−mapFB c f x ys = c (f x) ys
784+mapFB c f = \x ys -> c (f x) ys
862−#undef Type
863
785
864{-# RULES
786{-# RULES
865"mapFB/mapFB" forall c f g. mapFB (mapFB c f) g = mapFB c (f . g)
787"mapFB/mapFB" forall c f g. mapFB (mapFB c f) g = mapFB c (f . g)
@@ -867,7 +789,7 @@ mapFB c f x ys = c (f x) ys
867 #-}
789 #-}
868
790
869{-# INLINE map #-}
791{-# INLINE map #-}
870−map :: IsStream t => (a -> b) -> t m a -> t m b
792+map :: (a -> b) -> Stream m a -> Stream m b
871map f xs = buildS (\c n -> foldrS (mapFB c f) n xs)
793map f xs = buildS (\c n -> foldrS (mapFB c f) n xs)
872
794
873-- XXX This definition might potentially be more efficient, but the cost in the
795-- XXX This definition might potentially be more efficient, but the cost in the
@@ -898,21 +820,6 @@ mapMFB c f x = c (x >>= f)
898"mapMFB/return" forall c. mapMFB c (\x -> return x) = c
820"mapMFB/return" forall c. mapMFB c (\x -> return x) = c
899-}
821-}
900
822
901−-- Be careful when modifying this, this uses a consM (|:) deliberately to allow
902−-- other stream types to overload it.
903−{-# INLINE mapM #-}
904−mapM :: (IsStream t, MonadAsync m) => (a -> m b) -> t m a -> t m b
905−mapM f = foldrSShared (\x xs -> f x `consM` xs) nil
906−-- See note under map definition above.
907−{-
908−mapM f m = go m
909− where
910− go m1 = mkStream $ \st yld sng stp ->
911− let single a = f a >>= sng
912− yieldk a r = foldStreamShared st yld sng stp $ f a |: go r
913− in foldStream (adaptState st) yieldk single stp m1
914− -}
915−
916-- This is experimental serial version supporting fusion.
823-- This is experimental serial version supporting fusion.
917--
824--
918-- XXX what if we do not want to fuse two concurrent mapMs?
825-- XXX what if we do not want to fuse two concurrent mapMs?
@@ -921,9 +828,27 @@ mapM f m = go m
921-- XXX fusion would be easier for monomoprhic stream types.
828-- XXX fusion would be easier for monomoprhic stream types.
922-- {-# RULES "mapM serial" mapM = mapMSerial #-}
829-- {-# RULES "mapM serial" mapM = mapMSerial #-}
923{-# INLINE mapMSerial #-}
830{-# INLINE mapMSerial #-}
924−mapMSerial :: MonadAsync m => (a -> m b) -> Stream m a -> Stream m b
831+mapMSerial :: Monad m => (a -> m b) -> Stream m a -> Stream m b
925mapMSerial f xs = buildSM (\c n -> foldrSMShared (mapMFB c f) n xs)
832mapMSerial f xs = buildSM (\c n -> foldrSMShared (mapMFB c f) n xs)
926
833
834+{-# INLINE mapMWith #-}
835+mapMWith ::
836+ (m b -> Stream m b -> Stream m b)
837+ -> (a -> m b)
838+ -> Stream m a
839+ -> Stream m b
840+mapMWith cns f = foldrSShared (\x xs -> f x `cns` xs) nil
841+
842+{-
843+-- See note under map definition above.
844+mapMWith cns f = go
845+ where
846+ go m1 = mkStream $ \st yld sng stp ->
847+ let single a = f a >>= sng
848+ yieldk a r = foldStreamShared st yld sng stp $ f a `cns` go r
849+ in foldStream (adaptState st) yieldk single stp m1
850+-}
851+
927-- XXX in fact use the Stream type everywhere and only use polymorphism in the
852-- XXX in fact use the Stream type everywhere and only use polymorphism in the
928-- high level modules/prelude.
853-- high level modules/prelude.
929instance Monad m => Functor (Stream m) where
854instance Monad m => Functor (Stream m) where
@@ -943,18 +868,17 @@ instance MonadTrans Stream where
943
868
944-- | Detach a stream from an SVar
869-- | Detach a stream from an SVar
945{-# INLINE unShare #-}
870{-# INLINE unShare #-}
946−unShare :: IsStream t => t m a -> t m a
871+unShare :: Stream m a -> Stream m a
947unShare x = mkStream $ \st yld sng stp ->
872unShare x = mkStream $ \st yld sng stp ->
948 foldStream st yld sng stp x
873 foldStream st yld sng stp x
949
874
950-- XXX the function stream and value stream can run in parallel
875-- XXX the function stream and value stream can run in parallel
951{-# INLINE apWith #-}
876{-# INLINE apWith #-}
952−apWith
877+apWith ::
953− :: IsStream t
878+ (Stream m b -> Stream m b -> Stream m b)
954− => (t m b -> t m b -> t m b)
955− -> t m (a -> b)
879+ -> Stream m (a -> b)
956− -> t m a
880+ -> Stream m a
957− -> t m b
881+ -> Stream m b
958apWith par fstream stream = go1 fstream
882apWith par fstream stream = go1 fstream
959
883
960 where
884 where
@@ -973,11 +897,10 @@ apWith par fstream stream = go1 fstream
973 in foldStream (adaptState st) yieldk single stp m
897 in foldStream (adaptState st) yieldk single stp m
974
898
975{-# INLINE apSerial #-}
899{-# INLINE apSerial #-}
976−apSerial
900+apSerial ::
977− :: IsStream t
978− => t m (a -> b)
901+ Stream m (a -> b)
979− -> t m a
902+ -> Stream m a
980− -> t m b
903+ -> Stream m b
981apSerial fstream stream = go1 fstream
904apSerial fstream stream = go1 fstream
982
905
983 where
906 where
@@ -1004,11 +927,10 @@ apSerial fstream stream = go1 fstream
1004 in foldStream (adaptState st) yieldk single stp m
927 in foldStream (adaptState st) yieldk single stp m
1005
928
1006{-# INLINE apSerialDiscardFst #-}
929{-# INLINE apSerialDiscardFst #-}
1007−apSerialDiscardFst
930+apSerialDiscardFst ::
1008− :: IsStream t
931+ Stream m a
1009− => t m a
932+ -> Stream m b
1010− -> t m b
933+ -> Stream m b
1011− -> t m b
1012apSerialDiscardFst fstream stream = go1 fstream
934apSerialDiscardFst fstream stream = go1 fstream
1013
935
1014 where
936 where
@@ -1029,11 +951,10 @@ apSerialDiscardFst fstream stream = go1 fstream
1029 in foldStream st yieldk single stop m
951 in foldStream st yieldk single stop m
1030
952
1031{-# INLINE apSerialDiscardSnd #-}
953{-# INLINE apSerialDiscardSnd #-}
1032−apSerialDiscardSnd
954+apSerialDiscardSnd ::
1033− :: IsStream t
955+ Stream m a
1034− => t m a
956+ -> Stream m b
1035− -> t m b
957+ -> Stream m a
1036− -> t m a
1037apSerialDiscardSnd fstream stream = go1 fstream
958apSerialDiscardSnd fstream stream = go1 fstream
1038
959
1039 where
960 where
@@ -1059,17 +980,16 @@ apSerialDiscardSnd fstream stream = go1 fstream
1059 yieldk _ r = yld f (go3 f r)
980 yieldk _ r = yld f (go3 f r)
1060 in foldStream (adaptState st) yieldk single stp m
981 in foldStream (adaptState st) yieldk single stp m
1061
982
1062−-- XXX This is just concatMapBy with arguments flipped. We need to keep this
983+-- XXX This is just concatMapWith with arguments flipped. We need to keep this
1063-- instead of using a concatMap style definition because the bind
984-- instead of using a concatMap style definition because the bind
1064-- implementation in Async and WAsync streams show significant perf degradation
985-- implementation in Async and WAsync streams show significant perf degradation
1065-- if the argument order is changed.
986-- if the argument order is changed.
1066{-# INLINE bindWith #-}
987{-# INLINE bindWith #-}
1067−bindWith
988+bindWith ::
1068− :: IsStream t
989+ (Stream m b -> Stream m b -> Stream m b)
1069− => (t m b -> t m b -> t m b)
990+ -> Stream m a
1070− -> t m a
1071− -> (a -> t m b)
991+ -> (a -> Stream m b)
1072− -> t m b
992+ -> Stream m b
1073bindWith par m1 f = go m1
993bindWith par m1 f = go m1
1074 where
994 where
1075 go m =
995 go m =
@@ -1094,21 +1014,18 @@ bindWith par m1 f = go m1
1094-- function.
1014-- function.
1095--
1015--
1096-- @since 0.7.0
1016-- @since 0.7.0
1097−{-# INLINE concatMapBy #-}
1017+{-# INLINE concatMapWith #-}
1098−concatMapBy
1018+concatMapWith
1099− :: IsStream t
1019+ ::
1100− => (t m b -> t m b -> t m b)
1020+ (Stream m b -> Stream m b -> Stream m b)
1101− -> (a -> t m b)
1021+ -> (a -> Stream m b)
1102− -> t m a
1022+ -> Stream m a
1103− -> t m b
1023+ -> Stream m b
1104−concatMapBy par f xs = bindWith par xs f
1024+concatMapWith par f xs = bindWith par xs f
1105
1025
1106{-# INLINE concatMap #-}
1026{-# INLINE concatMap #-}
1107−concatMap :: IsStream t => (a -> t m b) -> t m a -> t m b
1027+concatMap :: (a -> Stream m b) -> Stream m a -> Stream m b
1108−concatMap f m = fromStream $
1028+concatMap = concatMapWith serial
1109− concatMapBy serial
1110− (adapt . toStream . f)
1111− (adapt $ toStream m)
1112
1029
1113{-
1030{-
1114-- Fused version.
1031-- Fused version.
@@ -1133,11 +1050,11 @@ concatMap_ f xs = buildS
1133--
1050--
1134{-# INLINE concatPairsWith #-}
1051{-# INLINE concatPairsWith #-}
1135concatPairsWith
1052concatPairsWith
1136− :: IsStream t
1053+ ::
1137− => (t m b -> t m b -> t m b)
1054+ (Stream m b -> Stream m b -> Stream m b)
1138− -> (a -> t m b)
1055+ -> (a -> Stream m b)
1139− -> t m a
1056+ -> Stream m a
1140− -> t m b
1057+ -> Stream m b
1141concatPairsWith combine f = go Nothing
1058concatPairsWith combine f = go Nothing
1142
1059
1143 where
1060 where
@@ -1195,3 +1112,194 @@ concatUnfoldr :: IsStream t
1195 => (b -> t m (Maybe (a, b))) -> t m b -> t m a
1112 => (b -> t m (Maybe (a, b))) -> t m b -> t m a
1196concatUnfoldr = undefined
1113concatUnfoldr = undefined
1197-}
1114-}
1115+
1116+------------------------------------------------------------------------------
1117+-- MonadReader
1118+------------------------------------------------------------------------------
1119+
1120+{-# INLINABLE withLocal #-}
1121+withLocal :: MonadReader r m => (r -> r) -> Stream m a -> Stream m a
1122+withLocal f m =
1123+ mkStream $ \st yld sng stp ->
1124+ let single = local f . sng
1125+ yieldk a r = local f $ yld a (withLocal f r)
1126+ in foldStream st yieldk single (local f stp) m
1127+
1128+-------------------------------------------------------------------------------
1129+-- Generation
1130+-------------------------------------------------------------------------------
1131+
1132+{-# INLINE unfoldr #-}
1133+unfoldr :: (b -> Maybe (a, b)) -> b -> Stream m a
1134+unfoldr next s0 = build $ \yld stp ->
1135+ let go s =
1136+ case next s of
1137+ Just (a, b) -> yld a (go b)
1138+ Nothing -> stp
1139+ in go s0
1140+
1141+{-# INLINE unfoldrMWith #-}
1142+unfoldrMWith :: Monad m =>
1143+ (m a -> Stream m a -> Stream m a)
1144+ -> (b -> m (Maybe (a, b)))
1145+ -> b
1146+ -> Stream m a
1147+unfoldrMWith cns step = go
1148+
1149+ where
1150+
1151+ go s = sharedMWith cns $ \yld _ stp -> do
1152+ r <- step s
1153+ case r of
1154+ Just (a, b) -> yld a (go b)
1155+ Nothing -> stp
1156+
1157+-- | Generate an infinite stream by repeating a pure value.
1158+--
1159+-- /Pre-release/
1160+{-# INLINE repeat #-}
1161+repeat :: a -> Stream m a
1162+repeat a = let x = cons a x in x
1163+
1164+-- | Like 'repeatM' but takes a stream 'cons' operation to combine the actions
1165+-- in a stream specific manner. A serial cons would repeat the values serially
1166+-- while an async cons would repeat concurrently.
1167+--
1168+-- /Pre-release/
1169+repeatMWith :: (m a -> t m a -> t m a) -> m a -> t m a
1170+repeatMWith cns = go
1171+
1172+ where
1173+
1174+ go m = m `cns` go m
1175+
1176+{-# INLINE replicateMWith #-}
1177+replicateMWith :: (m a -> Stream m a -> Stream m a) -> Int -> m a -> Stream m a
1178+replicateMWith cns n m = go n
1179+
1180+ where
1181+
1182+ go cnt = if cnt <= 0 then nil else m `cns` go (cnt - 1)
1183+
1184+{-# INLINE fromIndicesMWith #-}
1185+fromIndicesMWith ::
1186+ (m a -> Stream m a -> Stream m a) -> (Int -> m a) -> Stream m a
1187+fromIndicesMWith cns gen = go 0
1188+
1189+ where
1190+
1191+ go i = mkStream $ \st stp sng yld -> do
1192+ foldStreamShared st stp sng yld (gen i `cns` go (i + 1))
1193+
1194+{-# INLINE iterateMWith #-}
1195+iterateMWith :: Monad m =>
1196+ (m a -> Stream m a -> Stream m a) -> (a -> m a) -> m a -> Stream m a
1197+iterateMWith cns step = go
1198+
1199+ where
1200+
1201+ go s = mkStream $ \st stp sng yld -> do
1202+ !next <- s
1203+ foldStreamShared st stp sng yld (return next `cns` go (step next))
1204+
1205+{-# INLINE headPartial #-}
1206+headPartial :: Monad m => Stream m a -> m a
1207+headPartial = foldrM (\x _ -> return x) (error "head of nil")
1208+
1209+{-# INLINE tailPartial #-}
1210+tailPartial :: Stream m a -> Stream m a
1211+tailPartial m = mkStream $ \st yld sng stp ->
1212+ let stop = error "tail of nil"
1213+ single _ = stp
1214+ yieldk _ r = foldStream st yld sng stp r
1215+ in foldStream st yieldk single stop m
1216+
1217+{-# INLINE mfix #-}
1218+mfix :: Monad m => (m a -> Stream m a) -> Stream m a
1219+mfix f = mkStream $ \st yld sng stp ->
1220+ let single a = foldStream st yld sng stp $ a `cons` ys
1221+ yieldk a _ = foldStream st yld sng stp $ a `cons` ys
1222+ in foldStream st yieldk single stp xs
1223+
1224+ where
1225+
1226+ -- fix the head element of the stream
1227+ xs = fix (f . headPartial)
1228+
1229+ -- now fix the tail recursively
1230+ ys = mfix (tailPartial . f)
1231+
1232+-------------------------------------------------------------------------------
1233+-- Conversions
1234+-------------------------------------------------------------------------------
1235+
1236+-- |
1237+-- @
1238+-- fromFoldable = 'Prelude.foldr' 'cons' 'nil'
1239+-- @
1240+--
1241+-- Construct a stream from a 'Foldable' containing pure values:
1242+--
1243+-- @since 0.2.0
1244+{-# INLINE fromFoldable #-}
1245+fromFoldable :: Foldable f => f a -> Stream m a
1246+fromFoldable = Prelude.foldr cons nil
1247+
1248+{-# INLINE fromFoldableM #-}
1249+fromFoldableM :: (Foldable f, Monad m) => f (m a) -> Stream m a
1250+fromFoldableM = Prelude.foldr consM nil
1251+
1252+-------------------------------------------------------------------------------
1253+-- Deconstruction
1254+-------------------------------------------------------------------------------
1255+
1256+{-# INLINE uncons #-}
1257+uncons :: Monad m => Stream m a -> m (Maybe (a, Stream m a))
1258+uncons m =
1259+ let stop = return Nothing
1260+ single a = return (Just (a, nil))
1261+ yieldk a r = return (Just (a, r))
1262+ in foldStream defState yieldk single stop m
1263+
1264+{-# INLINE tail #-}
1265+tail :: Monad m => Stream m a -> m (Maybe (Stream m a))
1266+tail =
1267+ let stop = return Nothing
1268+ single _ = return $ Just nil
1269+ yieldk _ r = return $ Just r
1270+ in foldStream defState yieldk single stop
1271+
1272+{-# INLINE init #-}
1273+init :: Monad m => Stream m a -> m (Maybe (Stream m a))
1274+init = go1
1275+ where
1276+ go1 m1 = do
1277+ r <- uncons m1
1278+ case r of
1279+ Nothing -> return Nothing
1280+ Just (h, t) -> return . Just $ go h t
1281+ go p m1 = mkStream $ \_ yld sng stp ->
1282+ let single _ = sng p
1283+ yieldk a x = yld p $ go a x
1284+ in foldStream defState yieldk single stp m1
1285+
1286+------------------------------------------------------------------------------
1287+-- Reordering
1288+------------------------------------------------------------------------------
1289+
1290+-- | Lazy left fold to a stream.
1291+{-# INLINE foldlS #-}
1292+foldlS ::
1293+ (Stream m b -> a -> Stream m b) -> Stream m b -> Stream m a -> Stream m b
1294+foldlS step = go
1295+ where
1296+ go acc rest = mkStream $ \st yld sng stp ->
1297+ let run x = foldStream st yld sng stp x
1298+ stop = run acc
1299+ single a = run $ step acc a
1300+ yieldk a r = run $ go (step acc a) r
1301+ in foldStream (adaptState st) yieldk single stop rest
1302+
1303+{-# INLINE reverse #-}
1304+reverse :: Stream m a -> Stream m a
1305+reverse = foldlS (flip cons) nil
src/Streamly/Internal/Data/Stream/Zip.hs+43−120
@@ -15,23 +15,20 @@
15--
15--
16module Streamly.Internal.Data.Stream.Zip
16module Streamly.Internal.Data.Stream.Zip
17 (
17 (
18− ZipSerialM
18+ ZipSerialM (..)
19 , ZipSerial
19 , ZipSerial
20− , fromZipSerial
20+ , consMZip
21+ , zipWithK
22+ , zipWithMK
21
23
22− , ZipAsyncM
24+ , ZipAsyncM(..)
23 , ZipAsync
25 , ZipAsync
24− , fromZipAsync
26+ , consMZipAsync
25−
27+ , zipAsyncWithK
26− , zipWith
28+ , zipAsyncWithMK
27− , zipWithM
28− , zipAsyncWith
29− , zipAsyncWithM
30
29
31 -- * Deprecated
30 -- * Deprecated
32 , ZipStream
31 , ZipStream
33− , zipping
34− , zippingAsync
35 )
32 )
36where
33where
37
34
@@ -51,23 +48,18 @@ import GHC.Exts (IsList(..), IsString(..))
51import Text.Read
48import Text.Read
52 ( Lexeme(Ident), lexP, parens, prec, readPrec, readListPrec
49 ( Lexeme(Ident), lexP, parens, prec, readPrec, readListPrec
53 , readListPrecDefault)
50 , readListPrecDefault)
54−import Streamly.Internal.Control.Concurrent (MonadAsync)
55import Streamly.Internal.BaseCompat ((#.), errorWithoutStackTrace, oneShot)
51import Streamly.Internal.BaseCompat ((#.), errorWithoutStackTrace, oneShot)
56−import Streamly.Internal.Data.Stream.StreamK (IsStream(..), Stream)
52+import Streamly.Internal.Control.Concurrent (MonadAsync)
57import Streamly.Internal.Data.Maybe.Strict (Maybe'(..), toMaybe)
53import Streamly.Internal.Data.Maybe.Strict (Maybe'(..), toMaybe)
54+import Streamly.Internal.Data.Stream.Serial (SerialT(..))
55+import Streamly.Internal.Data.Stream.StreamK.Type (Stream)
58
56
59import qualified Streamly.Internal.Data.Stream.Parallel as Par
57import qualified Streamly.Internal.Data.Stream.Parallel as Par
60import qualified Streamly.Internal.Data.Stream.Prelude as P
58import qualified Streamly.Internal.Data.Stream.Prelude as P
61− (cmpBy, eqBy, foldl', foldr, fromList, toList, fromStreamS, toStreamS)
59+ (cmpBy, eqBy, foldl', foldr, fromList, toList)
62−import qualified Streamly.Internal.Data.Stream.StreamK as K (repeat)
63import qualified Streamly.Internal.Data.Stream.StreamK.Type as K
60import qualified Streamly.Internal.Data.Stream.StreamK.Type as K
64−import qualified Streamly.Internal.Data.Stream.StreamD as D (zipWithM)
61+import qualified Streamly.Internal.Data.Stream.StreamD as D
65−import qualified Streamly.Internal.Data.Stream.StreamD.Type as D
66−#ifdef USE_STREAMK_ONLY
67−import qualified Streamly.Internal.Data.Stream.StreamK as S (zipWith, zipWithM)
62+import qualified Streamly.Internal.Data.Stream.Serial as Serial
68−#else
69−import qualified Streamly.Internal.Data.Stream.StreamD as S (zipWith, zipWithM)
70−#endif
71
63
72import Prelude hiding (map, repeat, zipWith, errorWithoutStackTrace)
64import Prelude hiding (map, repeat, zipWith, errorWithoutStackTrace)
73
65
@@ -83,29 +75,16 @@ import Prelude hiding (map, repeat, zipWith, errorWithoutStackTrace)
83-- return n -- IO Int
75-- return n -- IO Int
84-- :}
76-- :}
85
77
86−-- | Like 'zipWith' but using a monadic zipping function.
78+{-# INLINE zipWithMK #-}
87−--
79+zipWithMK :: Monad m =>
88−-- @since 0.4.0
80+ (a -> b -> m c) -> Stream m a -> Stream m b -> Stream m c
89−{-# INLINABLE zipWithM #-}
81+zipWithMK f m1 m2 =
90−zipWithM :: (IsStream t, Monad m) => (a -> b -> m c) -> t m a -> t m b -> t m c
82+ D.toStreamK $ D.zipWithM f (D.fromStreamK m1) (D.fromStreamK m2)
91−zipWithM f m1 m2 = P.fromStreamS $ S.zipWithM f (P.toStreamS m1) (P.toStreamS m2)
92
83
93−-- | Stream @a@ is evaluated first, followed by stream @b@, the resulting
84+{-# INLINE zipWithK #-}
94−-- elements @a@ and @b@ are then zipped using the supplied zip function and the
85+zipWithK :: Monad m
95−-- result @c@ is yielded to the consumer.
86+ => (a -> b -> c) -> Stream m a -> Stream m b -> Stream m c
96−--
87+zipWithK f = zipWithMK (\a b -> return (f a b))
97−-- If stream @a@ or stream @b@ ends, the zipped stream ends. If stream @b@ ends
98−-- first, the element @a@ from previous evaluation of stream @a@ is discarded.
99−--
100−-- @
101−-- > S.toList $ S.zipWith (+) (S.fromList [1,2,3]) (S.fromList [4,5,6])
102−-- [5,7,9]
103−-- @
104−--
105−-- @since 0.1.0
106−{-# INLINABLE zipWith #-}
107−zipWith :: (IsStream t, Monad m) => (a -> b -> c) -> t m a -> t m b -> t m c
108−zipWith f m1 m2 = P.fromStreamS $ S.zipWith f (P.toStreamS m1) (P.toStreamS m2)
109
88
110------------------------------------------------------------------------------
89------------------------------------------------------------------------------
111-- Parallel Zipping
90-- Parallel Zipping
@@ -114,12 +93,12 @@ zipWith f m1 m2 = P.fromStreamS $ S.zipWith f (P.toStreamS m1) (P.toStreamS m2)
114-- | Like 'zipAsyncWith' but with a monadic zipping function.
93-- | Like 'zipAsyncWith' but with a monadic zipping function.
115--
94--
116-- @since 0.4.0
95-- @since 0.4.0
117−{-# INLINE zipAsyncWithM #-}
96+{-# INLINE zipAsyncWithMK #-}
118−zipAsyncWithM :: (IsStream t, MonadAsync m)
97+zipAsyncWithMK :: MonadAsync m
119− => (a -> b -> m c) -> t m a -> t m b -> t m c
98+ => (a -> b -> m c) -> Stream m a -> Stream m b -> Stream m c
120−zipAsyncWithM f m1 m2 = D.fromStreamD $
99+zipAsyncWithMK f m1 m2 = D.toStreamK $
121− D.zipWithM f (Par.mkParallelD $ D.toStreamD m1)
100+ D.zipWithM f (Par.mkParallelD $ D.fromStreamK m1)
122− (Par.mkParallelD $ D.toStreamD m2)
101+ (Par.mkParallelD $ D.fromStreamK m2)
123
102
124-- XXX Should we rename this to zipParWith or zipParallelWith? This can happen
103-- XXX Should we rename this to zipParWith or zipParallelWith? This can happen
125-- along with the change of behvaior to end the stream concurrently.
104-- along with the change of behvaior to end the stream concurrently.
@@ -136,10 +115,10 @@ zipAsyncWithM f m1 m2 = D.fromStreamD $
136-- as soon as any of the stream end is detected.
115-- as soon as any of the stream end is detected.
137--
116--
138-- @since 0.1.0
117-- @since 0.1.0
139−{-# INLINE zipAsyncWith #-}
118+{-# INLINE zipAsyncWithK #-}
140−zipAsyncWith :: (IsStream t, MonadAsync m)
119+zipAsyncWithK :: MonadAsync m
141− => (a -> b -> c) -> t m a -> t m b -> t m c
120+ => (a -> b -> c) -> Stream m a -> Stream m b -> Stream m c
142−zipAsyncWith f = zipAsyncWithM (\a b -> return (f a b))
121+zipAsyncWithK f = zipAsyncWithMK (\a b -> return (f a b))
143
122
144------------------------------------------------------------------------------
123------------------------------------------------------------------------------
145-- Serially Zipping Streams
124-- Serially Zipping Streams
@@ -178,49 +157,21 @@ type ZipStream = ZipSerialM
178-- @since 0.8.0
157-- @since 0.8.0
179type ZipSerial = ZipSerialM IO
158type ZipSerial = ZipSerialM IO
180
159
181−-- | Fix the type of a polymorphic stream as 'ZipSerialM'.
182−--
183−-- /Since: 0.2.0 ("Streamly")/
184−--
185−-- @since 0.8.0
186−fromZipSerial :: IsStream t => ZipSerialM m a -> t m a
187−fromZipSerial = K.adapt
188−
189−-- | Same as 'fromZipSerial'.
190−--
191−-- @since 0.1.0
192−{-# DEPRECATED zipping "Please use fromZipSerial instead." #-}
193−zipping :: IsStream t => ZipSerialM m a -> t m a
194−zipping = fromZipSerial
195−
196consMZip :: Monad m => m a -> ZipSerialM m a -> ZipSerialM m a
160consMZip :: Monad m => m a -> ZipSerialM m a -> ZipSerialM m a
197−consMZip m ms = fromStream $ K.consMStream m (toStream ms)
161+consMZip m (ZipSerialM r) = ZipSerialM $ K.consM m r
198−
199−instance IsStream ZipSerialM where
200− toStream = getZipSerialM
201− fromStream = ZipSerialM
202−
203− {-# INLINE consM #-}
204− {-# SPECIALIZE consM :: IO a -> ZipSerialM IO a -> ZipSerialM IO a #-}
205− consM :: Monad m => m a -> ZipSerialM m a -> ZipSerialM m a
206− consM = consMZip
207−
208− {-# INLINE (|:) #-}
209− {-# SPECIALIZE (|:) :: IO a -> ZipSerialM IO a -> ZipSerialM IO a #-}
210− (|:) :: Monad m => m a -> ZipSerialM m a -> ZipSerialM m a
211− (|:) = consMZip
212
162
213LIST_INSTANCES(ZipSerialM)
163LIST_INSTANCES(ZipSerialM)
214NFDATA1_INSTANCE(ZipSerialM)
164NFDATA1_INSTANCE(ZipSerialM)
215
165
216instance Monad m => Functor (ZipSerialM m) where
166instance Monad m => Functor (ZipSerialM m) where
217 {-# INLINE fmap #-}
167 {-# INLINE fmap #-}
218− fmap f (ZipSerialM m) = D.fromStreamD $ D.mapM (return . f) $ D.toStreamD m
168+ fmap f (ZipSerialM m) = ZipSerialM $ getSerialT $ fmap f (SerialT m)
219
169
220instance Monad m => Applicative (ZipSerialM m) where
170instance Monad m => Applicative (ZipSerialM m) where
221− pure = ZipSerialM . K.repeat
171+ pure = ZipSerialM . getSerialT . Serial.repeat
172+
222 {-# INLINE (<*>) #-}
173 {-# INLINE (<*>) #-}
223− (<*>) = zipWith id
174+ ZipSerialM m1 <*> ZipSerialM m2 = ZipSerialM $ zipWithK id m1 m2
224
175
225FOLDABLE_INSTANCE(ZipSerialM)
176FOLDABLE_INSTANCE(ZipSerialM)
226TRAVERSABLE_INSTANCE(ZipSerialM)
177TRAVERSABLE_INSTANCE(ZipSerialM)
@@ -257,43 +208,15 @@ newtype ZipAsyncM m a = ZipAsyncM {getZipAsyncM :: Stream m a}
257-- @since 0.8.0
208-- @since 0.8.0
258type ZipAsync = ZipAsyncM IO
209type ZipAsync = ZipAsyncM IO
259
210
260−-- | Fix the type of a polymorphic stream as 'ZipAsyncM'.
261−--
262−-- /Since: 0.2.0 ("Streamly")/
263−--
264−-- @since 0.8.0
265−fromZipAsync :: IsStream t => ZipAsyncM m a -> t m a
266−fromZipAsync = K.adapt
267−
268−-- | Same as 'fromZipAsync'.
269−--
270−-- @since 0.1.0
271−{-# DEPRECATED zippingAsync "Please use fromZipAsync instead." #-}
272−zippingAsync :: IsStream t => ZipAsyncM m a -> t m a
273−zippingAsync = fromZipAsync
274−
275consMZipAsync :: Monad m => m a -> ZipAsyncM m a -> ZipAsyncM m a
211consMZipAsync :: Monad m => m a -> ZipAsyncM m a -> ZipAsyncM m a
276−consMZipAsync m ms = fromStream $ K.consMStream m (toStream ms)
212+consMZipAsync m (ZipAsyncM r) = ZipAsyncM $ K.consM m r
277−
278−instance IsStream ZipAsyncM where
279− toStream = getZipAsyncM
280− fromStream = ZipAsyncM
281−
282− {-# INLINE consM #-}
283− {-# SPECIALIZE consM :: IO a -> ZipAsyncM IO a -> ZipAsyncM IO a #-}
284− consM :: Monad m => m a -> ZipAsyncM m a -> ZipAsyncM m a
285− consM = consMZipAsync
286−
287− {-# INLINE (|:) #-}
288− {-# SPECIALIZE (|:) :: IO a -> ZipAsyncM IO a -> ZipAsyncM IO a #-}
289− (|:) :: Monad m => m a -> ZipAsyncM m a -> ZipAsyncM m a
290− (|:) = consMZipAsync
291
213
292instance Monad m => Functor (ZipAsyncM m) where
214instance Monad m => Functor (ZipAsyncM m) where
293 {-# INLINE fmap #-}
215 {-# INLINE fmap #-}
294− fmap f (ZipAsyncM m) = D.fromStreamD $ D.mapM (return . f) $ D.toStreamD m
216+ fmap f (ZipAsyncM m) = ZipAsyncM $ getSerialT $ fmap f (SerialT m)
295
217
296instance MonadAsync m => Applicative (ZipAsyncM m) where
218instance MonadAsync m => Applicative (ZipAsyncM m) where
297− pure = ZipAsyncM . K.repeat
219+ pure = ZipAsyncM . getSerialT . Serial.repeat
220+
298 {-# INLINE (<*>) #-}
221 {-# INLINE (<*>) #-}
299− m1 <*> m2 = zipAsyncWith id m1 m2
222+ ZipAsyncM m1 <*> ZipAsyncM m2 = ZipAsyncM $ zipAsyncWithK id m1 m2
src/Streamly/Internal/Data/Unfold.hs+4−3
@@ -255,14 +255,15 @@ import Streamly.Internal.Control.Concurrent (MonadAsync)
255import Streamly.Internal.Data.Fold.Type (Fold(..))
255import Streamly.Internal.Data.Fold.Type (Fold(..))
256import Streamly.Internal.Data.IOFinalizer
256import Streamly.Internal.Data.IOFinalizer
257 (newIOFinalizer, runIOFinalizer, clearingIOFinalizer)
257 (newIOFinalizer, runIOFinalizer, clearingIOFinalizer)
258+import Streamly.Internal.Data.Stream.IsStream.Type (IsStream)
258import Streamly.Internal.Data.Stream.StreamD.Type (Stream(..), Step(..))
259import Streamly.Internal.Data.Stream.StreamD.Type (Stream(..), Step(..))
259import Streamly.Internal.Data.SVar.Type (defState)
260import Streamly.Internal.Data.SVar.Type (defState)
260
261
261import qualified Control.Monad.Catch as MC
262import qualified Control.Monad.Catch as MC
262import qualified Data.Tuple as Tuple
263import qualified Data.Tuple as Tuple
263import qualified Streamly.Internal.Data.Fold.Type as FL
264import qualified Streamly.Internal.Data.Fold.Type as FL
265+import qualified Streamly.Internal.Data.Stream.IsStream.Type as IsStream
264import qualified Streamly.Internal.Data.Stream.StreamD.Type as D
266import qualified Streamly.Internal.Data.Stream.StreamD.Type as D
265−import qualified Streamly.Internal.Data.Stream.StreamK as K (uncons)
266import qualified Streamly.Internal.Data.Stream.StreamK.Type as K
267import qualified Streamly.Internal.Data.Stream.StreamK.Type as K
267
268
268import Streamly.Internal.Data.Unfold.Enumeration
269import Streamly.Internal.Data.Unfold.Enumeration
@@ -485,8 +486,8 @@ fromStreamK = Unfold step return
485-- /Since: 0.8.0/
486-- /Since: 0.8.0/
486--
487--
487{-# INLINE_NORMAL fromStream #-}
488{-# INLINE_NORMAL fromStream #-}
488−fromStream :: (K.IsStream t, Monad m) => Unfold m (t m a) a
489+fromStream :: (IsStream t, Monad m) => Unfold m (t m a) a
489−fromStream = lmap K.toStream fromStreamK
490+fromStream = lmap IsStream.toStream fromStreamK
490
491
491-------------------------------------------------------------------------------
492-------------------------------------------------------------------------------
492-- Unfolds
493-- Unfolds
src/Streamly/Internal/FileSystem/Dir.hs+1−1
@@ -68,7 +68,7 @@ import Streamly.Internal.Data.Unfold.Type (Unfold(..))
68-- (Array(..), writeNUnsafe, defaultChunkSize, shrinkToFit,
68-- (Array(..), writeNUnsafe, defaultChunkSize, shrinkToFit,
69-- lpackArraysChunksOf)
69-- lpackArraysChunksOf)
70-- import Streamly.Internal.Data.Stream.Serial (SerialT)
70-- import Streamly.Internal.Data.Stream.Serial (SerialT)
71−import Streamly.Internal.Data.Stream.StreamK.Type (IsStream)
71+import Streamly.Internal.Data.Stream.IsStream.Type (IsStream)
72-- import Streamly.String (encodeUtf8, decodeUtf8, foldLines)
72-- import Streamly.String (encodeUtf8, decodeUtf8, foldLines)
73
73
74-- import qualified Streamly.Data.Fold as FL
74-- import qualified Streamly.Data.Fold as FL
src/Streamly/Internal/FileSystem/FD.hs+4−5
@@ -135,12 +135,11 @@ import Streamly.Internal.Data.Array.Foreign.Type
135import Streamly.Internal.Data.Array.Foreign.Mut.Type (mutableArray)
135import Streamly.Internal.Data.Array.Foreign.Mut.Type (mutableArray)
136import Streamly.Internal.System.IO (defaultChunkSize)
136import Streamly.Internal.System.IO (defaultChunkSize)
137import Streamly.Internal.Data.Stream.Serial (SerialT)
137import Streamly.Internal.Data.Stream.Serial (SerialT)
138−import Streamly.Internal.Data.Stream.StreamK.Type (IsStream, mkStream)
138+import Streamly.Internal.Data.Stream.IsStream.Type
139−
139+ (IsStream, mkStream, fromStreamD)
140#if !defined(mingw32_HOST_OS)
140#if !defined(mingw32_HOST_OS)
141+import Streamly.Internal.Data.Stream.IsStream.Type (toStreamD)
141import Streamly.Internal.System.IOVec (groupIOVecsOf)
142import Streamly.Internal.System.IOVec (groupIOVecsOf)
142−import Streamly.Internal.Data.Stream.StreamD (toStreamD)
143−import Streamly.Internal.Data.Stream.StreamD.Type (fromStreamD)
144import qualified Streamly.Internal.FileSystem.FDIO as RawIO hiding (write)
143import qualified Streamly.Internal.FileSystem.FDIO as RawIO hiding (write)
145import qualified Streamly.Internal.System.IOVec.Type as RawIO
144import qualified Streamly.Internal.System.IOVec.Type as RawIO
146#endif
145#endif
@@ -290,7 +289,7 @@ _readArraysOfUpto size h = go
290{-# INLINE_NORMAL readArraysOfUpto #-}
289{-# INLINE_NORMAL readArraysOfUpto #-}
291readArraysOfUpto :: (IsStream t, MonadIO m)
290readArraysOfUpto :: (IsStream t, MonadIO m)
292 => Int -> Handle -> t m (Array Word8)
291 => Int -> Handle -> t m (Array Word8)
293−readArraysOfUpto size h = D.fromStreamD (D.Stream step ())
292+readArraysOfUpto size h = fromStreamD (D.Stream step ())
294 where
293 where
295 {-# INLINE_LATE step #-}
294 {-# INLINE_LATE step #-}
296 step _ _ = do
295 step _ _ = do
src/Streamly/Internal/FileSystem/File.hs+2−2
@@ -99,17 +99,17 @@ import Streamly.Internal.Data.Fold.Type (Fold(..))
99import Streamly.Internal.Data.Unfold.Type (Unfold(..))
99import Streamly.Internal.Data.Unfold.Type (Unfold(..))
100import Streamly.Internal.Data.Array.Foreign.Type (Array(..), writeNUnsafe)
100import Streamly.Internal.Data.Array.Foreign.Type (Array(..), writeNUnsafe)
101import Streamly.Internal.Data.Stream.Serial (SerialT)
101import Streamly.Internal.Data.Stream.Serial (SerialT)
102−import Streamly.Internal.Data.Stream.StreamK.Type (IsStream)
102+import Streamly.Internal.Data.Stream.IsStream.Type (IsStream)
103-- import Streamly.Data.Fold (Fold)
103-- import Streamly.Data.Fold (Fold)
104-- import Streamly.String (encodeUtf8, decodeUtf8, foldLines)
104-- import Streamly.String (encodeUtf8, decodeUtf8, foldLines)
105import Streamly.Internal.System.IO (defaultChunkSize)
105import Streamly.Internal.System.IO (defaultChunkSize)
106
106
107+import qualified Streamly.Internal.Data.Array.Foreign as A
107import qualified Streamly.Internal.Data.Fold.Type as FL
108import qualified Streamly.Internal.Data.Fold.Type as FL
108import qualified Streamly.Internal.Data.Unfold as UF
109import qualified Streamly.Internal.Data.Unfold as UF
109import qualified Streamly.Internal.FileSystem.Handle as FH
110import qualified Streamly.Internal.FileSystem.Handle as FH
110import qualified Streamly.Internal.Data.Array.Stream.Foreign as AS
111import qualified Streamly.Internal.Data.Array.Stream.Foreign as AS
111import qualified Streamly.Internal.Data.Stream.IsStream as S
112import qualified Streamly.Internal.Data.Stream.IsStream as S
112−import qualified Streamly.Data.Array.Foreign as A
113
113
114-------------------------------------------------------------------------------
114-------------------------------------------------------------------------------
115-- References
115-- References
src/Streamly/Internal/FileSystem/Handle.hs+8−7
@@ -110,25 +110,26 @@ import System.IO (Handle, SeekMode(..), hGetBufSome, hPutBuf, hSeek)
110import Prelude hiding (read)
110import Prelude hiding (read)
111
111
112import Streamly.Internal.BaseCompat
112import Streamly.Internal.BaseCompat
113−import Streamly.Data.Fold (Fold)
113+import Streamly.Internal.Data.Fold (Fold)
114import Streamly.Internal.Data.Fold.Type (Fold2(..))
114import Streamly.Internal.Data.Fold.Type (Fold2(..))
115import Streamly.Internal.Data.Unfold.Type (Unfold(..))
115import Streamly.Internal.Data.Unfold.Type (Unfold(..))
116import Streamly.Internal.Data.Array.Foreign.Type
116import Streamly.Internal.Data.Array.Foreign.Type
117 (Array(..), writeNUnsafe, unsafeFreezeWithShrink)
117 (Array(..), writeNUnsafe, unsafeFreezeWithShrink)
118import Streamly.Internal.Data.Array.Foreign.Mut.Type (mutableArray)
118import Streamly.Internal.Data.Array.Foreign.Mut.Type (mutableArray)
119import Streamly.Internal.Data.Stream.Serial (SerialT)
119import Streamly.Internal.Data.Stream.Serial (SerialT)
120−import Streamly.Internal.Data.Stream.StreamK.Type (IsStream, mkStream)
120+import Streamly.Internal.Data.Stream.IsStream.Type
121+ (IsStream, mkStream, fromStreamD)
121import Streamly.Internal.Data.Array.Stream.Foreign (lpackArraysChunksOf)
122import Streamly.Internal.Data.Array.Stream.Foreign (lpackArraysChunksOf)
122-- import Streamly.String (encodeUtf8, decodeUtf8, foldLines)
123-- import Streamly.String (encodeUtf8, decodeUtf8, foldLines)
123import Streamly.Internal.System.IO (defaultChunkSize)
124import Streamly.Internal.System.IO (defaultChunkSize)
124
125
125−import qualified Streamly.Data.Fold as FL
126+import qualified Streamly.Internal.Data.Array.Foreign as A
126−import qualified Streamly.Internal.Data.Fold.Type as FL
127−import qualified Streamly.Internal.Data.Unfold as UF
128import qualified Streamly.Internal.Data.Array.Stream.Foreign as AS
127import qualified Streamly.Internal.Data.Array.Stream.Foreign as AS
128+import qualified Streamly.Internal.Data.Fold as FL
129+import qualified Streamly.Internal.Data.Fold.Type as FL
129import qualified Streamly.Internal.Data.Stream.IsStream as S
130import qualified Streamly.Internal.Data.Stream.IsStream as S
130−import qualified Streamly.Data.Array.Foreign as A
131import qualified Streamly.Internal.Data.Stream.StreamD.Type as D
131import qualified Streamly.Internal.Data.Stream.StreamD.Type as D
132+import qualified Streamly.Internal.Data.Unfold as UF
132
133
133-- $setup
134-- $setup
134-- >>> import qualified Streamly.Data.Array.Foreign as Array
135-- >>> import qualified Streamly.Data.Array.Foreign as Array
@@ -219,7 +220,7 @@ _toChunksWithBufferOf size h = go
219{-# INLINE_NORMAL toChunksWithBufferOf #-}
220{-# INLINE_NORMAL toChunksWithBufferOf #-}
220toChunksWithBufferOf :: (IsStream t, MonadIO m) =>
221toChunksWithBufferOf :: (IsStream t, MonadIO m) =>
221 Int -> Handle -> t m (Array Word8)
222 Int -> Handle -> t m (Array Word8)
222−toChunksWithBufferOf size h = D.fromStreamD (D.Stream step ())
223+toChunksWithBufferOf size h = fromStreamD (D.Stream step ())
223 where
224 where
224 {-# INLINE_LATE step #-}
225 {-# INLINE_LATE step #-}
225 step _ _ = do
226 step _ _ = do
src/Streamly/Internal/Network/Inet/TCP.hs+3−3
@@ -106,8 +106,8 @@ import Prelude hiding (read)
106import Streamly.Internal.Control.Concurrent (MonadAsync, fork)
106import Streamly.Internal.Control.Concurrent (MonadAsync, fork)
107import Streamly.Internal.Data.Array.Foreign.Type (Array(..), writeNUnsafe)
107import Streamly.Internal.Data.Array.Foreign.Type (Array(..), writeNUnsafe)
108import Streamly.Internal.Data.Fold.Type (Fold(..))
108import Streamly.Internal.Data.Fold.Type (Fold(..))
109+import Streamly.Internal.Data.Stream.IsStream.Type (IsStream)
109import Streamly.Internal.Data.Stream.Serial (SerialT)
110import Streamly.Internal.Data.Stream.Serial (SerialT)
110−import Streamly.Internal.Data.Stream.StreamK.Type (IsStream)
111import Streamly.Internal.Data.Tuple.Strict (Tuple'(..))
111import Streamly.Internal.Data.Tuple.Strict (Tuple'(..))
112import Streamly.Internal.Data.Unfold.Type (Unfold(..))
112import Streamly.Internal.Data.Unfold.Type (Unfold(..))
113import Streamly.Internal.Network.Socket (SockSpec(..), accept, connections)
113import Streamly.Internal.Network.Socket (SockSpec(..), accept, connections)
@@ -121,7 +121,6 @@ import qualified Streamly.Internal.Data.Array.Foreign as A
121import qualified Streamly.Internal.Data.Array.Stream.Foreign as AS
121import qualified Streamly.Internal.Data.Array.Stream.Foreign as AS
122import qualified Streamly.Internal.Data.Fold.Type as FL
122import qualified Streamly.Internal.Data.Fold.Type as FL
123import qualified Streamly.Internal.Data.Stream.IsStream as S
123import qualified Streamly.Internal.Data.Stream.IsStream as S
124−import qualified Streamly.Network.Socket as SK
125import qualified Streamly.Internal.Network.Socket as ISK
124import qualified Streamly.Internal.Network.Socket as ISK
126
125
127-------------------------------------------------------------------------------
126-------------------------------------------------------------------------------
@@ -356,7 +355,8 @@ writeChunks addr port = Fold step initial extract
356 where
355 where
357 initial = do
356 initial = do
358 skt <- liftIO (connect addr port)
357 skt <- liftIO (connect addr port)
358+ fld <- FL.initialize (ISK.writeChunks skt)
359− fld <- FL.initialize (SK.writeChunks skt) `MC.onException` liftIO (Net.close skt)
359+ `MC.onException` liftIO (Net.close skt)
360 return $ FL.Partial (Tuple' fld skt)
360 return $ FL.Partial (Tuple' fld skt)
361 step (Tuple' fld skt) x = do
361 step (Tuple' fld skt) x = do
362 r <- FL.runStep fld x `MC.onException` liftIO (Net.close skt)
362 r <- FL.runStep fld x `MC.onException` liftIO (Net.close skt)
src/Streamly/Internal/Network/Socket.hs+12−11
@@ -86,24 +86,25 @@ import Prelude hiding (read)
86import qualified Network.Socket as Net
86import qualified Network.Socket as Net
87
87
88import Streamly.Internal.BaseCompat
88import Streamly.Internal.BaseCompat
89−import Streamly.Internal.Data.Unfold.Type (Unfold(..))
89+import Streamly.Internal.Control.Concurrent (MonadAsync)
90−import Streamly.Internal.Data.Array.Stream.Foreign (lpackArraysChunksOf)
91−import Streamly.Internal.Data.Array.Foreign.Type (Array(..))
92import Streamly.Internal.Data.Array.Foreign.Mut.Type (mutableArray)
90import Streamly.Internal.Data.Array.Foreign.Mut.Type (mutableArray)
93−import Streamly.Internal.Data.Stream.IsStream (MonadAsync)
91+import Streamly.Internal.Data.Array.Foreign.Type (Array(..))
92+import Streamly.Internal.Data.Array.Stream.Foreign (lpackArraysChunksOf)
93+import Streamly.Internal.Data.Fold (Fold)
94+import Streamly.Internal.Data.Stream.IsStream.Type
95+ (IsStream, mkStream, fromStreamD)
94import Streamly.Internal.Data.Stream.Serial (SerialT)
96import Streamly.Internal.Data.Stream.Serial (SerialT)
95−import Streamly.Internal.Data.Stream.StreamK.Type (IsStream, mkStream)
97+import Streamly.Internal.Data.Unfold.Type (Unfold(..))
96−import Streamly.Data.Fold (Fold)
97-- import Streamly.String (encodeUtf8, decodeUtf8, foldLines)
98-- import Streamly.String (encodeUtf8, decodeUtf8, foldLines)
98import Streamly.Internal.System.IO (defaultChunkSize)
99import Streamly.Internal.System.IO (defaultChunkSize)
99
100
100−import qualified Streamly.Data.Fold as FL
101+import qualified Streamly.Internal.Data.Array.Foreign as A
101−import qualified Streamly.Internal.Data.Unfold as UF
102−import qualified Streamly.Data.Array.Foreign as A
103−import qualified Streamly.Internal.Data.Array.Stream.Foreign as AS
104import qualified Streamly.Internal.Data.Array.Foreign.Type as A
102import qualified Streamly.Internal.Data.Array.Foreign.Type as A
103+import qualified Streamly.Internal.Data.Array.Stream.Foreign as AS
104+import qualified Streamly.Internal.Data.Fold as FL
105import qualified Streamly.Internal.Data.Stream.IsStream as S
105import qualified Streamly.Internal.Data.Stream.IsStream as S
106import qualified Streamly.Internal.Data.Stream.StreamD.Type as D
106import qualified Streamly.Internal.Data.Stream.StreamD.Type as D
107+import qualified Streamly.Internal.Data.Unfold as UF
107
108
108-- | @'forSocketM' action socket@ runs the monadic computation @action@ passing
109-- | @'forSocketM' action socket@ runs the monadic computation @action@ passing
109-- the socket handle to it. The handle will be closed on exit from
110-- the socket handle to it. The handle will be closed on exit from
@@ -343,7 +344,7 @@ _readChunksUptoWith f size h = go
343toChunksWithBufferOf :: (IsStream t, MonadIO m)
344toChunksWithBufferOf :: (IsStream t, MonadIO m)
344 => Int -> Socket -> t m (Array Word8)
345 => Int -> Socket -> t m (Array Word8)
345-- toChunksWithBufferOf = _readChunksUptoWith readChunk
346-- toChunksWithBufferOf = _readChunksUptoWith readChunk
346−toChunksWithBufferOf size h = D.fromStreamD (D.Stream step ())
347+toChunksWithBufferOf size h = fromStreamD (D.Stream step ())
347 where
348 where
348 {-# INLINE_LATE step #-}
349 {-# INLINE_LATE step #-}
349 step _ _ = do
350 step _ _ = do
src/Streamly/Internal/Unicode/Char.hs+3−6
@@ -32,14 +32,11 @@ import Data.Char (isAsciiUpper, isAsciiLower, chr, ord)
32import Data.Typeable (Typeable)
32import Data.Typeable (Typeable)
33
33
34import Unicode.Char (DecomposeMode(..))
34import Unicode.Char (DecomposeMode(..))
35−import Streamly.Internal.Data.Stream.IsStream (IsStream)
35+import Streamly.Internal.Data.Stream.IsStream.Type
36+ (IsStream, fromStreamD, toStreamD)
36import Streamly.Internal.Data.Stream.StreamD (Stream(..), Step (..))
37import Streamly.Internal.Data.Stream.StreamD (Stream(..), Step (..))
37
38
38import qualified Unicode.Char as Char
39import qualified Unicode.Char as Char
39−import qualified Streamly.Internal.Data.Stream.StreamD as StreamD
40−
41−
42−-- import Streamly.Prelude (IsStream)
43
40
44-------------------------------------------------------------------------------
41-------------------------------------------------------------------------------
45-- Unicode aware operations on strings
42-- Unicode aware operations on strings
@@ -319,4 +316,4 @@ normalizeD NFC = partialComposeD . decomposeD False Canonical
319normalizeD NFKC = partialComposeD . decomposeD False Kompat
316normalizeD NFKC = partialComposeD . decomposeD False Kompat
320
317
321normalize :: (IsStream t, Monad m) => NormalizationMode -> t m Char -> t m Char
318normalize :: (IsStream t, Monad m) => NormalizationMode -> t m Char -> t m Char
322−normalize mode = StreamD.fromStreamD . normalizeD mode . StreamD.toStreamD
319+normalize mode = fromStreamD . normalizeD mode . toStreamD
src/Streamly/Internal/Unicode/Stream.hs+18−17
@@ -90,14 +90,15 @@ import GHC.ForeignPtr (ForeignPtr (..))
90import GHC.IO.Encoding.Failure (isSurrogate)
90import GHC.IO.Encoding.Failure (isSurrogate)
91import GHC.Ptr (Ptr (..), plusPtr)
91import GHC.Ptr (Ptr (..), plusPtr)
92import System.IO.Unsafe (unsafePerformIO)
92import System.IO.Unsafe (unsafePerformIO)
93−import Streamly.Data.Fold (Fold)
94−import Streamly.Data.Array.Foreign (Array)
93+import Streamly.Internal.Data.Array.Foreign (Array)
95−import Streamly.Internal.Data.Unfold (Unfold)
94+import Streamly.Internal.Data.Fold (Fold)
96−import Streamly.Internal.Data.SVar (adaptState)
97−import Streamly.Internal.Data.Stream.IsStream (IsStream)
95+import Streamly.Internal.Data.Stream.IsStream.Type
96+ (IsStream, fromStreamD, toStreamD, adapt)
98import Streamly.Internal.Data.Stream.Serial (SerialT)
97import Streamly.Internal.Data.Stream.Serial (SerialT)
99import Streamly.Internal.Data.Stream.StreamD (Stream(..), Step (..))
98import Streamly.Internal.Data.Stream.StreamD (Stream(..), Step (..))
99+import Streamly.Internal.Data.SVar (adaptState)
100import Streamly.Internal.Data.Tuple.Strict (Tuple'(..))
100import Streamly.Internal.Data.Tuple.Strict (Tuple'(..))
101+import Streamly.Internal.Data.Unfold (Unfold)
101import Streamly.Internal.System.IO (unsafeInlineIO)
102import Streamly.Internal.System.IO (unsafeInlineIO)
102
103
103import qualified Streamly.Internal.Data.Unfold as Unfold
104import qualified Streamly.Internal.Data.Unfold as Unfold
@@ -396,7 +397,7 @@ decodeUtf8EitherD = resumeDecodeUtf8EitherD 0 0
396{-# INLINE decodeUtf8Either #-}
397{-# INLINE decodeUtf8Either #-}
397decodeUtf8Either :: (Monad m, IsStream t)
398decodeUtf8Either :: (Monad m, IsStream t)
398 => t m Word8 -> t m (Either DecodeError Char)
399 => t m Word8 -> t m (Either DecodeError Char)
399−decodeUtf8Either = D.fromStreamD . decodeUtf8EitherD . D.toStreamD
400+decodeUtf8Either = fromStreamD . decodeUtf8EitherD . toStreamD
400
401
401-- |
402-- |
402--
403--
@@ -409,7 +410,7 @@ resumeDecodeUtf8Either
409 -> t m Word8
410 -> t m Word8
410 -> t m (Either DecodeError Char)
411 -> t m (Either DecodeError Char)
411resumeDecodeUtf8Either st cp =
412resumeDecodeUtf8Either st cp =
412− D.fromStreamD . resumeDecodeUtf8EitherD st cp . D.toStreamD
413+ fromStreamD . resumeDecodeUtf8EitherD st cp . toStreamD
413
414
414-------------------------------------------------------------------------------
415-------------------------------------------------------------------------------
415-- One shot decoding
416-- One shot decoding
@@ -533,7 +534,7 @@ decodeUtf8D = decodeUtf8WithD TransliterateCodingFailure
533-- /Since: 0.8.0 (Lenient Behaviour)/
534-- /Since: 0.8.0 (Lenient Behaviour)/
534{-# INLINE decodeUtf8 #-}
535{-# INLINE decodeUtf8 #-}
535decodeUtf8 :: (Monad m, IsStream t) => t m Word8 -> t m Char
536decodeUtf8 :: (Monad m, IsStream t) => t m Word8 -> t m Char
536−decodeUtf8 = D.fromStreamD . decodeUtf8D . D.toStreamD
537+decodeUtf8 = fromStreamD . decodeUtf8D . toStreamD
537
538
538{-# INLINE decodeUtf8D' #-}
539{-# INLINE decodeUtf8D' #-}
539decodeUtf8D' :: Monad m => Stream m Word8 -> Stream m Char
540decodeUtf8D' :: Monad m => Stream m Word8 -> Stream m Char
@@ -545,7 +546,7 @@ decodeUtf8D' = decodeUtf8WithD ErrorOnCodingFailure
545-- @since 0.8.0
546-- @since 0.8.0
546{-# INLINE decodeUtf8' #-}
547{-# INLINE decodeUtf8' #-}
547decodeUtf8' :: (Monad m, IsStream t) => t m Word8 -> t m Char
548decodeUtf8' :: (Monad m, IsStream t) => t m Word8 -> t m Char
548−decodeUtf8' = D.fromStreamD . decodeUtf8D' . D.toStreamD
549+decodeUtf8' = fromStreamD . decodeUtf8D' . toStreamD
549
550
550{-# INLINE decodeUtf8D_ #-}
551{-# INLINE decodeUtf8D_ #-}
551decodeUtf8D_ :: Monad m => Stream m Word8 -> Stream m Char
552decodeUtf8D_ :: Monad m => Stream m Word8 -> Stream m Char
@@ -557,7 +558,7 @@ decodeUtf8D_ = decodeUtf8WithD DropOnCodingFailure
557-- @since 0.8.0
558-- @since 0.8.0
558{-# INLINE decodeUtf8_ #-}
559{-# INLINE decodeUtf8_ #-}
559decodeUtf8_ :: (Monad m, IsStream t) => t m Word8 -> t m Char
560decodeUtf8_ :: (Monad m, IsStream t) => t m Word8 -> t m Char
560−decodeUtf8_ = D.fromStreamD . decodeUtf8D_ . D.toStreamD
561+decodeUtf8_ = fromStreamD . decodeUtf8D_ . toStreamD
561
562
562-- | Same as 'decodeUtf8'
563-- | Same as 'decodeUtf8'
563--
564--
@@ -715,7 +716,7 @@ decodeUtf8ArraysD = decodeUtf8ArraysWithD TransliterateCodingFailure
715decodeUtf8Arrays ::
716decodeUtf8Arrays ::
716 (MonadIO m, IsStream t) => t m (Array Word8) -> t m Char
717 (MonadIO m, IsStream t) => t m (Array Word8) -> t m Char
717decodeUtf8Arrays =
718decodeUtf8Arrays =
718− D.fromStreamD . decodeUtf8ArraysD . D.toStreamD
719+ fromStreamD . decodeUtf8ArraysD . toStreamD
719
720
720{-# INLINE decodeUtf8ArraysD' #-}
721{-# INLINE decodeUtf8ArraysD' #-}
721decodeUtf8ArraysD' ::
722decodeUtf8ArraysD' ::
@@ -729,7 +730,7 @@ decodeUtf8ArraysD' = decodeUtf8ArraysWithD ErrorOnCodingFailure
729-- /Pre-release/
730-- /Pre-release/
730{-# INLINE decodeUtf8Arrays' #-}
731{-# INLINE decodeUtf8Arrays' #-}
731decodeUtf8Arrays' :: (MonadIO m, IsStream t) => t m (Array Word8) -> t m Char
732decodeUtf8Arrays' :: (MonadIO m, IsStream t) => t m (Array Word8) -> t m Char
732−decodeUtf8Arrays' = D.fromStreamD . decodeUtf8ArraysD' . D.toStreamD
733+decodeUtf8Arrays' = fromStreamD . decodeUtf8ArraysD' . toStreamD
733
734
734{-# INLINE decodeUtf8ArraysD_ #-}
735{-# INLINE decodeUtf8ArraysD_ #-}
735decodeUtf8ArraysD_ ::
736decodeUtf8ArraysD_ ::
@@ -745,7 +746,7 @@ decodeUtf8ArraysD_ = decodeUtf8ArraysWithD DropOnCodingFailure
745decodeUtf8Arrays_ ::
746decodeUtf8Arrays_ ::
746 (MonadIO m, IsStream t) => t m (Array Word8) -> t m Char
747 (MonadIO m, IsStream t) => t m (Array Word8) -> t m Char
747decodeUtf8Arrays_ =
748decodeUtf8Arrays_ =
748− D.fromStreamD . decodeUtf8ArraysD_ . D.toStreamD
749+ fromStreamD . decodeUtf8ArraysD_ . toStreamD
749
750
750-------------------------------------------------------------------------------
751-------------------------------------------------------------------------------
751-- Encoding Unicode (UTF-8) Characters
752-- Encoding Unicode (UTF-8) Characters
@@ -867,7 +868,7 @@ encodeUtf8D' = encodeUtf8DGeneric ErrorInvalid
867-- @since 0.8.0
868-- @since 0.8.0
868{-# INLINE encodeUtf8' #-}
869{-# INLINE encodeUtf8' #-}
869encodeUtf8' :: (Monad m, IsStream t) => t m Char -> t m Word8
870encodeUtf8' :: (Monad m, IsStream t) => t m Char -> t m Word8
870−encodeUtf8' = D.fromStreamD . encodeUtf8D' . D.toStreamD
871+encodeUtf8' = fromStreamD . encodeUtf8D' . toStreamD
871
872
872-- | See section "3.9 Unicode Encoding Forms" in
873-- | See section "3.9 Unicode Encoding Forms" in
873-- https://www.unicode.org/versions/Unicode13.0.0/UnicodeStandard-13.0.pdf
874-- https://www.unicode.org/versions/Unicode13.0.0/UnicodeStandard-13.0.pdf
@@ -885,7 +886,7 @@ encodeUtf8D = encodeUtf8DGeneric ReplaceInvalid
885-- /Since: 0.8.0 (Lenient Behaviour)/
886-- /Since: 0.8.0 (Lenient Behaviour)/
886{-# INLINE encodeUtf8 #-}
887{-# INLINE encodeUtf8 #-}
887encodeUtf8 :: (Monad m, IsStream t) => t m Char -> t m Word8
888encodeUtf8 :: (Monad m, IsStream t) => t m Char -> t m Word8
888−encodeUtf8 = D.fromStreamD . encodeUtf8D . D.toStreamD
889+encodeUtf8 = fromStreamD . encodeUtf8D . toStreamD
889
890
890{-# INLINE_NORMAL encodeUtf8D_ #-}
891{-# INLINE_NORMAL encodeUtf8D_ #-}
891encodeUtf8D_ :: Monad m => Stream m Char -> Stream m Word8
892encodeUtf8D_ :: Monad m => Stream m Char -> Stream m Word8
@@ -897,7 +898,7 @@ encodeUtf8D_ = encodeUtf8DGeneric DropInvalid
897-- @since 0.8.0
898-- @since 0.8.0
898{-# INLINE encodeUtf8_ #-}
899{-# INLINE encodeUtf8_ #-}
899encodeUtf8_ :: (Monad m, IsStream t) => t m Char -> t m Word8
900encodeUtf8_ :: (Monad m, IsStream t) => t m Char -> t m Word8
900−encodeUtf8_ = D.fromStreamD . encodeUtf8D_ . D.toStreamD
901+encodeUtf8_ = fromStreamD . encodeUtf8D_ . toStreamD
901
902
902-- | Same as 'encodeUtf8'
903-- | Same as 'encodeUtf8'
903--
904--
@@ -932,7 +933,7 @@ encodeObjects :: (MonadIO m, IsStream t) =>
932 -> Unfold m a Char
933 -> Unfold m a Char
933 -> t m a
934 -> t m a
934 -> t m (Array Word8)
935 -> t m (Array Word8)
935−encodeObjects encode u = Serial.mapM (encodeObject encode u)
936+encodeObjects encode u = adapt . Serial.mapM (encodeObject encode u) . adapt
936
937
937-- | Encode a stream of 'String' using the supplied encoding scheme. Each
938-- | Encode a stream of 'String' using the supplied encoding scheme. Each
938-- string is encoded as an @Array Word8@.
939-- string is encoded as an @Array Word8@.
src/Streamly/Prelude.hs+1
@@ -936,6 +936,7 @@ module Streamly.Prelude
936 )
936 )
937where
937where
938
938
939+import Streamly.Internal.Control.Concurrent (MonadAsync)
939import Prelude
940import Prelude
940 hiding (filter, drop, dropWhile, take, takeWhile, zipWith, foldr,
941 hiding (filter, drop, dropWhile, take, takeWhile, zipWith, foldr,
941 foldl, map, mapM, mapM_, sequence, all, any, sum, product, elem,
942 foldl, map, mapM, mapM_, sequence, all, any, sum, product, elem,
streamly.cabal+10−6
@@ -77,6 +77,7 @@ extra-source-files:
77 docs/*.hs
77 docs/*.hs
78 docs/streamly-docs.cabal
78 docs/streamly-docs.cabal
79 src/Streamly/Internal/Data/Stream/Instances.hs
79 src/Streamly/Internal/Data/Stream/Instances.hs
80+ src/Streamly/Internal/Data/Stream/PreludeCommon.hs
80 src/Streamly/Internal/Data/Time/Clock/config-clock.h
81 src/Streamly/Internal/Data/Time/Clock/config-clock.h
81 src/Streamly/Internal/Data/Array/PrimInclude.hs
82 src/Streamly/Internal/Data/Array/PrimInclude.hs
82 src/Streamly/Internal/Data/Array/Prim/TypesInclude.hs
83 src/Streamly/Internal/Data/Array/Prim/TypesInclude.hs
@@ -263,6 +264,7 @@ common default-extensions
263 RecordWildCards
264 RecordWildCards
264 ScopedTypeVariables
265 ScopedTypeVariables
265 TupleSections
266 TupleSections
267+ TypeApplications
266 TypeFamilies
268 TypeFamilies
267 ViewPatterns
269 ViewPatterns
268
270
@@ -301,13 +303,11 @@ common lib-options
301library
303library
302 import: lib-options
304 import: lib-options
303
305
304− if impl(ghc >= 8.1)
305− default-extensions: TypeApplications
306 if impl(ghc >= 8.6)
306 if impl(ghc >= 8.6)
307 default-extensions: QuantifiedConstraints
307 default-extensions: QuantifiedConstraints
308
308
309 js-sources: jsbits/clock.js
309 js-sources: jsbits/clock.js
310− include-dirs: src
310+ include-dirs: src, src/Streamly/Internal/Data/Stream
311 if os(windows)
311 if os(windows)
312 c-sources: src/Streamly/Internal/Data/Time/Clock/Windows.c
312 c-sources: src/Streamly/Internal/Data/Time/Clock/Windows.c
313 exposed-modules: Streamly.Internal.FileSystem.Event.Windows
313 exposed-modules: Streamly.Internal.FileSystem.Event.Windows
@@ -412,7 +412,6 @@ library
412 , Streamly.Internal.Data.SmallArray.Type
412 , Streamly.Internal.Data.SmallArray.Type
413
413
414 -- streamly-base-streams
414 -- streamly-base-streams
415− , Streamly.Internal.Data.Stream.StreamK
416 -- StreamD depends on streamly-core-array
415 -- StreamD depends on streamly-core-array
417 , Streamly.Internal.Data.Stream.StreamD.Generate
416 , Streamly.Internal.Data.Stream.StreamD.Generate
418 , Streamly.Internal.Data.Stream.StreamD.Eliminate
417 , Streamly.Internal.Data.Stream.StreamD.Eliminate
@@ -434,6 +433,7 @@ library
434 , Streamly.Internal.Data.Fold.Tee
433 , Streamly.Internal.Data.Fold.Tee
435 , Streamly.Internal.Data.Fold
434 , Streamly.Internal.Data.Fold
436 , Streamly.Internal.Data.Fold.SVar
435 , Streamly.Internal.Data.Fold.SVar
436+ , Streamly.Internal.Data.Fold.Async
437 , Streamly.Internal.Data.Sink
437 , Streamly.Internal.Data.Sink
438 , Streamly.Internal.Data.Parser
438 , Streamly.Internal.Data.Parser
439 , Streamly.Internal.Data.Pipe
439 , Streamly.Internal.Data.Pipe
@@ -445,9 +445,11 @@ library
445 , Streamly.Internal.Data.Stream.Parallel
445 , Streamly.Internal.Data.Stream.Parallel
446 , Streamly.Internal.Data.Stream.Ahead
446 , Streamly.Internal.Data.Stream.Ahead
447 , Streamly.Internal.Data.Stream.Zip
447 , Streamly.Internal.Data.Stream.Zip
448+ , Streamly.Internal.Data.List
449+
450+ , Streamly.Internal.Data.Stream.IsStream.Type
448 , Streamly.Internal.Data.Stream.IsStream.Combinators
451 , Streamly.Internal.Data.Stream.IsStream.Combinators
449 , Streamly.Internal.Data.Stream.IsStream.Common
452 , Streamly.Internal.Data.Stream.IsStream.Common
450− , Streamly.Internal.Data.Stream.IsStream.Types
451 , Streamly.Internal.Data.Stream.IsStream.Enumeration
453 , Streamly.Internal.Data.Stream.IsStream.Enumeration
452 , Streamly.Internal.Data.Stream.IsStream.Generate
454 , Streamly.Internal.Data.Stream.IsStream.Generate
453 , Streamly.Internal.Data.Stream.IsStream.Eliminate
455 , Streamly.Internal.Data.Stream.IsStream.Eliminate
@@ -458,7 +460,6 @@ library
458 , Streamly.Internal.Data.Stream.IsStream.Lift
460 , Streamly.Internal.Data.Stream.IsStream.Lift
459 , Streamly.Internal.Data.Stream.IsStream.Top
461 , Streamly.Internal.Data.Stream.IsStream.Top
460 , Streamly.Internal.Data.Stream.IsStream
462 , Streamly.Internal.Data.Stream.IsStream
461− , Streamly.Internal.Data.List
462
463
463 -- streamly-arrays
464 -- streamly-arrays
464 -- May depend on streamly-core
465 -- May depend on streamly-core
@@ -501,6 +502,9 @@ library
501 , Streamly.Internal.Network.Socket
502 , Streamly.Internal.Network.Socket
502 , Streamly.Internal.Network.Inet.TCP
503 , Streamly.Internal.Network.Inet.TCP
503
504
505+ -- Only used for benchmarks
506+ , Streamly.Internal.Data.Stream.StreamK
507+
504 build-depends:
508 build-depends:
505 -- Core libraries shipped with ghc, the min and max
509 -- Core libraries shipped with ghc, the min and max
506 -- constraints of these libraries should match with
510 -- constraints of these libraries should match with
test/Streamly/Test/Prelude/WSerial.hs+2−1
@@ -60,7 +60,8 @@ interleaveCheck t f =
60wSerialMinLengthProp :: Property
60wSerialMinLengthProp :: Property
61wSerialMinLengthProp =
61wSerialMinLengthProp =
62 forAll (chooseInt (0, 10))
62 forAll (chooseInt (0, 10))
63+ $ \len ->
63− $ \len -> S.length (combined len) `shouldReturn` 2 * len + 1
64+ S.length (fromWSerial $ combined len) `shouldReturn` 2 * len + 1
64
65
65 where
66 where
66
67