on master help sign in
Move IsStream definition out of low level modules

The IsStream type class contains MonadAsync type in the consM method. This refactor allows lifting MonadAsync, therefore, dependency on monad-control out of the low level modules.

commit70e7f94691d93073f8e22d47ec0f0fe05ed50c84 authorHarendra Kumar <harendra@composewell.com> dateSat 4 Sep 2021, 11:17 (5 years ago) parentd8bc53b
64 files changed+3035−2452
.hlint.ignore+5 benchmark/Streamly/Benchmark/Data/Stream/StreamK.hs+27−16 benchmark/Streamly/Benchmark/Prelude/Async.hs+2−2 benchmark/Streamly/Benchmark/Prelude/Parallel.hs+1−2 benchmark/Streamly/Benchmark/Prelude/Serial/Transformation3.hs+1 benchmark/lib/Streamly/Benchmark/Prelude.hs+3−1 hie.yaml+8 src/Streamly.hs+12−13 src/Streamly/Internal/Data/Array.hs+8−9 src/Streamly/Internal/Data/Array/Foreign.hs+7−8 src/Streamly/Internal/Data/Array/Foreign/Mut/Type.hs+2−2 src/Streamly/Internal/Data/Array/Foreign/Type.hs+7−6 src/Streamly/Internal/Data/Array/Prim/TypesInclude.hs+3−3 src/Streamly/Internal/Data/Array/PrimInclude.hs+14−15 src/Streamly/Internal/Data/Array/Stream/Foreign.hs+18−17 src/Streamly/Internal/Data/Array/Stream/Mut/Foreign.hs+10−7 src/Streamly/Internal/Data/Fold.hs+4−6 src/Streamly/Internal/Data/Fold/Async.hs+120 src/Streamly/Internal/Data/Fold/Type.hs+1−94 src/Streamly/Internal/Data/IORef/Prim.hs−10 src/Streamly/Internal/Data/List.hs+22−17 src/Streamly/Internal/Data/SmallArray.hs+7−8 src/Streamly/Internal/Data/Stream/Ahead.hs+48−101 src/Streamly/Internal/Data/Stream/Async.hs+74−250 src/Streamly/Internal/Data/Stream/Instances.hs+13−11 src/Streamly/Internal/Data/Stream/IsStream.hs+4−2 src/Streamly/Internal/Data/Stream/IsStream/Combinators.hs+5−2 src/Streamly/Internal/Data/Stream/IsStream/Common.hs+128−15 src/Streamly/Internal/Data/Stream/IsStream/Eliminate.hs+49−25 src/Streamly/Internal/Data/Stream/IsStream/Enumeration.hs+20−13 src/Streamly/Internal/Data/Stream/IsStream/Exception.hs+15−15 src/Streamly/Internal/Data/Stream/IsStream/Expand.hs+397−61 src/Streamly/Internal/Data/Stream/IsStream/Generate.hs+125−30 src/Streamly/Internal/Data/Stream/IsStream/Lift.hs+2−3 src/Streamly/Internal/Data/Stream/IsStream/Reduce.hs+36−32 src/Streamly/Internal/Data/Stream/IsStream/Top.hs+15−15 src/Streamly/Internal/Data/Stream/IsStream/Transform.hs+107−28 src/Streamly/Internal/Data/Stream/IsStream/Type.hs+698 src/Streamly/Internal/Data/Stream/IsStream/Types.hs−74 src/Streamly/Internal/Data/Stream/Parallel.hs+70−161 src/Streamly/Internal/Data/Stream/Prelude.hs+13−308 src/Streamly/Internal/Data/Stream/PreludeCommon.hs+139 src/Streamly/Internal/Data/Stream/SVar/Eliminate.hs+7−6 src/Streamly/Internal/Data/Stream/SVar/Generate.hs+7−13 src/Streamly/Internal/Data/Stream/Serial.hs+85−114 src/Streamly/Internal/Data/Stream/StreamD/Eliminate.hs−13 src/Streamly/Internal/Data/Stream/StreamD/Generate.hs−2 src/Streamly/Internal/Data/Stream/StreamD/Transform.hs+3−13 src/Streamly/Internal/Data/Stream/StreamD/Type.hs+21−13 src/Streamly/Internal/Data/Stream/StreamK.hs+82−343 src/Streamly/Internal/Data/Stream/StreamK/Type.hs+479−371 src/Streamly/Internal/Data/Stream/Zip.hs+43−120 src/Streamly/Internal/Data/Unfold.hs+4−3 src/Streamly/Internal/FileSystem/Dir.hs+1−1 src/Streamly/Internal/FileSystem/FD.hs+4−5 src/Streamly/Internal/FileSystem/File.hs+2−2 src/Streamly/Internal/FileSystem/Handle.hs+8−7 src/Streamly/Internal/Network/Inet/TCP.hs+3−3 src/Streamly/Internal/Network/Socket.hs+12−11 src/Streamly/Internal/Unicode/Char.hs+3−6 src/Streamly/Internal/Unicode/Stream.hs+18−17 src/Streamly/Prelude.hs+1 streamly.cabal+10−6 test/Streamly/Test/Prelude/WSerial.hs+2−1
.hlint.ignore+5
@@ -1,3 +1,5 @@
1+src/Streamly/Internal/Data/Stream/Prelude.hs
2+src/Streamly/Internal/Data/Stream/PreludeCommon.hs
13src/Streamly/Internal/Data/Stream/Serial.hs
24src/Streamly/Internal/Data/Stream/Zip.hs
35src/Streamly/Internal/Data/Stream/StreamK/Type.hs
@@ -6,7 +8,10 @@ src/Streamly/Internal/Data/Pipe/Type.hs
68src/Streamly/Internal/Data/SmallArray/Type.hs
79src/Streamly/Internal/Unicode/Stream.hs
810src/Streamly/Internal/Data/Array/Prim/Type.hs
11+src/Streamly/Internal/Data/Array/Prim/Mut/Type.hs
912src/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
1015src/Streamly/Internal/Data/Array/Prim/TypesInclude.hs
1116test/Streamly/Test/Common/Array.hs
1217test/Streamly/Test/Data/Array.hs
benchmark/Streamly/Benchmark/Data/Stream/StreamK.hs+27−16
@@ -32,6 +32,7 @@ import qualified Prelude as P
3232import qualified Data.List as List
3333
3434import qualified Streamly.Internal.Control.Concurrent as S
35+import qualified Streamly.Internal.Data.Stream.StreamK.Type as S
3536import qualified Streamly.Internal.Data.Stream.StreamK as S
3637
3738import Gauge (bench, nfIO, bgroup, Benchmark, defaultMain)
@@ -127,7 +128,7 @@ unfoldr streamLen n = S.unfoldr step n
127128
128129{-# INLINE unfoldrM #-}
129130unfoldrM :: 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
131132 where
132133 step cnt =
133134 if cnt > n + streamLen
@@ -148,7 +149,7 @@ replicate = S.replicate
148149
149150{-# INLINE replicateM #-}
150151replicateM :: S.MonadAsync m => Int -> Int -> Stream m Int
151−replicateM streamLen = S.replicateM streamLen . return
152+replicateM streamLen = S.replicateMWith S.consM streamLen . return
152153
153154{-# INLINE iterate #-}
154155iterate :: Int -> Int -> Stream m Int
@@ -168,8 +169,11 @@ fromFoldableM streamLen n =
168169 Prelude.foldr S.consM S.nil (Prelude.fmap return [n..n+streamLen])
169170
170171{-# INLINABLE concatMapFoldableWith #-}
171−concatMapFoldableWith :: (S.IsStream t, Foldable f)
172− => (t m b -> t m b -> t m b) -> (a -> t m b) -> f a -> t m b
172+concatMapFoldableWith :: Foldable f
173+ => (Stream m b -> Stream m b -> Stream m b)
174+ -> (a -> Stream m b)
175+ -> f a
176+ -> Stream m b
173177concatMapFoldableWith f g = Prelude.foldr (f . g) S.nil
174178
175179{-# INLINE concatMapFoldableSerial #-}
@@ -202,13 +206,13 @@ uncons s = do
202206 Just (_, t) -> uncons t
203207
204208{-# INLINE init #-}
205−init :: (Monad m, S.IsStream t) => t m a -> m ()
209+init :: Monad m => Stream m a -> m ()
206210init s = do
207211 t <- S.init s
208212 P.mapM_ S.drain t
209213
210214{-# INLINE tail #-}
211−tail :: (Monad m, S.IsStream t) => t m a -> m ()
215+tail :: Monad m => Stream m a -> m ()
212216tail s = S.tail s >>= P.mapM_ tail
213217
214218{-# INLINE nullTail #-}
@@ -265,7 +269,7 @@ fmapK n = composeN n $ P.fmap (+ 1)
265269
266270{-# INLINE mapM #-}
267271mapM :: 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
269273
270274{-# INLINE mapMSerial #-}
271275mapMSerial :: S.MonadAsync m => Int -> Stream m Int -> m ()
@@ -339,7 +343,8 @@ iterateSource iterStreamLen g i n = f i (unfoldrM iterStreamLen n)
339343-- this is quadratic
340344{-# INLINE iterateScan #-}
341345iterateScan :: S.MonadAsync m => Int -> Int -> Int -> Stream m Int
342−iterateScan iterStreamLen maxIters = iterateSource iterStreamLen (S.scanl' (+) 0) (maxIters `div` 10)
346+iterateScan iterStreamLen maxIters =
347+ iterateSource iterStreamLen (S.scanl' (+) 0) (maxIters `div` 10)
343348
344349-- this is quadratic
345350{-# INLINE iterateDropWhileFalse #-}
@@ -349,23 +354,27 @@ iterateDropWhileFalse streamLen iterStreamLen maxIters =
349354
350355{-# INLINE iterateMapM #-}
351356iterateMapM :: S.MonadAsync m => Int -> Int -> Int -> Stream m Int
352−iterateMapM iterStreamLen maxIters = iterateSource iterStreamLen (S.mapM return) maxIters
357+iterateMapM iterStreamLen =
358+ iterateSource iterStreamLen (S.mapMWith S.consM return)
353359
354360{-# INLINE iterateFilterEven #-}
355361iterateFilterEven :: 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)
357363
358364{-# INLINE iterateTakeAll #-}
359365iterateTakeAll :: S.MonadAsync m => Int -> Int -> Int -> Int -> Stream m Int
360−iterateTakeAll streamLen iterStreamLen maxIters = iterateSource iterStreamLen (S.take streamLen) maxIters
366+iterateTakeAll streamLen iterStreamLen =
367+ iterateSource iterStreamLen (S.take streamLen)
361368
362369{-# INLINE iterateDropOne #-}
363370iterateDropOne :: 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)
365372
366373{-# INLINE iterateDropWhileTrue #-}
367−iterateDropWhileTrue :: S.MonadAsync m => Int -> Int -> Int -> Int -> Stream m Int
368−iterateDropWhileTrue streamLen iterStreamLen maxIters = iterateSource iterStreamLen (S.dropWhile (<= streamLen)) maxIters
374+iterateDropWhileTrue :: S.MonadAsync m =>
375+ Int -> Int -> Int -> Int -> Stream m Int
376+iterateDropWhileTrue streamLen iterStreamLen =
377+ iterateSource iterStreamLen (S.dropWhile (<= streamLen))
369378
370379-------------------------------------------------------------------------------
371380-- Zipping
@@ -471,7 +480,7 @@ sourceConcatMapId val n =
471480{-# INLINE concatMapBySerial #-}
472481concatMapBySerial :: Int -> Int -> Int -> IO ()
473482concatMapBySerial outer inner n =
474− S.drain $ S.concatMapBy S.serial
483+ S.drain $ S.concatMapWith S.serial
475484 (unfoldrM inner)
476485 (unfoldrM outer n)
477486
@@ -681,7 +690,9 @@ o_1_space_concat streamLen =
681690
682691 -- This is for comparison with concatMapFoldableWith
683692 , benchIOSrc1 "concatMapWithId (n of 1) (fromFoldable)"
684− (S.drain . S.concatMapBy S.serial id . sourceConcatMapId streamLen)
693+ (S.drain
694+ . S.concatMapWith S.serial id
695+ . sourceConcatMapId streamLen)
685696
686697 , benchIOSrc1 "concatMapBy serial (n of 1)"
687698 (concatMapBySerial streamLen 1)
benchmark/Streamly/Benchmark/Prelude/Async.hs+2−2
@@ -9,7 +9,7 @@ import Prelude hiding (mapM)
99
1010import Streamly.Prelude (fromAsync, async, maxBuffer, maxThreads, fromSerial)
1111import 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
1313
1414import Streamly.Benchmark.Common
1515import Streamly.Benchmark.Prelude
@@ -48,7 +48,7 @@ foldrSShared :: Int -> Int -> IO ()
4848foldrSShared count n =
4949 S.drain
5050 $ 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
5252 $ fromSerial
5353 $ sourceUnfoldrM count n
5454
benchmark/Streamly/Benchmark/Prelude/Parallel.hs+1−2
@@ -15,7 +15,6 @@ import Streamly.Prelude
1515
1616import qualified Streamly.Prelude as S
1717import qualified Streamly.Internal.Data.Fold as FL
18−import qualified Streamly.Internal.Data.Stream.Parallel as Par
1918import qualified Streamly.Internal.Data.Stream.IsStream as Internal
2019
2120import Streamly.Benchmark.Common
@@ -72,7 +71,7 @@ parAppSum src = (S.sum S.|$. src) >>= \x -> seq x (return ())
7271
7372{-# INLINE tapAsyncS #-}
7473tapAsyncS :: 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
7675
7776{-# INLINE tapAsync #-}
7877tapAsync :: S.MonadAsync m => Int -> SerialT m Int -> m ()
benchmark/Streamly/Benchmark/Prelude/Serial/Transformation3.hs+1
@@ -84,6 +84,7 @@ iterateStateT n = do
8484 else return x
8585
8686{-# INLINE iterateState #-}
87+{-# SPECIALIZE iterateState :: Int -> SerialT (StateT Int IO) Int #-}
8788iterateState ::
8889 (S.MonadAsync m, MonadState Int m)
8990 => Int
benchmark/lib/Streamly/Benchmark/Prelude.hs+3−1
@@ -26,6 +26,7 @@ import qualified Data.Foldable as F
2626import qualified Data.List as List
2727import qualified Streamly.Prelude as S
2828import qualified Streamly.Internal.Data.Stream.IsStream as Internal
29+import qualified Streamly.Internal.Data.Stream.IsStream.Type as IsStream
2930import qualified Streamly.Internal.Data.Pipe as Pipe
3031import qualified Streamly.Internal.Data.Stream.Serial as Serial
3132
@@ -89,7 +90,8 @@ sourceUnfoldrM count start = S.unfoldrM step start
8990
9091{-# INLINE sourceUnfoldrMSerial #-}
9192sourceUnfoldrMSerial :: (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
9395 where
9496 step cnt =
9597 if cnt > start + count
hie.yaml+8
@@ -14,10 +14,18 @@ cradle:
1414 component: "bench:Data.Parser.ParserD"
1515 - path: "./benchmark/Streamly/Benchmark/Data/Parser/ParserK.hs"
1616 component: "bench:Data.Parser.ParserK"
17+ - path: "./benchmark/Streamly/Benchmark/Data/Stream/StreamK.hs"
18+ component: "bench:Data.Stream.StreamK"
1719 - path: "./benchmark/Streamly/Benchmark/FileSystem/Handle/Read.hs"
1820 component: "bench:FileSystem.Handle"
1921 - path: "./benchmark/Streamly/Benchmark/FileSystem/Handle/ReadWrite.hs"
2022 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"
2129 - path: "./benchmark/Streamly/Benchmark/Prelude/Serial.hs"
2230 component: "bench:Prelude.Serial"
2331 - path: "./benchmark/Streamly/Benchmark/Prelude/Serial/Elimination.hs"
src/Streamly.hs+12−13
@@ -213,17 +213,16 @@ import Data.Semigroup (Semigroup(..))
213213import Streamly.Internal.Control.Concurrent (MonadAsync)
214214import Streamly.Internal.Data.SVar (Rate(..))
215215import Streamly.Internal.Data.Stream.Ahead
216−import Streamly.Internal.Data.Stream.Async hiding (mkAsync)
216+import Streamly.Internal.Data.Stream.Async
217217import Streamly.Internal.Data.Stream.IsStream.Combinators
218−import Streamly.Internal.Data.Stream.Parallel
219−import Streamly.Internal.Data.Stream.Serial
220−import Streamly.Internal.Data.Stream.StreamK hiding (serial)
218+import Streamly.Internal.Data.Stream.IsStream.Expand
219+import Streamly.Internal.Data.Stream.IsStream.Type
220+import Streamly.Internal.Data.Stream.Serial (StreamT, InterleavedT)
221221import Streamly.Internal.Data.Stream.Zip
222222
223223import qualified Streamly.Prelude as P
224224import qualified Streamly.Internal.Data.Stream.IsStream as IP
225−import qualified Streamly.Internal.Data.Stream.StreamK as K
226−import qualified Streamly.Internal.Data.Stream.Async as Async
225+import qualified Streamly.Internal.Data.Stream.IsStream.Transform as Transform
227226
228227-- XXX provide good succinct examples of pipelining, merging, splitting etc.
229228-- below.
@@ -364,7 +363,7 @@ import qualified Streamly.Internal.Data.Stream.Async as Async
364363-- @since 0.1.0
365364{-# DEPRECATED runStreaming "Please use runStream instead." #-}
366365runStreaming :: (Monad m, IsStream t) => t m a -> m ()
367−runStreaming = P.drain . K.adapt
366+runStreaming = P.drain . adapt
368367
369368-- | Same as @runStream@.
370369--
@@ -384,35 +383,35 @@ runStream = P.drain
384383-- @since 0.1.0
385384{-# DEPRECATED runInterleavedT "Please use 'drain . interleaving' instead." #-}
386385runInterleavedT :: Monad m => WSerialT m a -> m ()
387−runInterleavedT = P.drain . K.adapt
386+runInterleavedT = P.drain . adapt
388387
389388-- | Same as @drain . fromParallel@.
390389--
391390-- @since 0.1.0
392391{-# DEPRECATED runParallelT "Please use 'drain . fromParallel' instead." #-}
393392runParallelT :: Monad m => ParallelT m a -> m ()
394−runParallelT = P.drain . K.adapt
393+runParallelT = P.drain . adapt
395394
396395-- | Same as @drain . fromAsync@.
397396--
398397-- @since 0.1.0
399398{-# DEPRECATED runAsyncT "Please use 'drain . fromAsync' instead." #-}
400399runAsyncT :: Monad m => AsyncT m a -> m ()
401−runAsyncT = P.drain . K.adapt
400+runAsyncT = P.drain . adapt
402401
403402-- | Same as @drain . zipping@.
404403--
405404-- @since 0.1.0
406405{-# DEPRECATED runZipStream "Please use 'drain . fromZipSerial instead." #-}
407406runZipStream :: Monad m => ZipSerialM m a -> m ()
408−runZipStream = P.drain . K.adapt
407+runZipStream = P.drain . adapt
409408
410409-- | Same as @drain . zippingAsync@.
411410--
412411-- @since 0.1.0
413412{-# DEPRECATED runZipAsync "Please use 'drain . fromZipAsync instead." #-}
414413runZipAsync :: Monad m => ZipAsyncM m a -> m ()
415−runZipAsync = P.drain . K.adapt
414+runZipAsync = P.drain . adapt
416415
417416{-
418417-- | Same as "Streamly.Prelude.foldWith".
@@ -451,7 +450,7 @@ forEachWith = P.forEachWith
451450-- @since 0.2.0
452451{-# INLINABLE mkAsync #-}
453452mkAsync :: (IsStream t, MonadAsync m) => t m a -> m (t m a)
454−mkAsync = return . Async.mkAsync
453+mkAsync = return . Transform.mkAsync
455454
456455------------------------------------------------------------------------------
457456-- Documentation
src/Streamly/Internal/Data/Array.hs+8−9
@@ -56,8 +56,7 @@ import GHC.Base (Int(..))
5656import GHC.IO (unsafePerformIO)
5757
5858import Streamly.Internal.Data.Fold.Type (Fold(..))
59−import Streamly.Internal.Data.Stream.StreamK.Type (IsStream)
60−import Streamly.Internal.Data.Stream.Serial (SerialT)
59+import Streamly.Internal.Data.Stream.Serial (SerialT(..))
6160import Streamly.Internal.Data.Tuple.Strict (Tuple'(..), Tuple3'(..))
6261import Streamly.Internal.Data.Unfold.Type (Unfold(..))
6362
@@ -131,13 +130,13 @@ fromStreamD = D.fold write
131130
132131{-# INLINE fromStreamN #-}
133132fromStreamN :: MonadIO m => Int -> SerialT m a -> m (Array a)
134−fromStreamN n m = do
133+fromStreamN n (SerialT m) = do
135134 when (n < 0) $ error "fromStreamN: negative write count specified"
136− fromStreamDN n $ D.toStreamD m
135+ fromStreamDN n $ D.fromStreamK m
137136
138137{-# INLINE fromStream #-}
139138fromStream :: MonadIO m => SerialT m a -> m (Array a)
140−fromStream m = fromStreamD $ D.toStreamD m
139+fromStream (SerialT m) = fromStreamD $ D.fromStreamK m
141140
142141{-# INLINABLE fromListN #-}
143142fromListN :: Int -> [a] -> Array a
@@ -196,12 +195,12 @@ toStreamDRev arr = D.Stream step (length arr - 1)
196195 (# x #) -> D.Yield x (I# i - 1)
197196
198197{-# INLINE_EARLY toStream #-}
199−toStream :: (Monad m, IsStream t) => Array a -> t m a
200−toStream = D.fromStreamD . toStreamD
198+toStream :: Monad m => Array a -> SerialT m a
199+toStream = SerialT . D.toStreamK . toStreamD
201200
202201{-# INLINE_EARLY toStreamRev #-}
203−toStreamRev :: (Monad m, IsStream t) => Array a -> t m a
204−toStreamRev = D.fromStreamD . toStreamDRev
202+toStreamRev :: Monad m => Array a -> SerialT m a
203+toStreamRev = SerialT . D.toStreamK . toStreamDRev
205204
206205-------------------------------------------------------------------------------
207206-- Elimination - using Folds
src/Streamly/Internal/Data/Array/Foreign.hs+7−8
@@ -141,7 +141,7 @@ import Streamly.Internal.BaseCompat
141141import Streamly.Internal.Data.Array.Foreign.Type (Array(..), length)
142142import Streamly.Internal.Data.Fold.Type (Fold(..))
143143import Streamly.Internal.Data.Producer.Type (Producer)
144−import Streamly.Internal.Data.Stream.Serial (SerialT)
144+import Streamly.Internal.Data.Stream.Serial (SerialT(..))
145145import Streamly.Internal.Data.Tuple.Strict (Tuple3'(..))
146146import Streamly.Internal.Data.Unfold.Type (Unfold(..))
147147import Streamly.Internal.System.IO (unsafeInlineIO)
@@ -150,7 +150,6 @@ import qualified Streamly.Internal.Data.Array.Foreign.Mut.Type as MA
150150import qualified Streamly.Internal.Data.Array.Foreign.Type as A
151151import qualified Streamly.Internal.Data.Fold as FL
152152import qualified Streamly.Internal.Data.Stream.Prelude as P
153−import qualified Streamly.Internal.Data.Stream.Serial as Serial
154153import qualified Streamly.Internal.Data.Stream.StreamD as D
155154import qualified Streamly.Internal.Data.Unfold as Unfold
156155import qualified Streamly.Internal.Data.Producer.Type as Producer
@@ -176,9 +175,9 @@ plusForeignPtr (ForeignPtr addr c) (I# d) = ForeignPtr (plusAddr# addr d) c
176175-- /Pre-release/
177176{-# INLINE fromStreamN #-}
178177fromStreamN :: (MonadIO m, Storable a) => Int -> SerialT m a -> m (Array a)
179−fromStreamN n m = do
178+fromStreamN n (SerialT m) = do
180179 when (n < 0) $ error "writeN: negative write count specified"
181− A.fromStreamDN n $ D.toStreamD m
180+ A.fromStreamDN n $ D.fromStreamK m
182181
183182-- | Create an 'Array' from a stream. This is useful when we want to create a
184183-- single array from a stream of unknown size. 'writeN' is at least twice
@@ -191,8 +190,8 @@ fromStreamN n m = do
191190-- /Pre-release/
192191{-# INLINE fromStream #-}
193192fromStream :: (MonadIO m, Storable a) => SerialT m a -> m (Array a)
194−fromStream = P.fold A.write
195−-- write m = A.fromStreamD $ D.toStreamD m
193+fromStream (SerialT m) = P.fold A.write m
194+-- write m = A.fromStreamD $ D.fromStreamK m
196195
197196-------------------------------------------------------------------------------
198197-- Elimination
@@ -454,7 +453,7 @@ streamTransform :: forall m a b. (MonadIO m, Storable a, Storable b)
454453 => (SerialT m a -> SerialT m b) -> Array a -> m (Array b)
455454streamTransform f arr =
456455 P.fold (A.toArrayMinChunk (alignment (undefined :: a)) (length arr))
457− $ f (A.toStream arr)
456+ $ getSerialT $ f (A.toStream arr)
458457
459458-------------------------------------------------------------------------------
460459-- Casts
@@ -527,7 +526,7 @@ unsafeAsCString arr act = do
527526-- /Pre-release/
528527{-# INLINE fold #-}
529528fold :: 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))
531530
532531-- | Fold an array using a stream fold operation.
533532--
src/Streamly/Internal/Data/Array/Foreign/Mut/Type.hs+2−2
@@ -686,7 +686,7 @@ toStreamD Array{..} =
686686 return $ D.Yield x (p `plusPtr` sizeOf (undefined :: a))
687687
688688{-# 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
690690toStreamK Array{..} =
691691 let p = unsafeForeignPtrToPtr aStart
692692 in go p
@@ -726,7 +726,7 @@ toStreamDRev Array{..} =
726726 return $ D.Yield x (p `plusPtr` negate (sizeOf (undefined :: a)))
727727
728728{-# 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
730730toStreamKRev Array {..} =
731731 let p = aEnd `plusPtr` negate (sizeOf (undefined :: a))
732732 in go p
src/Streamly/Internal/Data/Array/Foreign/Type.hs+7−6
@@ -91,6 +91,7 @@ import GHC.ForeignPtr (touchForeignPtr, unsafeForeignPtrToPtr)
9191import GHC.IO (unsafePerformIO)
9292import GHC.Ptr (Ptr(..))
9393import Streamly.Internal.Data.Fold.Type (Fold(..))
94+import Streamly.Internal.Data.Stream.Serial (SerialT(..))
9495import Streamly.Internal.Data.Unfold.Type (Unfold(..))
9596import Text.Read (readPrec, readListPrec, readListPrecDefault)
9697
@@ -429,7 +430,7 @@ toStreamD :: forall m a. (Monad m, Storable a) => Array a -> D.Stream m a
429430toStreamD arr = MA.toStreamD (unsafeThaw arr)
430431
431432{-# 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
433434toStreamK arr = MA.toStreamK (unsafeThaw arr)
434435
435436{-# INLINE_NORMAL toStreamDRev #-}
@@ -437,15 +438,15 @@ toStreamDRev :: forall m a. (Monad m, Storable a) => Array a -> D.Stream m a
437438toStreamDRev arr = MA.toStreamDRev (unsafeThaw arr)
438439
439440{-# 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
441442toStreamKRev arr = MA.toStreamKRev (unsafeThaw arr)
442443
443444-- | Convert an 'Array' into a stream.
444445--
445446-- /Pre-release/
446447{-# INLINE_EARLY toStream #-}
447−toStream :: (Monad m, K.IsStream t, Storable a) => Array a -> t m a
448−toStream = D.fromStreamD . toStreamD
448+toStream :: (Monad m, Storable a) => Array a -> SerialT m a
449+toStream = SerialT . D.toStreamK . toStreamD
449450-- XXX add fallback to StreamK rule
450451-- {-# RULES "Streamly.Array.read fallback to StreamK" [1]
451452-- forall a. S.readK (read a) = K.fromArray a #-}
@@ -454,8 +455,8 @@ toStream = D.fromStreamD . toStreamD
454455--
455456-- /Pre-release/
456457{-# INLINE_EARLY toStreamRev #-}
457−toStreamRev :: (Monad m, K.IsStream t, Storable a) => Array a -> t m a
458−toStreamRev = D.fromStreamD . toStreamDRev
458+toStreamRev :: (Monad m, Storable a) => Array a -> SerialT m a
459+toStreamRev = SerialT . D.toStreamK . toStreamDRev
459460
460461-- XXX add fallback to StreamK rule
461462-- {-# 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
2525import qualified Prelude as P
2626import qualified Streamly.Internal.Data.Fold as FL
2727import 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
2929
3030import GHC.Exts hiding (fromListN, fromList, toList)
3131import Prelude hiding (length, unlines, foldr)
@@ -398,7 +398,7 @@ toStreamD arr = D.Stream step 0
398398 step _ i = return $ D.Yield (unsafeIndex arr i) (i + 1)
399399
400400{-# INLINE toStreamK #-}
401−toStreamK :: (K.IsStream t, Prim a) => Array a -> t m a
401+toStreamK :: Prim a => Array a -> K.Stream m a
402402toStreamK arr = go 0
403403
404404 where
@@ -423,7 +423,7 @@ toStreamDRev arr = D.Stream step (length arr - 1)
423423 step _ i = return $ D.Yield (unsafeIndex arr i) (i - 1)
424424
425425{-# INLINE toStreamKRev #-}
426−toStreamKRev :: (K.IsStream t, Prim a) => Array a -> t m a
426+toStreamKRev :: Prim a => Array a -> K.Stream m a
427427toStreamKRev arr = go (length arr - 1)
428428
429429 where
src/Streamly/Internal/Data/Array/PrimInclude.hs+14−15
@@ -9,13 +9,10 @@ import Control.Monad.IO.Class (MonadIO(..))
99import Data.Primitive.Types (Prim(..))
1010import Streamly.Internal.Data.Fold.Type (Fold(..))
1111import Streamly.Internal.Data.Unfold.Type (Unfold(..))
12−import Streamly.Internal.Data.Stream.Serial (SerialT)
13−import Streamly.Internal.Data.Stream.StreamK.Type (IsStream)
12+import Streamly.Internal.Data.Stream.Serial (SerialT(..))
1413
1514import qualified Streamly.Internal.Data.Stream.Prelude as P
16−import qualified Streamly.Internal.Data.Stream.Serial as Serial
1715import qualified Streamly.Internal.Data.Stream.StreamD as D
18−import qualified Streamly.Internal.Data.Stream.StreamK as K
1916
2017import Prelude hiding (length, null, last, map, (!!), read, concat)
2118
@@ -30,9 +27,9 @@ import Prelude hiding (length, null, last, map, (!!), read, concat)
3027-- /Pre-release/
3128{-# INLINE fromStreamN #-}
3229fromStreamN :: (MonadIO m, Prim a) => Int -> SerialT m a -> m (Array a)
33−fromStreamN n m = do
30+fromStreamN n (SerialT m) = do
3431 when (n < 0) $ error "writeN: negative write count specified"
35− A.fromStreamDN n $ D.toStreamD m
32+ A.fromStreamDN n $ D.fromStreamK m
3633
3734-- | Create an 'Array' from a stream. This is useful when we want to create a
3835-- single array from a stream of unknown size. 'writeN' is at least twice
@@ -45,7 +42,7 @@ fromStreamN n m = do
4542-- /Pre-release/
4643{-# INLINE fromStream #-}
4744fromStream :: (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
4946-- write m = A.fromStreamD $ D.toStreamD m
5047
5148-------------------------------------------------------------------------------
@@ -56,8 +53,8 @@ fromStream = P.fold A.write
5653--
5754-- /Pre-release/
5855{-# INLINE_EARLY toStream #-}
59−toStream :: (MonadIO m, K.IsStream t, Prim a) => Array a -> t m a
60−toStream = D.fromStreamD . A.toStreamD
56+toStream :: (MonadIO m, Prim a) => Array a -> SerialT m a
57+toStream = SerialT . D.toStreamK . A.toStreamD
6158-- XXX add fallback to StreamK rule
6259-- {-# RULES "Streamly.Array.read fallback to StreamK" [1]
6360-- forall a. S.readK (read a) = K.fromArray a #-}
@@ -66,8 +63,8 @@ toStream = D.fromStreamD . A.toStreamD
6663--
6764-- /Pre-release/
6865{-# INLINE_EARLY toStreamRev #-}
69−toStreamRev :: (MonadIO m, IsStream t, Prim a) => Array a -> t m a
70−toStreamRev = D.fromStreamD . A.toStreamDRev
66+toStreamRev :: (MonadIO m, Prim a) => Array a -> SerialT m a
67+toStreamRev = SerialT . D.toStreamK . A.toStreamDRev
7168-- XXX add fallback to StreamK rule
7269-- {-# RULES "Streamly.Array.readRev fallback to StreamK" [1]
7370-- forall a. S.toStreamK (readRev a) = K.revFromArray a #-}
@@ -128,7 +125,7 @@ null arr = length arr == 0
128125-- /Pre-release/
129126{-# INLINE fold #-}
130127fold :: 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))
132129
133130-- | Fold an array using a stream fold operation.
134131--
@@ -170,10 +167,11 @@ last arr = readIndex arr (length arr - 1)
170167--
171168-- /Pre-release/
172169{-# 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
174171-- concat m = D.fromStreamD $ A.flattenArrays (D.toStreamD m)
175172-- concat m = D.fromStreamD $ D.concatMap A.toStreamD (D.toStreamD m)
176−concat m = D.fromStreamD $ D.unfoldMany read (D.toStreamD m)
173+concat (SerialT m) =
174+ SerialT $ D.toStreamK $ D.unfoldMany read (D.fromStreamK m)
177175
178176-- | Coalesce adjacent arrays in incoming stream to form bigger arrays of a
179177-- maximum specified size in bytes.
@@ -182,4 +180,5 @@ concat m = D.fromStreamD $ D.unfoldMany read (D.toStreamD m)
182180{-# INLINE compact #-}
183181compact ::
184182 (MonadIO m, Prim a) => Int -> SerialT m (Array a) -> SerialT m (Array a)
185−compact n xs = D.fromStreamD $ A.packArraysChunksOf n (D.toStreamD xs)
183+compact n (SerialT 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(..))
7272import Streamly.Internal.Data.Fold.Type (Fold(..))
7373import Streamly.Internal.Data.Parser (ParseError(..))
7474import 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)
7677import Streamly.Internal.Data.SVar (adaptState, defState)
7778import Streamly.Internal.Data.Array.Foreign.Mut.Type (memcpy, bytesToElemCount)
7879import Streamly.Internal.System.IO (mkChunkSizeKB)
@@ -102,7 +103,7 @@ import qualified Streamly.Internal.Data.Stream.StreamD as D
102103{-# INLINE arraysOf #-}
103104arraysOf :: (IsStream t, MonadIO m, Storable a)
104105 => 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)
106107
107108-------------------------------------------------------------------------------
108109-- Append
@@ -121,9 +122,9 @@ arraysOf n str = D.fromStreamD $ A.arraysOf n (D.toStreamD str)
121122-- @since 0.7.0
122123{-# INLINE concat #-}
123124concat :: (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 = D.fromStreamD $ D.concatMap A.toStreamD (D.toStreamD m)
126−concat m = D.fromStreamD $ D.unfoldMany A.read (D.toStreamD m)
125+-- concat m = fromStreamD $ A.flattenArrays (toStreamD m)
126+-- concat m = fromStreamD $ D.concatMap A.toStreamD (toStreamD m)
127+concat m = fromStreamD $ D.unfoldMany A.read (toStreamD m)
127128
128129-- | Convert a stream of arrays into a stream of their elements reversing the
129130-- contents of each array before flattening.
@@ -133,7 +134,7 @@ concat m = D.fromStreamD $ D.unfoldMany A.read (D.toStreamD m)
133134-- @since 0.7.0
134135{-# INLINE concatRev #-}
135136concatRev :: (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)
137138
138139-------------------------------------------------------------------------------
139140-- Intersperse and append
@@ -159,7 +160,7 @@ intercalateSuffix = S.intercalateSuffix A.read
159160{-# INLINE interposeSuffix #-}
160161interposeSuffix :: (MonadIO m, IsStream t, Storable a)
161162 => 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
163164interposeSuffix x = S.interposeSuffix x A.read
164165
165166data FlattenState s a =
@@ -220,7 +221,7 @@ lpackArraysChunksOf n fld =
220221{-# INLINE compact #-}
221222compact :: (MonadIO m, Storable a)
222223 => 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)
224225
225226-------------------------------------------------------------------------------
226227-- Split
@@ -294,7 +295,7 @@ splitOn
294295 -> t m (Array Word8)
295296 -> t m (Array Word8)
296297splitOn 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
298299
299300{-# INLINE splitOnSuffix #-}
300301splitOnSuffix
@@ -302,9 +303,9 @@ splitOnSuffix
302303 => Word8
303304 -> t m (Array Word8)
304305 -> 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
306307splitOnSuffix 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
308309
309310-------------------------------------------------------------------------------
310311-- Elimination - Running folds
@@ -362,7 +363,7 @@ fold ::
362363 => FL.Fold m a b
363364 -> SerialT m (A.Array a)
364365 -> 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)
366367
367368-------------------------------------------------------------------------------
368369-- Fold to a single Array
@@ -613,7 +614,7 @@ parse ::
613614 => PRD.Parser m a b
614615 -> SerialT m (A.Array a)
615616 -> 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)
617618
618619-------------------------------------------------------------------------------
619620-- Elimination - Running Array Folds and parsers
@@ -695,7 +696,7 @@ parseArr ::
695696 => ASF.Parser m a b
696697 -> SerialT m (A.Array a)
697698 -> 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)
699700-}
700701
701702-- | 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)
705706{-# INLINE foldArr #-}
706707foldArr :: (MonadIO m, MonadThrow m, Storable a) =>
707708 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)
709710
710711-- | Like 'fold' but also returns the remaining stream.
711712--
@@ -714,7 +715,7 @@ foldArr (ASF.Fold p) s = fst <$> parseArrD p (D.toStreamD s)
714715{-# INLINE foldArr_ #-}
715716foldArr_ :: (MonadIO m, MonadThrow m, Storable a) =>
716717 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)
718719
719720{-# ANN type ParseChunksState Fuse #-}
720721data ParseChunksState x inpBuf st pst =
@@ -856,4 +857,4 @@ foldArrMany
856857 => ASF.Fold m a b
857858 -> t m (Array a)
858859 -> 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)
3232import Foreign.Storable (Storable(..))
3333import Streamly.Internal.Data.Array.Foreign.Mut.Type (Array(..))
3434import Streamly.Internal.Data.Fold.Type (Fold(..))
35−import Streamly.Internal.Data.Stream.Serial (SerialT)
36−import Streamly.Internal.Data.Stream.StreamK.Type (IsStream)
35+import Streamly.Internal.Data.Stream.Serial (SerialT(..))
36+import Streamly.Internal.Data.Stream.IsStream.Type
37+ (IsStream, fromStreamD, toStreamD)
3738import Streamly.Internal.Data.Tuple.Strict (Tuple'(..))
3839
3940import qualified Streamly.Internal.Data.Array.Foreign.Mut.Type as MArray
@@ -51,7 +52,7 @@ import qualified Streamly.Internal.Data.Stream.StreamD as D
5152{-# INLINE arraysOf #-}
5253arraysOf :: (IsStream t, MonadIO m, Storable a)
5354 => 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
5556
5657-------------------------------------------------------------------------------
5758-- Compact
@@ -190,7 +191,8 @@ lpackArraysChunksOf n (Fold step1 initial1 extract1) =
190191{-# INLINE compact #-}
191192compact :: (MonadIO m, Storable a)
192193 => Int -> SerialT m (Array a) -> SerialT m (Array a)
193−compact n xs = D.fromStreamD $ packArraysChunksOf n (D.toStreamD xs)
194+compact n (SerialT xs) =
195+ SerialT $ D.toStreamK $ packArraysChunksOf n (D.fromStreamK xs)
194196
195197-- See lpackArraysChunksOf/packArraysChunksOf to implement this.
196198--
@@ -212,7 +214,8 @@ compactLEFold = undefined
212214-- /Internal/
213215compactLE :: (MonadIO m {-, Storable a-}) =>
214216 Int -> SerialT m (Array a) -> SerialT m (Array a)
215−compactLE n xs = D.fromStreamD $ D.foldMany (compactLEFold n) (D.toStreamD xs)
217+compactLE n (SerialT xs) =
218+ SerialT $ D.toStreamK $ D.foldMany (compactLEFold n) (D.fromStreamK xs)
216219
217220-- | Like 'compactLE' but generates arrays of exactly equal to the size
218221-- 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)
222225compactEQ :: -- (MonadIO m, Storable a) =>
223226 Int -> SerialT m (Array a) -> SerialT m (Array a)
224227compactEQ _n _xs = undefined
225− -- D.fromStreamD $ D.foldMany (compactEQFold n) (D.toStreamD xs)
228+ -- IsStream.fromStreamD $ D.foldMany (compactEQFold n) (IsStream.toStreamD xs)
226229
227230-- | Like 'compactLE' but generates arrays of size greater than or equal to the
228231-- specified except for the last array in the stream which could be shorter.
@@ -232,4 +235,4 @@ compactEQ _n _xs = undefined
232235compactGE :: -- (MonadIO m, Storable a) =>
233236 Int -> SerialT m (Array a) -> SerialT m (Array a)
234237compactGE _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
143143
144144 -- ** Trimming
145145 , take
146− , takeInterval
147146
148147 -- By elements
149148 , takeEndBy
@@ -215,7 +214,6 @@ module Streamly.Internal.Data.Fold
215214
216215 -- ** Splitting
217216 , many
218− , intervalsOf
219217 , chunksOf
220218 , chunksBetween
221219
@@ -252,12 +250,12 @@ import Streamly.Internal.Data.Either.Strict
252250 (Either'(..), fromLeft', fromRight', isLeft', isRight')
253251import Streamly.Internal.Data.Pipe.Type (Pipe (..), PipeState(..))
254252import Streamly.Internal.Data.Tuple.Strict (Tuple'(..), Tuple3'(..))
255−import Streamly.Internal.Data.Stream.Serial (SerialT)
253+import Streamly.Internal.Data.Stream.Serial (SerialT(..))
256254
257255import qualified Data.Map.Strict as Map
258256import qualified Streamly.Internal.Data.Pipe.Type as Pipe
259257-- 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
261259import qualified Prelude
262260
263261import Prelude hiding
@@ -1690,7 +1688,7 @@ chunksBetween _low _high _f1 _f2 = undefined
16901688-- /Pre-release/
16911689{-# INLINE toStream #-}
16921690toStream :: Monad m => Fold m a (SerialT Identity a)
1693−toStream = foldr K.cons K.nil
1691+toStream = fmap SerialT $ foldr K.cons K.nil
16941692
16951693-- This is more efficient than 'toStream'. toStream is exactly the same as
16961694-- reversing the stream after toStreamRev.
@@ -1708,4 +1706,4 @@ toStream = foldr K.cons K.nil
17081706-- xn : ... : x2 : x1 : []
17091707{-# INLINABLE toStreamRev #-}
17101708toStreamRev :: 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
228228
229229 -- ** Trimming
230230 , take
231− , takeInterval
232231
233232 -- ** Serial Append
234233 , serialWith
@@ -248,7 +247,6 @@ module Streamly.Internal.Data.Fold.Type
248247 , many
249248 , manyPost
250249 , chunksOf
251− , intervalsOf
252250
253251 -- ** Nesting
254252 , concatMap
@@ -265,18 +263,12 @@ module Streamly.Internal.Data.Fold.Type
265263 )
266264where
267265
268−import Control.Monad (void, (>=>))
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)
266+import Control.Monad ((>=>))
274267import Data.Bifunctor (Bifunctor(..))
275268import Data.Maybe (isJust, fromJust)
276269import Fusion.Plugin.Types (Fuse(..))
277270import Streamly.Internal.Data.Maybe.Strict (Maybe'(..), toMaybe)
278271import Streamly.Internal.Data.Tuple.Strict (Tuple'(..), Tuple3'(..))
279−import Streamly.Internal.Control.Concurrent (MonadAsync)
280272
281273import Prelude hiding (concatMap, filter, foldr, map, take)
282274
@@ -1358,88 +1350,3 @@ chunksOf2 n (Fold step1 initial1 extract1) (Fold2 step2 inject2 extract2) =
13581350 else extract1 r1 >>= step2 r2 >>= loopUntilPartial
13591351
13601352 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
3535
3636 -- * Read
3737 , readIORef
38− , toStream
3938 , toStreamD
4039 )
4140where
@@ -48,7 +47,6 @@ import Data.Primitive.Types (Prim, sizeOf#, readByteArray#, writeByteArray#)
4847import GHC.Exts (MutableByteArray#, newByteArray#, RealWorld)
4948import GHC.IO (IO(..))
5049
51−import qualified Streamly.Internal.Data.Stream.StreamK.Type as K
5250import qualified Streamly.Internal.Data.Stream.StreamD.Type as D
5351
5452-- | An 'IORef' holds a single 'Prim' value.
@@ -100,11 +98,3 @@ toStreamD var = D.Stream step ()
10098
10199 {-# INLINE_LATE step #-}
102100 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(..))
7272#endif
7373import GHC.Exts (IsList(..), IsString(..))
7474
75−import Streamly.Internal.Data.Stream.Serial (SerialT)
76−import Streamly.Internal.Data.Stream.Zip (ZipSerialM)
75+import Streamly.Internal.Data.Stream.Serial (SerialT(..))
76+import Streamly.Internal.Data.Stream.Zip (ZipSerialM(..))
7777
78−import qualified Streamly.Internal.Data.Stream.IsStream as Stream
79−import qualified Streamly.Internal.Data.Stream.StreamK as K
78+import qualified Streamly.Internal.Data.Stream.Serial as Serial
79+import qualified Streamly.Internal.Data.Stream.StreamK.Type as K
8080
8181-- We implement list as a newtype instead of a type synonym to make type
8282-- inference easier when using -XOverloadedLists and -XOverloadedStrings. When
@@ -103,15 +103,15 @@ newtype List a = List { toSerial :: SerialT Identity a }
103103
104104instance (a ~ Char) => IsString (List a) where
105105 {-# INLINE fromString #-}
106− fromString = List . Stream.fromList
106+ fromString = List . fromList
107107
108108-- GHC versions 8.0 and below cannot derive IsList
109109instance IsList (List a) where
110110 type (Item (List a)) = a
111111 {-# INLINE fromList #-}
112− fromList = List . Stream.fromList
112+ fromList = List . fromList
113113 {-# INLINE toList #-}
114− toList = runIdentity . Stream.toList . toSerial
114+ toList = toList . toSerial
115115
116116------------------------------------------------------------------------------
117117-- Patterns
@@ -128,8 +128,8 @@ instance IsList (List a) where
128128--
129129-- @since 0.6.0
130130pattern Nil :: List a
131−pattern Nil <- (runIdentity . K.null . toSerial -> True) where
132− Nil = List K.nil
131+pattern Nil <- (runIdentity . K.null . getSerialT . toSerial -> True) where
132+ Nil = List $ SerialT K.nil
133133
134134infixr 5 `Cons`
135135
@@ -139,9 +139,14 @@ infixr 5 `Cons`
139139-- @since 0.6.0
140140pattern Cons :: a -> List a -> List a
141141pattern Cons x xs <-
142− (fmap (second List) . runIdentity . K.uncons . toSerial
143− -> Just (x, xs)) where
144− Cons x xs = List $ K.cons x (toSerial xs)
142+ (fmap (second (List . SerialT))
143+ . runIdentity . K.uncons . getSerialT . toSerial
144+ -> Just (x, xs)
145+ )
146+
147+ where
148+
149+ Cons x xs = List $ Serial.cons x (toSerial xs)
145150
146151#if __GLASGOW_HASKELL__ >= 802
147152{-# COMPLETE Nil, Cons #-}
@@ -165,24 +170,24 @@ newtype ZipList a = ZipList { toZipSerial :: ZipSerialM Identity a }
165170
166171instance (a ~ Char) => IsString (ZipList a) where
167172 {-# INLINE fromString #-}
168− fromString = ZipList . Stream.fromList
173+ fromString = ZipList . fromList
169174
170175-- GHC versions 8.0 and below cannot derive IsList
171176instance IsList (ZipList a) where
172177 type (Item (ZipList a)) = a
173178 {-# INLINE fromList #-}
174− fromList = ZipList . Stream.fromList
179+ fromList = ZipList . fromList
175180 {-# INLINE toList #-}
176− toList = runIdentity . Stream.toList . K.adapt . toZipSerial
181+ toList = toList . toZipSerial
177182
178183-- | Convert a 'ZipList' to a regular 'List'
179184--
180185-- @since 0.6.0
181186fromZipList :: ZipList a -> List a
182−fromZipList = List . K.adapt . toZipSerial
187+fromZipList (ZipList zs) = List $ SerialT $ getZipSerialM zs
183188
184189-- | Convert a regular 'List' to a 'ZipList'
185190--
186191-- @since 0.6.0
187192toZipList :: 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
5353import Streamly.Internal.Data.Tuple.Strict (Tuple'(..))
5454import Streamly.Internal.Data.Unfold.Type (Unfold(..))
5555import Streamly.Internal.Data.Fold.Type (Fold(..))
56−import Streamly.Internal.Data.Stream.StreamK.Type (IsStream)
57−import Streamly.Internal.Data.Stream.Serial (SerialT)
56+import Streamly.Internal.Data.Stream.Serial (SerialT(..))
5857
5958import qualified Streamly.Internal.Data.Stream.StreamD as D
6059import qualified Streamly.Internal.Data.Fold.Type as FL
@@ -155,17 +154,17 @@ instance NFData a => NFData (SmallArray a) where
155154-- For optimal performance use this with @n@ <= 128.
156155{-# INLINE fromStreamN #-}
157156fromStreamN :: MonadIO m => Int -> SerialT m a -> m (SmallArray a)
158−fromStreamN n m = do
157+fromStreamN n (SerialT m) = do
159158 when (n < 0) $ error "fromStreamN: negative write count specified"
160− fromStreamDN n $ D.toStreamD m
159+ fromStreamDN n $ D.fromStreamK m
161160
162161{-# INLINE_EARLY toStream #-}
163−toStream :: (Monad m, IsStream t) => SmallArray a -> t m a
164−toStream = D.fromStreamD . toStreamD
162+toStream :: Monad m => SmallArray a -> SerialT m a
163+toStream = SerialT . D.toStreamK . toStreamD
165164
166165{-# INLINE_EARLY toStreamRev #-}
167−toStreamRev :: (Monad m, IsStream t) => SmallArray a -> t m a
168−toStreamRev = D.fromStreamD . toStreamDRev
166+toStreamRev :: Monad m => SmallArray a -> SerialT m a
167+toStreamRev = SerialT . D.toStreamK . toStreamDRev
169168
170169{-# INLINE fold #-}
171170fold :: Monad m => Fold m a b -> SmallArray a -> m b
src/Streamly/Internal/Data/Stream/Ahead.hs+48−101
@@ -22,10 +22,10 @@
2222--
2323module Streamly.Internal.Data.Stream.Ahead
2424 (
25− AheadT
25+ AheadT(..)
2626 , Ahead
27− , fromAhead
28− , ahead
27+ , aheadK
28+ , consM
2929 )
3030where
3131
@@ -52,10 +52,9 @@ import qualified Data.Heap as H
5252
5353import Streamly.Internal.Control.Concurrent
5454 (MonadAsync, RunInIO(..), captureMonadState)
55−import Streamly.Internal.Data.Stream.StreamK.Type
56− (IsStream(..), Stream, mkStream, foldStream, foldStreamShared)
55+import Streamly.Internal.Data.Stream.Serial (SerialT(..))
56+import Streamly.Internal.Data.Stream.StreamK.Type (Stream)
5757
58−import qualified Streamly.Internal.Data.Stream.StreamK as K (withLocal)
5958import qualified Streamly.Internal.Data.Stream.StreamK.Type as K
6059import qualified Streamly.Internal.Data.Stream.StreamD.Type as D
6160
@@ -321,7 +320,7 @@ processHeap q heap st sv winfo entry sno stopping = loopHeap sno entry
321320 let stop = do
322321 liftIO (incrementYieldLimit sv)
323322 nextHeap seqNo
324− foldStreamShared st
323+ K.foldStreamShared st
325324 (yieldStreamFromHeap seqNo)
326325 (singleStreamFromHeap seqNo)
327326 stop
@@ -380,7 +379,7 @@ processWithoutToken q heap st sv winfo m seqNo = do
380379 mrun = runInIO $ svarMrun sv
381380
382381 r <- liftIO $ mrun $
383− foldStreamShared st
382+ K.foldStreamShared st
384383 (\a r -> do
385384 runIn <- captureMonadState
386385 toHeap $ AheadEntryStream (runIn, K.cons a r))
@@ -451,7 +450,7 @@ processWithToken q heap st sv winfo action sno = do
451450 mrun = runInIO $ svarMrun sv
452451
453452 r <- liftIO $ mrun $
454− foldStreamShared st (yieldOutput sno) (singleOutput sno) stop action
453+ K.foldStreamShared st (yieldOutput sno) (singleOutput sno) stop action
455454
456455 res <- restoreM r
457456 case res of
@@ -479,7 +478,7 @@ processWithToken q heap st sv winfo action sno = do
479478 let stop = do
480479 liftIO (incrementYieldLimit sv)
481480 return $ TokenContinue (seqNo + 1)
482− foldStreamShared st
481+ K.foldStreamShared st
483482 (yieldOutput seqNo)
484483 (singleOutput seqNo)
485484 stop
@@ -513,7 +512,7 @@ processWithToken q heap st sv winfo action sno = do
513512 return $ TokenContinue (seqNo + 1)
514513 mrun = runInIO $ svarMrun sv
515514 r <- liftIO $ mrun $
516− foldStreamShared st
515+ K.foldStreamShared st
517516 (yieldOutput seqNo)
518517 (singleOutput seqNo)
519518 stop
@@ -604,80 +603,36 @@ workLoopAhead q heap st sv winfo = do
604603
605604-- The only difference between forkSVarAsync and this is that we run the left
606605-- computation without a shared SVar.
607−forkSVarAhead :: (IsStream t, MonadAsync m) => t m a -> t m a -> t m a
608−forkSVarAhead m1 m2 = mkStream $ \st yld sng stp -> do
609− sv <- newAheadVar st (concurrently (toStream m1) (toStream m2))
606+forkSVarAhead :: MonadAsync m => Stream m a -> Stream m a -> Stream m a
607+forkSVarAhead m1 m2 = K.mkStream $ \st yld sng stp -> do
608+ sv <- newAheadVar st (concurrently m1 m2)
610609 workLoopAhead
611− foldStream st yld sng stp (fromSVar sv)
610+ K.foldStream st yld sng stp $ getSerialT (fromSVar sv)
612611 where
613− concurrently ma mb = mkStream $ \st yld sng stp -> do
612+ concurrently ma mb = K.mkStream $ \st yld sng stp -> do
614613 runInIO <- captureMonadState
615614 liftIO $ enqueue (fromJust $ streamVar st) (runInIO, mb)
616− foldStream st yld sng stp ma
615+ K.foldStream st yld sng stp ma
617616
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 #-}
663−ahead :: (IsStream t, MonadAsync m) => t m a -> t m a -> t m a
664−ahead m1 m2 = mkStream $ \st yld sng stp ->
617+{-# INLINE aheadK #-}
618+aheadK :: MonadAsync m => Stream m a -> Stream m a -> Stream m a
619+aheadK m1 m2 = K.mkStream $ \st yld sng stp ->
665620 case streamVar st of
666621 Just sv | svarStyle sv == AheadVar -> do
667622 runInIO <- captureMonadState
668− liftIO $ enqueue sv (runInIO, toStream m2)
623+ liftIO $ enqueue sv (runInIO, m2)
669624 -- Always run the left side on a new SVar to avoid complexity in
670625 -- sequencing results. This means the left side cannot further
671626 -- split into more ahead computations on the same SVar.
672− foldStream st yld sng stp m1
673− _ -> foldStreamShared st yld sng stp (forkSVarAhead m1 m2)
627+ K.foldStream st yld sng stp m1
628+ _ -> K.foldStreamShared st yld sng stp (forkSVarAhead m1 m2)
674629
675630-- | XXX we can implement it more efficienty by directly implementing instead
676631-- of combining streams using ahead.
677−{-# INLINE consMAhead #-}
678−{-# SPECIALIZE consMAhead :: IO a -> AheadT IO a -> AheadT IO a #-}
679−consMAhead :: MonadAsync m => m a -> AheadT m a -> AheadT m a
680−consMAhead m r = fromStream $ K.fromEffect m `ahead` toStream r
632+{-# INLINE consM #-}
633+{-# SPECIALIZE consM :: IO a -> AheadT IO a -> AheadT IO a #-}
634+consM :: MonadAsync m => m a -> AheadT m a -> AheadT m a
635+consM m (AheadT r) = AheadT $ aheadK (K.fromEffect m) r
681636
682637------------------------------------------------------------------------------
683638-- AheadT
@@ -737,66 +692,58 @@ newtype AheadT m a = AheadT {getAheadT :: Stream m a}
737692-- @since 0.8.0
738693type Ahead = AheadT IO
739694
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−
754695------------------------------------------------------------------------------
755696-- Semigroup
756697------------------------------------------------------------------------------
757698
758−{-# INLINE mappendAhead #-}
759−{-# SPECIALIZE mappendAhead :: AheadT IO a -> AheadT IO a -> AheadT IO a #-}
760−mappendAhead :: MonadAsync m => AheadT m a -> AheadT m a -> AheadT m a
761−mappendAhead m1 m2 = fromStream $ ahead (toStream m1) (toStream m2)
699+{-# INLINE append #-}
700+{-# SPECIALIZE append :: AheadT IO a -> AheadT IO a -> AheadT IO a #-}
701+append :: MonadAsync m => AheadT m a -> AheadT m a -> AheadT m a
702+append (AheadT m1) (AheadT m2) = AheadT $ aheadK m1 m2
762703
763704instance MonadAsync m => Semigroup (AheadT m a) where
764− (<>) = mappendAhead
705+ (<>) = append
765706
766707------------------------------------------------------------------------------
767708-- Monoid
768709------------------------------------------------------------------------------
769710
770711instance MonadAsync m => Monoid (AheadT m a) where
771− mempty = K.nil
712+ mempty = AheadT K.nil
772713 mappend = (<>)
773714
774715------------------------------------------------------------------------------
775−-- Monad
716+-- Applicative
776717------------------------------------------------------------------------------
777718
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−
784719{-# INLINE apAhead #-}
785720apAhead :: MonadAsync m => AheadT m (a -> b) -> AheadT m a -> AheadT m b
786721apAhead (AheadT m1) (AheadT m2) =
787− let f x1 = K.concatMapBy ahead (pure . x1) m2
788− in AheadT $ K.concatMapBy ahead f m1
722+ let f x1 = K.concatMapWith aheadK (pure . x1) m2
723+ in AheadT $ K.concatMapWith aheadK f m1
789724
790725instance (Monad m, MonadAsync m) => Applicative (AheadT m) where
791726 {-# INLINE pure #-}
792727 pure = AheadT . K.fromPure
728+
793729 {-# INLINE (<*>) #-}
794730 (<*>) = apAhead
795731
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+
796742instance MonadAsync m => Monad (AheadT m) where
797743 return = pure
744+
798745 {-# INLINE (>>=) #-}
799− (>>=) = flip concatMapAhead
746+ (>>=) = bindAhead
800747
801748------------------------------------------------------------------------------
802749-- Other instances
src/Streamly/Internal/Data/Stream/Async.hs+74−250
@@ -24,18 +24,17 @@
2424--
2525module Streamly.Internal.Data.Stream.Async
2626 (
27− AsyncT
27+ AsyncT(..)
2828 , Async
29− , fromAsync
30− , async
31− , (<|) --deprecated
32− , mkAsync
29+ , consMAsync
30+ , asyncK
3331 , mkAsyncK
32+ , mkAsyncD
3433
35− , WAsyncT
34+ , WAsyncT(..)
3635 , WAsync
37− , fromWAsync
38− , wAsync
36+ , consMWAsync
37+ , wAsyncK
3938 )
4039where
4140
@@ -63,11 +62,10 @@ import Streamly.Internal.Control.Concurrent
6362 (MonadAsync, RunInIO(..), captureMonadState)
6463import Streamly.Internal.Data.Atomics
6564 (atomicModifyIORefCAS, atomicModifyIORefCAS_)
65+import Streamly.Internal.Data.Stream.Serial (SerialT (..))
66+import Streamly.Internal.Data.Stream.StreamK.Type (Stream)
6667import Streamly.Internal.Data.Stream.SVar.Generate (fromSVar, fromSVarD)
67−import Streamly.Internal.Data.Stream.StreamK.Type
68− (IsStream(..), Stream, mkStream, foldStream, adapt, foldStreamShared)
6968
70−import qualified Streamly.Internal.Data.Stream.StreamK as K (withLocal)
7169import qualified Streamly.Internal.Data.Stream.StreamK.Type as K
7270import qualified Streamly.Internal.Data.Stream.StreamD.Type as D
7371
@@ -130,7 +128,7 @@ workLoopLIFO q st sv winfo = run
130128 -- monad state here. That way it can work easily for
131129 -- distributed case as well.
132130 r <- liftIO $ runin $
133− foldStreamShared st yieldk single (return Continue) m
131+ K.foldStreamShared st yieldk single (return Continue) m
134132 res <- restoreM r
135133 case res of
136134 Continue -> run
@@ -143,7 +141,7 @@ workLoopLIFO q st sv winfo = run
143141 yieldk a r = do
144142 res <- liftIO $ sendYield sv winfo (ChildYield a)
145143 if res
146− then foldStreamShared st yieldk single (return Continue) r
144+ then K.foldStreamShared st yieldk single (return Continue) r
147145 else do
148146 runInIO <- captureMonadState
149147 liftIO $ enqueueLIFO sv q (runInIO, r)
@@ -187,7 +185,7 @@ workLoopLIFOLimited q st sv winfo = run
187185 if yieldLimitOk
188186 then do
189187 r <- liftIO $ runin $
190− foldStreamShared st yieldk single incrContinue m
188+ K.foldStreamShared st yieldk single incrContinue m
191189 res <- restoreM r
192190 case res of
193191 Continue -> run
@@ -209,7 +207,7 @@ workLoopLIFOLimited q st sv winfo = run
209207 res <- liftIO $ sendYield sv winfo (ChildYield a)
210208 yieldLimitOk <- liftIO $ decrementYieldLimit sv
211209 if res && yieldLimitOk
212− then foldStreamShared st yieldk single incrContinue r
210+ then K.foldStreamShared st yieldk single incrContinue r
213211 else do
214212 runInIO <- captureMonadState
215213 liftIO $ incrementYieldLimit sv
@@ -259,7 +257,7 @@ workLoopFIFO q st sv winfo = run
259257 Nothing -> stop
260258 Just (RunInIO runin, m) -> do
261259 r <- liftIO $ runin $
262− foldStreamShared st yieldk single (return Continue) m
260+ K.foldStreamShared st yieldk single (return Continue) m
263261 res <- restoreM r
264262 case res of
265263 Continue -> run
@@ -302,7 +300,7 @@ workLoopFIFOLimited q st sv winfo = run
302300 if yieldLimitOk
303301 then do
304302 r <- liftIO $ runin $
305− foldStreamShared st yieldk single incrContinue m
303+ K.foldStreamShared st yieldk single incrContinue m
306304 res <- restoreM r
307305 case res of
308306 Continue -> run
@@ -545,18 +543,21 @@ newAsyncVar st m = do
545543-- /Pre-release/
546544--
547545{-# INLINABLE mkAsyncK #-}
548−mkAsyncK :: (IsStream t, MonadAsync m) => t m a -> t m a
549−mkAsyncK m = mkStream $ \st yld sng stp -> do
550− sv <- newAsyncVar (adaptState st) (toStream m)
551− foldStream st yld sng stp $ fromSVar sv
546+mkAsyncK :: MonadAsync m => Stream m a -> Stream m a
547+mkAsyncK m = K.mkStream $ \st yld sng stp -> do
548+ sv <- newAsyncVar (adaptState st) m
549+ K.foldStream st yld sng stp $ getSerialT $ fromSVar sv
552550
551+--
552+-- This is slightly faster than the CPS version above
553+--
553554{-# INLINE_NORMAL mkAsyncD #-}
554555mkAsyncD :: MonadAsync m => D.Stream m a -> D.Stream m a
555556mkAsyncD m = D.Stream step Nothing
556557 where
557558
558559 step gst Nothing = do
559− sv <- newAsyncVar gst (D.fromStreamD m)
560+ sv <- newAsyncVar gst (D.toStreamK m)
560561 return $ D.Skip $ Just $ fromSVarD sv
561562
562563 step gst (Just (D.UnStream step1 st)) = do
@@ -566,23 +567,7 @@ mkAsyncD m = D.Stream step Nothing
566567 D.Skip s -> D.Skip (Just $ D.Stream step1 s)
567568 D.Stop -> D.Stop
568569
569−--
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−
570+-- XXX We can pass captureMonadState instead of using MonadAsync
586571-- | Create a new SVar and enqueue one stream computation on it.
587572{-# INLINABLE newWAsyncVar #-}
588573newWAsyncVar :: MonadAsync m
@@ -590,6 +575,8 @@ newWAsyncVar :: MonadAsync m
590575newWAsyncVar st m = do
591576 mrun <- captureMonadState
592577 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
593580 sendFirstWorker sv m
594581
595582------------------------------------------------------------------------------
@@ -656,109 +643,38 @@ newWAsyncVar st m = do
656643-- composition and vice-versa we create a new SVar to isolate the scheduling
657644-- of the two.
658645
659−forkSVarAsync :: (IsStream t, MonadAsync m)
660− => SVarStyle -> t m a -> t m a -> t m a
661−forkSVarAsync style m1 m2 = mkStream $ \st yld sng stp -> do
646+forkSVarAsync :: MonadAsync m
647+ => SVarStyle -> Stream m a -> Stream m a -> Stream m a
648+forkSVarAsync style m1 m2 = K.mkStream $ \st yld sng stp -> do
662649 sv <- case style of
663− AsyncVar -> newAsyncVar st (concurrently (toStream m1) (toStream m2))
664− WAsyncVar -> newWAsyncVar st (concurrently (toStream m1) (toStream m2))
650+ AsyncVar -> newAsyncVar st (concurrently m1 m2)
651+ WAsyncVar -> newWAsyncVar st (concurrently m1 m2)
665652 _ -> error "illegal svar type"
666− foldStream st yld sng stp $ fromSVar sv
653+ K.foldStream st yld sng stp $ getSerialT $ fromSVar sv
667654 where
668− concurrently ma mb = mkStream $ \st yld sng stp -> do
655+ concurrently ma mb = K.mkStream $ \st yld sng stp -> do
669656 runInIO <- captureMonadState
670657 liftIO $ enqueue (fromJust $ streamVar st) (runInIO, mb)
671− foldStreamShared st yld sng stp ma
658+ K.foldStreamShared st yld sng stp ma
672659
673660{-# INLINE joinStreamVarAsync #-}
674−joinStreamVarAsync :: (IsStream t, MonadAsync m)
675− => SVarStyle -> t m a -> t m a -> t m a
676−joinStreamVarAsync style m1 m2 = mkStream $ \st yld sng stp ->
661+joinStreamVarAsync :: MonadAsync m
662+ => SVarStyle -> Stream m a -> Stream m a -> Stream m a
663+joinStreamVarAsync style m1 m2 = K.mkStream $ \st yld sng stp ->
677664 case streamVar st of
678665 Just sv | svarStyle sv == style -> do
679666 runInIO <- captureMonadState
680− liftIO $ enqueue sv (runInIO, toStream m2)
681− foldStreamShared st yld sng stp m1
682− _ -> foldStreamShared st yld sng stp (forkSVarAsync style m1 m2)
667+ liftIO $ enqueue sv (runInIO, m2)
668+ K.foldStreamShared st yld sng stp m1
669+ _ -> K.foldStreamShared st yld sng stp (forkSVarAsync style m1 m2)
683670
684671------------------------------------------------------------------------------
685672-- Semigroup and Monoid style compositions for parallel actions
686673------------------------------------------------------------------------------
687674
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 #-}
752−async :: (IsStream t, MonadAsync m) => t m a -> t m a -> t m a
753−async = 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
675+{-# INLINE asyncK #-}
676+asyncK :: MonadAsync m => Stream m a -> Stream m a -> Stream m a
677+asyncK = joinStreamVarAsync AsyncVar
762678
763679-- IMPORTANT: using a monomorphically typed and SPECIALIZED consMAsync makes a
764680-- huge difference in the performance of consM in IsStream instance even we
@@ -769,7 +685,7 @@ async = joinStreamVarAsync AsyncVar
769685{-# INLINE consMAsync #-}
770686{-# SPECIALIZE consMAsync :: IO a -> AsyncT IO a -> AsyncT IO a #-}
771687consMAsync :: 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
773689
774690------------------------------------------------------------------------------
775691-- AsyncT
@@ -829,40 +745,26 @@ newtype AsyncT m a = AsyncT {getAsyncT :: Stream m a}
829745-- @since 0.8.0
830746type Async = AsyncT IO
831747
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−
846748------------------------------------------------------------------------------
847749-- Semigroup
848750------------------------------------------------------------------------------
849751
850752-- Monomorphically typed version of "async" for better performance of Semigroup
851753-- instance.
852−{-# INLINE mappendAsync #-}
853−{-# SPECIALIZE mappendAsync :: AsyncT IO a -> AsyncT IO a -> AsyncT IO a #-}
854−mappendAsync :: MonadAsync m => AsyncT m a -> AsyncT m a -> AsyncT m a
855−mappendAsync m1 m2 = fromStream $ async (toStream m1) (toStream m2)
754+{-# INLINE append #-}
755+{-# SPECIALIZE append :: AsyncT IO a -> AsyncT IO a -> AsyncT IO a #-}
756+append :: MonadAsync m => AsyncT m a -> AsyncT m a -> AsyncT m a
757+append (AsyncT m1) (AsyncT m2) = AsyncT $ asyncK m1 m2
856758
857759instance MonadAsync m => Semigroup (AsyncT m a) where
858− (<>) = mappendAsync
760+ (<>) = append
859761
860762------------------------------------------------------------------------------
861763-- Monoid
862764------------------------------------------------------------------------------
863765
864766instance MonadAsync m => Monoid (AsyncT m a) where
865− mempty = K.nil
767+ mempty = AsyncT K.nil
866768 mappend = (<>)
867769
868770------------------------------------------------------------------------------
@@ -873,12 +775,13 @@ instance MonadAsync m => Monoid (AsyncT m a) where
873775{-# SPECIALIZE apAsync :: AsyncT IO (a -> b) -> AsyncT IO a -> AsyncT IO b #-}
874776apAsync :: MonadAsync m => AsyncT m (a -> b) -> AsyncT m a -> AsyncT m b
875777apAsync (AsyncT m1) (AsyncT m2) =
876− let f x1 = K.concatMapBy async (pure . x1) m2
877− in AsyncT $ K.concatMapBy async f m1
778+ let f x1 = K.concatMapWith asyncK (pure . x1) m2
779+ in AsyncT $ K.concatMapWith asyncK f m1
878780
879781instance (Monad m, MonadAsync m) => Applicative (AsyncT m) where
880782 {-# INLINE pure #-}
881783 pure = AsyncT . K.fromPure
784+
882785 {-# INLINE (<*>) #-}
883786 (<*>) = apAsync
884787
@@ -889,9 +792,10 @@ instance (Monad m, MonadAsync m) => Applicative (AsyncT m) where
889792-- GHC: if we change the implementation of bindWith with arguments in a
890793-- different order we see a significant performance degradation (~2x).
891794{-# INLINE bindAsync #-}
892−{-# SPECIALIZE bindAsync :: AsyncT IO a -> (a -> AsyncT IO b) -> AsyncT IO b #-}
795+{-# SPECIALIZE bindAsync ::
796+ AsyncT IO a -> (a -> AsyncT IO b) -> AsyncT IO b #-}
893797bindAsync :: 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)
895799
896800-- GHC: if we specify arguments in the definition of (>>=) we see a significant
897801-- performance degradation (~2x).
@@ -909,84 +813,16 @@ MONAD_COMMON_INSTANCES(AsyncT, MONADPARALLEL)
909813-- WAsyncT
910814------------------------------------------------------------------------------
911815
816+{-# INLINE wAsyncK #-}
817+wAsyncK :: MonadAsync m => Stream m a -> Stream m a -> Stream m a
818+wAsyncK = joinStreamVarAsync WAsyncVar
819+
912820-- | XXX we can implement it more efficienty by directly implementing instead
913821-- of combining streams using wAsync.
914822{-# INLINE consMWAsync #-}
915823{-# SPECIALIZE consMWAsync :: IO a -> WAsyncT IO a -> WAsyncT IO a #-}
916824consMWAsync :: MonadAsync m => m a -> WAsyncT m a -> WAsyncT m a
917−consMWAsync m r = fromStream $ K.fromEffect m `wAsync` toStream 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
825+consMWAsync m (WAsyncT r) = WAsyncT $ wAsyncK (K.fromEffect m) r
990826
991827-- | For 'WAsyncT' streams:
992828--
@@ -1132,38 +968,24 @@ newtype WAsyncT m a = WAsyncT {getWAsyncT :: Stream m a}
1132968-- @since 0.8.0
1133969type WAsync = WAsyncT IO
1134970
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−
1149971------------------------------------------------------------------------------
1150972-- Semigroup
1151973------------------------------------------------------------------------------
1152974
1153−{-# INLINE mappendWAsync #-}
1154−{-# SPECIALIZE mappendWAsync :: WAsyncT IO a -> WAsyncT IO a -> WAsyncT IO a #-}
1155−mappendWAsync :: MonadAsync m => WAsyncT m a -> WAsyncT m a -> WAsyncT m a
1156−mappendWAsync m1 m2 = fromStream $ wAsync (toStream m1) (toStream m2)
975+{-# INLINE wAppend #-}
976+{-# SPECIALIZE wAppend :: WAsyncT IO a -> WAsyncT IO a -> WAsyncT IO a #-}
977+wAppend :: MonadAsync m => WAsyncT m a -> WAsyncT m a -> WAsyncT m a
978+wAppend (WAsyncT m1) (WAsyncT m2) = WAsyncT $ wAsyncK m1 m2
1157979
1158980instance MonadAsync m => Semigroup (WAsyncT m a) where
1159− (<>) = mappendWAsync
981+ (<>) = wAppend
1160982
1161983------------------------------------------------------------------------------
1162984-- Monoid
1163985------------------------------------------------------------------------------
1164986
1165987instance MonadAsync m => Monoid (WAsyncT m a) where
1166− mempty = K.nil
988+ mempty = WAsyncT K.nil
1167989 mappend = (<>)
1168990
1169991------------------------------------------------------------------------------
@@ -1171,11 +993,12 @@ instance MonadAsync m => Monoid (WAsyncT m a) where
1171993------------------------------------------------------------------------------
1172994
1173995{-# INLINE apWAsync #-}
1174−{-# SPECIALIZE apWAsync :: WAsyncT IO (a -> b) -> WAsyncT IO a -> WAsyncT IO b #-}
996+{-# SPECIALIZE apWAsync ::
997+ WAsyncT IO (a -> b) -> WAsyncT IO a -> WAsyncT IO b #-}
1175998apWAsync :: MonadAsync m => WAsyncT m (a -> b) -> WAsyncT m a -> WAsyncT m b
1176999apWAsync (WAsyncT m1) (WAsyncT m2) =
1177− let f x1 = K.concatMapBy wAsync (pure . x1) m2
1178− in WAsyncT $ K.concatMapBy wAsync f m1
1000+ let f x1 = K.concatMapWith wAsyncK (pure . x1) m2
1001+ in WAsyncT $ K.concatMapWith wAsyncK f m1
11791002
11801003-- GHC: if we specify arguments in the definition of (<*>) we see a significant
11811004-- performance degradation (~2x).
@@ -1190,9 +1013,10 @@ instance (Monad m, MonadAsync m) => Applicative (WAsyncT m) where
11901013-- GHC: if we change the implementation of bindWith with arguments in a
11911014-- different order we see a significant performance degradation (~2x).
11921015{-# INLINE bindWAsync #-}
1193−{-# SPECIALIZE bindWAsync :: WAsyncT IO a -> (a -> WAsyncT IO b) -> WAsyncT IO b #-}
1016+{-# SPECIALIZE bindWAsync ::
1017+ WAsyncT IO a -> (a -> WAsyncT IO b) -> WAsyncT IO b #-}
11941018bindWAsync :: 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)
11961020
11971021-- GHC: if we specify arguments in the definition of (>>=) we see a significant
11981022-- performance degradation (~2x).
src/Streamly/Internal/Data/Stream/Instances.hs+13−11
@@ -10,7 +10,8 @@
1010#define MONAD_COMMON_INSTANCES(STREAM,CONSTRAINT) \
1111instance Monad m => Functor (STREAM m) where { \
1212 {-# 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; \
1415 {-# INLINE (<$) #-}; \
1516 (<$) = fmap . const }; \
1617 \
@@ -32,7 +33,7 @@ instance (MonadError e m CONSTRAINT) => MonadError e (STREAM m) where { \
3233 \
3334instance (MonadReader r m CONSTRAINT) => MonadReader r (STREAM m) where { \
3435 ask = lift ask; \
35− local f m = fromStream $ K.withLocal f (toStream m) }; \
36+ local f (STREAM m) = STREAM $ K.withLocal f m }; \
3637 \
3738instance (MonadState s m CONSTRAINT) => MonadState s (STREAM m) where { \
3839 {-# INLINE get #-}; \
@@ -59,7 +60,7 @@ instance (MonadState s m CONSTRAINT) => MonadState s (STREAM m) where { \
5960#define NFDATA1_INSTANCE(STREAM) \
6061instance NFData1 (STREAM Identity) where { \
6162 {-# INLINE liftRnf #-}; \
62− liftRnf r = runIdentity . P.foldl' (\_ x -> r x) () }
63+ liftRnf f (STREAM xs) = runIdentity $ P.foldl' (\_ x -> f x) () xs}
6364#else
6465#define NFDATA1_INSTANCE(STREAM)
6566#endif
@@ -68,17 +69,17 @@ instance NFData1 (STREAM Identity) where { \
6869instance IsList (STREAM Identity a) where { \
6970 type (Item (STREAM Identity a)) = a; \
7071 {-# INLINE fromList #-}; \
71− fromList = P.fromList; \
72+ fromList xs = STREAM $ P.fromList xs; \
7273 {-# INLINE toList #-}; \
73− toList = runIdentity . P.toList }; \
74+ toList (STREAM xs) = runIdentity $ P.toList xs }; \
7475 \
7576instance Eq a => Eq (STREAM Identity a) where { \
7677 {-# INLINE (==) #-}; \
77− (==) xs ys = runIdentity $ P.eqBy (==) xs ys }; \
78+ (==) (STREAM xs) (STREAM ys) = runIdentity $ P.eqBy (==) xs ys }; \
7879 \
7980instance Ord a => Ord (STREAM Identity a) where { \
8081 {-# INLINE compare #-}; \
81− compare xs ys = runIdentity $ P.cmpBy compare xs ys; \
82+ compare (STREAM xs) (STREAM ys) = runIdentity $ P.cmpBy compare xs ys; \
8283 {-# INLINE (<) #-}; \
8384 x < y = case compare x y of { LT -> True; _ -> False }; \
8485 {-# INLINE (<=) #-}; \
@@ -104,11 +105,11 @@ instance Read a => Read (STREAM Identity a) where { \
104105 \
105106instance (a ~ Char) => IsString (STREAM Identity a) where { \
106107 {-# INLINE fromString #-}; \
107− fromString = P.fromList }; \
108+ fromString xs = STREAM $ P.fromList xs }; \
108109 \
109110instance NFData a => NFData (STREAM Identity a) where { \
110111 {-# INLINE rnf #-}; \
111− rnf = runIdentity . P.foldl' (\_ x -> rnf x) () }; \
112+ rnf (STREAM xs) = runIdentity $ P.foldl' (\_ x -> rnf x) () xs}; \
112113
113114-------------------------------------------------------------------------------
114115-- Foldable
@@ -125,7 +126,7 @@ instance NFData a => NFData (STREAM Identity a) where { \
125126instance (Foldable m, Monad m) => Foldable (STREAM m) where { \
126127 \
127128 {-# INLINE foldMap #-}; \
128− foldMap f = fold . P.foldr (mappend . f) mempty; \
129+ foldMap f (STREAM xs) = fold $ P.foldr (mappend . f) mempty xs; \
129130 \
130131 {-# INLINE foldr #-}; \
131132 foldr f z t = appEndo (foldMap (Endo #. f) t) z; \
@@ -169,5 +170,6 @@ instance (Foldable m, Monad m) => Foldable (STREAM m) where { \
169170#define TRAVERSABLE_INSTANCE(STREAM) \
170171instance Traversable (STREAM Identity) where { \
171172 {-# INLINE traverse #-}; \
172− traverse f s = runIdentity $ P.foldr consA (pure mempty) s \
173+ traverse f (STREAM xs) = \
174+ fmap STREAM $ runIdentity $ P.foldr consA (pure mempty) xs \
173175 where { consA x ys = liftA2 K.cons (f x) ys }}
src/Streamly/Internal/Data/Stream/IsStream.hs+4−2
@@ -11,7 +11,7 @@
1111-- experimental APIs.
1212
1313module Streamly.Internal.Data.Stream.IsStream
14− ( module Streamly.Internal.Data.Stream.IsStream.Types
14+ ( module Streamly.Internal.Data.Stream.IsStream.Type
1515 , module Streamly.Internal.Data.Stream.IsStream.Generate
1616 , module Streamly.Internal.Data.Stream.IsStream.Eliminate
1717 , module Streamly.Internal.Data.Stream.IsStream.Transform
@@ -31,4 +31,6 @@ import Streamly.Internal.Data.Stream.IsStream.Lift
3131import Streamly.Internal.Data.Stream.IsStream.Expand
3232import Streamly.Internal.Data.Stream.IsStream.Reduce
3333import 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
2626import Control.Monad.IO.Class (MonadIO(liftIO))
2727import Data.Int (Int64)
2828
29−import Streamly.Internal.Data.SVar
30−import Streamly.Internal.Data.Stream.StreamK.Type
29+import Streamly.Internal.Data.Stream.IsStream.Type
30+ (IsStream, mkStream, foldStreamShared)
3131import Streamly.Internal.Data.Stream.Serial (SerialT)
32+import Streamly.Internal.Data.Stream.StreamK.Type (Stream)
33+
34+import Streamly.Internal.Data.SVar
3235
3336-------------------------------------------------------------------------------
3437-- Concurrency control
src/Streamly/Internal/Data/Stream/IsStream/Common.hs+128−15
@@ -26,6 +26,7 @@ module Streamly.Internal.Data.Stream.IsStream.Common
2626 , fold_
2727
2828 -- * Transformation
29+ , map
2930 , scanlMAfter'
3031 , postscanlM'
3132 , smapM
@@ -39,12 +40,21 @@ module Streamly.Internal.Data.Stream.IsStream.Common
3940 , reverse
4041 , reverse'
4142
43+ -- * Concurrent
44+ , mkAsync
45+ , mkParallel
46+ , parallelFst
47+
4248 -- * Nesting
4349 , concatM
4450 , concatMapM
4551 , concatMap
4652 , splitOnSeq
4753
54+ -- * Zipping
55+ , zipWithM
56+ , zipWith
57+
4858 -- * Deprecated
4959 , yield
5060 , yieldM
@@ -60,15 +70,15 @@ import Streamly.Internal.Control.Concurrent (MonadAsync)
6070import Streamly.Internal.Data.Array.Foreign.Type (Array)
6171import Streamly.Internal.Data.Fold.Type (Fold (..))
6272import 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)
6475import 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())
6776import Streamly.Internal.Data.Time.Units (AbsTime, RelTime64, addToAbsTime64)
6877
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
6981import 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)
7282import qualified Streamly.Internal.Data.Stream.StreamK.Type as K
7383import qualified Streamly.Internal.Data.Stream.StreamD as D
7484#ifdef USE_STREAMK_ONLY
@@ -76,8 +86,9 @@ import qualified Streamly.Internal.Data.Stream.StreamK as S
7686#else
7787import qualified Streamly.Internal.Data.Stream.StreamD as S
7888#endif
89+import Streamly.Internal.System.IO (defaultChunkSize)
7990
80−import Prelude hiding (take, takeWhile, drop, reverse, concatMap)
91+import Prelude hiding (take, takeWhile, drop, reverse, concatMap, map, zipWith)
8192
8293--
8394-- $setup
@@ -124,7 +135,7 @@ import Prelude hiding (take, takeWhile, drop, reverse, concatMap)
124135--
125136{-# INLINE fromPure #-}
126137fromPure :: IsStream t => a -> t m a
127−fromPure = K.fromPure
138+fromPure = fromStream . K.fromPure
128139
129140-- | Same as 'fromPure'
130141--
@@ -151,7 +162,7 @@ yield = fromPure
151162--
152163{-# INLINE fromEffect #-}
153164fromEffect :: (Monad m, IsStream t) => m a -> t m a
154−fromEffect = K.fromEffect
165+fromEffect = fromStream . K.fromEffect
155166
156167-- | Same as 'fromEffect'
157168--
@@ -179,7 +190,7 @@ yieldM = fromEffect
179190-- @since 0.2.0
180191{-# INLINE_EARLY repeatM #-}
181192repeatM :: (IsStream t, MonadAsync m) => m a -> t m a
182−repeatM = K.repeatM
193+repeatM = K.repeatMWith IsStream.consM
183194
184195{-# RULES "repeatM serial" repeatM = repeatMSerial #-}
185196{-# INLINE repeatMSerial #-}
@@ -286,13 +297,30 @@ fold fl strm = do
286297{-# INLINE fold_ #-}
287298fold_ :: Monad m => Fold m a b -> SerialT m a -> m (b, SerialT m a)
288299fold_ fl strm = do
289− (b, str) <- D.fold_ fl $ D.toStreamD strm
290− return $! (b, D.fromStreamD str)
300+ (b, str) <- D.fold_ fl $ IsStream.toStreamD strm
301+ return $! (b, IsStream.fromStreamD str)
291302
292303------------------------------------------------------------------------------
293304-- Transformation
294305------------------------------------------------------------------------------
295306
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+
296324-- | @scanlMAfter' accumulate initial done stream@ is like 'scanlM'' except
297325-- that it provides an additional @done@ function to be applied on the
298326-- accumulator when the stream stops. The result of @done@ is also emitted in
@@ -366,7 +394,7 @@ smapM step initial stream =
366394 (\(s, _) a -> step s a)
367395 (fmap (,undefined) initial)
368396 stream
369− in Serial.map snd r
397+ in map snd r
370398
371399------------------------------------------------------------------------------
372400-- Transformation - Trimming
@@ -439,7 +467,7 @@ intersperseM m = fromStreamS . S.intersperseM m . toStreamS
439467interjectSuffix
440468 :: (IsStream t, MonadAsync m)
441469 => 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
443471 where timed = liftIO (threadDelay (round $ n * 1000000)) >> f
444472
445473------------------------------------------------------------------------------
@@ -469,7 +497,59 @@ reverse s = fromStreamS $ S.reverse $ toStreamS s
469497-- /Pre-release/
470498{-# INLINE reverse' #-}
471499reverse' :: (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)
473553
474554------------------------------------------------------------------------------
475555-- Combine streams and flatten
@@ -575,4 +655,37 @@ concatM generator = concatMapM (\() -> generator) (fromPure ())
575655splitOnSeq
576656 :: (IsStream t, MonadIO m, Storable a, Enum a, Eq a)
577657 => Array a -> Fold m a b -> t m a -> t m b
578−splitOnSeq patt f m = D.fromStreamD $ D.splitOnSeq patt f (D.toStreamD m)
658+splitOnSeq patt f 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
4545 , foldr
4646
4747 -- * Left Folds
48+ -- Lazy left folds are useful only for reversing the stream
49+ , foldlS
50+ , foldlT
51+
4852 , foldl'
4953 , foldl1'
5054 , foldlM'
@@ -151,24 +155,23 @@ where
151155
152156import Control.Monad.Catch (MonadThrow)
153157import Control.Monad.IO.Class (MonadIO(..))
158+import Control.Monad.Trans.Class (MonadTrans(..))
154159import Foreign.Storable (Storable)
155160import Streamly.Internal.Control.Concurrent (MonadAsync)
156161import Streamly.Internal.Data.Parser (Parser (..))
157162import Streamly.Internal.Data.SVar (defState)
158163import Streamly.Internal.Data.Stream.IsStream.Common
159164 ( fold, fold_, drop, findIndices, reverse, splitOnSeq, take
160− , takeWhile)
161−import Streamly.Internal.Data.Stream.Prelude (toStreamS)
162−import Streamly.Internal.Data.Stream.StreamD (fromStreamD, toStreamD)
163−import Streamly.Internal.Data.Stream.StreamK (IsStream)
164−import Streamly.Internal.Data.Stream.Serial (SerialT)
165+ , takeWhile, mkParallel)
166+import Streamly.Internal.Data.Stream.IsStream.Type
167+ (IsStream, toStreamS, fromStreamD, toStreamD)
168+import Streamly.Internal.Data.Stream.Serial (SerialT(..))
165169
166170import qualified Streamly.Internal.Data.Array.Foreign.Type as A
167171import qualified Streamly.Internal.Data.Fold as FL
168−import qualified Streamly.Internal.Data.Stream.Parallel as Par
169−import qualified Streamly.Internal.Data.Stream.Prelude as P
172+import qualified Streamly.Internal.Data.Stream.IsStream.Type as IsStream
170173import 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
172175import qualified Streamly.Internal.Data.Parser.ParserD as PRD
173176import qualified Streamly.Internal.Data.Parser.ParserK.Type as PRK
174177import qualified System.IO as IO
@@ -212,7 +215,7 @@ import Prelude hiding
212215-- @since 0.1.0
213216{-# INLINE uncons #-}
214217uncons :: (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
216219
217220------------------------------------------------------------------------------
218221-- Right Folds
@@ -240,7 +243,7 @@ uncons m = K.uncons (K.adapt m)
240243-- /Since: 0.1.0/
241244{-# INLINE foldrM #-}
242245foldrM :: Monad m => (a -> m b -> m b) -> m b -> SerialT m a -> m b
243−foldrM = P.foldrM
246+foldrM = IsStream.foldrM
244247
245248-- | Right fold, lazy for lazy monads and pure streams, and strict for strict
246249-- monads.
@@ -255,7 +258,7 @@ foldrM = P.foldrM
255258-- @since 0.1.0
256259{-# INLINE foldr #-}
257260foldr :: Monad m => (a -> b -> b) -> b -> SerialT m a -> m b
258−foldr = P.foldr
261+foldr = IsStream.foldr
259262
260263-- XXX This seems to be of limited use as it cannot be used to construct
261264-- recursive structures and for reduction foldl1' is better.
@@ -273,6 +276,27 @@ foldr1 f m = S.foldr1 f (toStreamS m)
273276-- Left Folds
274277------------------------------------------------------------------------------
275278
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+
276300-- | Strict left fold with an extraction function. Like the standard strict
277301-- left fold, but applies a user supplied extraction function (the third
278302-- 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)
282306{-# DEPRECATED foldx "Please use foldl' followed by fmap instead." #-}
283307{-# INLINE foldx #-}
284308foldx :: Monad m => (x -> a -> x) -> x -> (x -> b) -> SerialT m a -> m b
285−foldx = P.foldlx'
309+foldx = IsStream.foldlx'
286310
287311-- | Left associative/strict push fold. @foldl' reduce initial stream@ invokes
288312-- @reduce@ with the accumulator and the next input in the input stream, using
@@ -295,7 +319,7 @@ foldx = P.foldlx'
295319-- @since 0.2.0
296320{-# INLINE foldl' #-}
297321foldl' :: Monad m => (b -> a -> b) -> b -> SerialT m a -> m b
298−foldl' = P.foldl'
322+foldl' = IsStream.foldl'
299323
300324-- | Strict left fold, for non-empty streams, using first element as the
301325-- starting value. Returns 'Nothing' if the stream is empty.
@@ -317,7 +341,7 @@ foldl1' step m = do
317341{-# DEPRECATED foldxM "Please use foldlM' followed by fmap instead." #-}
318342{-# INLINE foldxM #-}
319343foldxM :: Monad m => (x -> a -> m x) -> m x -> (x -> m b) -> SerialT m a -> m b
320−foldxM = P.foldlMx'
344+foldxM = IsStream.foldlMx'
321345
322346-- | Like 'foldl'' but with a monadic step function.
323347--
@@ -422,7 +446,7 @@ mapM_ f m = S.mapM_ f $ toStreamS m
422446-- @since 0.7.0
423447{-# INLINE drain #-}
424448drain :: Monad m => SerialT m a -> m ()
425−drain = P.drain
449+drain = IsStream.drain
426450
427451-- |
428452-- > drainN n = Stream.drain . Stream.take n
@@ -513,14 +537,14 @@ headElse x = D.headElse x . toStreamD
513537-- @since 0.1.1
514538{-# INLINE tail #-}
515539tail :: (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
517541
518542-- | Extract all but the last element of the stream, if any.
519543--
520544-- @since 0.5.0
521545{-# INLINE init #-}
522546init :: (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
524548
525549-- | Extract the last element of the stream, if any.
526550--
@@ -657,7 +681,7 @@ minimumBy cmp m = S.minimumBy cmp (toStreamS m)
657681-- @since 0.1.0
658682{-# INLINE maximum #-}
659683maximum :: (Monad m, Ord a) => SerialT m a -> m (Maybe a)
660−maximum = P.maximum
684+maximum m = S.maximum (toStreamS m)
661685
662686-- | Determine the maximum element in a stream using the supplied comparison
663687-- function.
@@ -755,7 +779,7 @@ elemIndex a = findIndex (== a)
755779-- @since 0.1.0
756780{-# INLINE toList #-}
757781toList :: Monad m => SerialT m a -> m [a]
758−toList = P.toList
782+toList = IsStream.toList
759783
760784-- |
761785-- @
@@ -789,7 +813,7 @@ toHandle h = go
789813 let stop = return ()
790814 single a = liftIO (IO.hPutStrLn h a)
791815 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
793817
794818-- | Convert a stream to a pure stream.
795819--
@@ -801,7 +825,7 @@ toHandle h = go
801825--
802826{-# INLINE toStream #-}
803827toStream :: Monad m => SerialT m a -> m (SerialT n a)
804−toStream = foldr K.cons K.nil
828+toStream = foldr IsStream.cons IsStream.nil
805829
806830-- | Convert a stream to a pure stream in reverse order.
807831--
@@ -813,7 +837,7 @@ toStream = foldr K.cons K.nil
813837--
814838{-# INLINE toStreamRev #-}
815839toStreamRev :: 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
817841
818842------------------------------------------------------------------------------
819843-- Concurrent Application
@@ -853,7 +877,7 @@ toStreamRev = foldl' (flip K.cons) K.nil
853877{-# INLINE (|$.) #-}
854878(|$.) :: (IsStream t, MonadAsync m) => (t m a -> m b) -> (t m a -> m b)
855879-- (|$.) f = f . Async.mkAsync
856−(|$.) f = f . Par.mkParallel
880+(|$.) f = f . mkParallel
857881
858882infixr 0 |$.
859883
@@ -1009,7 +1033,7 @@ stripSuffix m1 m2 = fmap reverse <$> stripPrefix (reverse m1) (reverse m2)
10091033-- @since 0.6.0
10101034{-# INLINABLE eqBy #-}
10111035eqBy :: (IsStream t, Monad m) => (a -> b -> Bool) -> t m a -> t m b -> m Bool
1012−eqBy = P.eqBy
1036+eqBy = IsStream.eqBy
10131037
10141038-- | Compare two streams lexicographically using a comparison function.
10151039--
@@ -1018,4 +1042,4 @@ eqBy = P.eqBy
10181042cmpBy
10191043 :: (IsStream t, Monad m)
10201044 => (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
6060import Numeric.Natural
6161import Data.Functor.Identity (Identity(..))
6262
63−import Streamly.Internal.Data.Stream.StreamD.Type (fromStreamD)
64−import Streamly.Internal.Data.Stream.StreamK.Type (IsStream(..))
63+import Streamly.Internal.Data.Stream.IsStream.Type (IsStream(..), fromStreamD)
6564
65+import qualified Streamly.Internal.Data.Stream.IsStream.Type as IsStream
6666import qualified Streamly.Internal.Data.Stream.StreamD.Generate as D
6767import qualified Streamly.Internal.Data.Stream.Serial as Serial (map)
6868
@@ -292,8 +292,10 @@ enumerateFromThenToFractional from next to =
292292-- @since 0.6.0
293293{-# INLINE enumerateFromToSmall #-}
294294enumerateFromToSmall :: (IsStream t, Monad m, Enum a) => a -> a -> t m a
295−enumerateFromToSmall from to = Serial.map toEnum $
296− enumerateFromToIntegral (fromEnum from) (fromEnum to)
295+enumerateFromToSmall from to =
296+ IsStream.fromSerial
297+ $ Serial.map toEnum
298+ $ enumerateFromToIntegral (fromEnum from) (fromEnum to)
297299
298300-- | 'enumerateFromThenTo' for 'Enum' types not larger than 'Int'.
299301--
@@ -301,8 +303,11 @@ enumerateFromToSmall from to = Serial.map toEnum $
301303{-# INLINE enumerateFromThenToSmall #-}
302304enumerateFromThenToSmall :: (IsStream t, Monad m, Enum a)
303305 => a -> a -> a -> t m a
304−enumerateFromThenToSmall from next to = Serial.map toEnum $
305− enumerateFromThenToIntegral (fromEnum from) (fromEnum next) (fromEnum to)
306+enumerateFromThenToSmall from next to =
307+ IsStream.fromSerial
308+ $ Serial.map toEnum
309+ $ enumerateFromThenToIntegral
310+ (fromEnum from) (fromEnum next) (fromEnum to)
306311
307312-- | 'enumerateFromThen' for 'Enum' types not larger than 'Int'.
308313--
@@ -550,17 +555,19 @@ ENUMERABLE_FRACTIONAL((Ratio a),Integral a)
550555
551556instance Enumerable a => Enumerable (Identity a) where
552557 {-# INLINE enumerateFrom #-}
553− enumerateFrom (Identity from) = Serial.map Identity $
554− enumerateFrom from
558+ enumerateFrom (Identity from) =
559+ IsStream.fromSerial $ Serial.map Identity $ enumerateFrom from
555560 {-# INLINE enumerateFromThen #-}
556− enumerateFromThen (Identity from) (Identity next) = Serial.map Identity $
557− enumerateFromThen from next
561+ enumerateFromThen (Identity from) (Identity next) =
562+ IsStream.fromSerial $ Serial.map Identity $ enumerateFromThen from next
558563 {-# INLINE enumerateFromTo #-}
559− enumerateFromTo (Identity from) (Identity to) = Serial.map Identity $
560− enumerateFromTo from to
564+ enumerateFromTo (Identity from) (Identity to) =
565+ IsStream.fromSerial $ Serial.map Identity $ enumerateFromTo from to
561566 {-# INLINE enumerateFromThenTo #-}
562567 enumerateFromThenTo (Identity from) (Identity next) (Identity to) =
563− Serial.map Identity $ enumerateFromThenTo from next to
568+ IsStream.fromSerial
569+ $ Serial.map Identity
570+ $ enumerateFromThenTo from next to
564571
565572-- TODO
566573{-
src/Streamly/Internal/Data/Stream/IsStream/Exception.hs+15−15
@@ -29,8 +29,8 @@ import Control.Monad.IO.Class (MonadIO(..))
2929import Control.Monad.Trans.Control (MonadBaseControl)
3030import Data.Map.Strict (Map)
3131import Streamly.Internal.Control.Concurrent (MonadAsync)
32−import Streamly.Internal.Data.Stream.StreamD (toStreamD)
33−import Streamly.Internal.Data.Stream.StreamK (IsStream)
32+import Streamly.Internal.Data.Stream.IsStream.Type
33+ (IsStream(..), fromStreamD, toStreamD)
3434
3535import qualified Streamly.Internal.Data.Stream.StreamD as D
3636
@@ -53,7 +53,7 @@ import qualified Streamly.Internal.Data.Stream.StreamD as D
5353-- @since 0.7.0
5454{-# INLINE before #-}
5555before :: (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
5757
5858-- | Like 'after', with following differences:
5959--
@@ -70,7 +70,7 @@ before action xs = D.fromStreamD $ D.before action $ D.toStreamD xs
7070--
7171{-# INLINE after_ #-}
7272after_ :: (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
7474
7575-- | Run the action @m b@ whenever the stream @t m a@ stops normally, or if it
7676-- is garbage collected after a partial lazy evaluation.
@@ -85,7 +85,7 @@ after_ action xs = D.fromStreamD $ D.after_ action $ D.toStreamD xs
8585{-# INLINE after #-}
8686after :: (IsStream t, MonadIO m, MonadBaseControl IO m)
8787 => 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
8989
9090-- | Run the action @m b@ if the stream aborts due to an exception. The
9191-- exception is not caught, simply rethrown.
@@ -95,7 +95,7 @@ after action xs = D.fromStreamD $ D.after action $ D.toStreamD xs
9595-- @since 0.7.0
9696{-# INLINE onException #-}
9797onException :: (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
9999
100100-- | Like 'finally' with following differences:
101101--
@@ -110,7 +110,7 @@ onException action xs = D.fromStreamD $ D.onException action $ D.toStreamD xs
110110--
111111{-# INLINE finally_ #-}
112112finally_ :: (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
114114
115115-- | Run the action @m b@ whenever the stream @t m a@ stops normally, aborts
116116-- 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
131131--
132132{-# INLINE finally #-}
133133finally :: (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
135135
136136-- | Like 'bracket' but with following differences:
137137--
@@ -148,7 +148,7 @@ finally action xs = D.fromStreamD $ D.finally action $ D.toStreamD xs
148148{-# INLINE bracket_ #-}
149149bracket_ :: (IsStream t, MonadCatch m)
150150 => 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 $
152152 D.bracket_ bef aft (toStreamD . bet)
153153
154154-- | Run the alloc action @m b@ with async exceptions disabled but keeping
@@ -193,7 +193,7 @@ bracket bef aft = bracket' bef aft aft aft
193193{-# INLINE bracket' #-}
194194bracket' :: (IsStream t, MonadAsync m, MonadCatch m)
195195 => 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 $
197197 D.bracket' bef aft exc gc (toStreamD . bet)
198198
199199-- | Like 'handle' but the exception handler is also provided with the stream
@@ -212,9 +212,9 @@ bracket' bef aft gc exc bet = D.fromStreamD $
212212ghandle :: (IsStream t, MonadCatch m, Exception e)
213213 => (e -> t m a -> t m a) -> t m a -> t m a
214214ghandle handler =
215− D.fromStreamD
216− . D.ghandle (\e xs -> D.toStreamD $ handler e (D.fromStreamD xs))
217− . D.toStreamD
215+ fromStreamD
216+ . D.ghandle (\e xs -> toStreamD $ handler e (fromStreamD xs))
217+ . toStreamD
218218
219219-- | When evaluating a stream if an exception occurs, stream evaluation aborts
220220-- and the specified exception handler is run with the exception as argument.
@@ -226,7 +226,7 @@ ghandle handler =
226226handle :: (IsStream t, MonadCatch m, Exception e)
227227 => (e -> t m a) -> t m a -> t m a
228228handle handler xs =
229− D.fromStreamD $ D.handle (D.toStreamD . handler) $ D.toStreamD xs
229+ fromStreamD $ D.handle (toStreamD . handler) $ toStreamD xs
230230
231231
232232-- | @retry@ takes 3 arguments
@@ -269,4 +269,4 @@ retry :: (IsStream t, MonadCatch m, Exception e, Ord e)
269269 -> t m a
270270 -> t m a
271271retry 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
3030 , async
3131 , wAsync
3232 , parallel
33− , Par.parallelFst
34− , Par.parallelMin
33+ , parallelFst
34+ , parallelMin
3535
3636 -- * Binary Combinators (Pair Wise)
3737 -- | Like the functions in the section above these functions also combine
@@ -68,10 +68,10 @@ module Streamly.Internal.Data.Stream.IsStream.Expand
6868 , roundrobin
6969
7070 -- ** Zip
71− , Z.zipWith
72− , Z.zipWithM
73− , Z.zipAsyncWith
74− , Z.zipAsyncWithM
71+ , zipWith
72+ , zipWithM
73+ , zipAsyncWith
74+ , zipAsyncWithM
7575
7676 -- ** Merge
7777 -- , merge
@@ -120,9 +120,9 @@ module Streamly.Internal.Data.Stream.IsStream.Expand
120120 -- * Flatten Containers
121121 -- | Flatten 'Foldable' containers using the binary stream merging
122122 -- operations.
123− , concatFoldableWith
124− , concatMapFoldableWith
125− , concatForFoldableWith
123+ , IsStream.concatFoldableWith
124+ , IsStream.concatMapFoldableWith
125+ , IsStream.concatForFoldableWith
126126
127127 -- * ConcatMapWith
128128 -- | Map and flatten a stream like 'concatMap' but using a custom binary
@@ -136,8 +136,8 @@ module Streamly.Internal.Data.Stream.IsStream.Expand
136136 -- fashion, a pair wise merging using 'concatPairsWith' would be more
137137 -- efficient. These cases include operations like 'mergeBy' or 'zipWith'.
138138
139− , concatMapWith
140− , K.bindWith
139+ , IsStream.concatMapWith
140+ , IsStream.bindWith
141141 , concatSmapMWith
142142
143143 -- * ConcatPairsWith
@@ -153,49 +153,56 @@ module Streamly.Internal.Data.Stream.IsStream.Expand
153153
154154 -- * Deprecated
155155 , concatUnfold
156+ , (<=>)
157+ , (<|)
156158 )
157159where
158160
159161#include "inline.hs"
160162
161163import Streamly.Internal.Control.Concurrent (MonadAsync)
162−import Streamly.Internal.Data.Stream.Ahead (ahead)
163−import Streamly.Internal.Data.Stream.Async (async, wAsync)
164+import Streamly.Internal.Data.Stream.Ahead (aheadK)
165+import Streamly.Internal.Data.Stream.Async (asyncK, wAsyncK)
164166import Streamly.Internal.Data.Stream.IsStream.Common
165− (concatM, concatMapM, concatMap, smapM, fromPure, fromEffect)
166−import Streamly.Internal.Data.Stream.Parallel (parallel)
167−import Streamly.Internal.Data.Stream.Prelude
168− ( concatFoldableWith, concatMapFoldableWith
169− , concatForFoldableWith, fromStreamS, toStreamS)
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)
167+ ( concatM, concatMapM, concatMap, smapM, fromPure, fromEffect, parallelFst
168+ , zipWith, zipWithM)
169+import Streamly.Internal.Data.Stream.IsStream.Type
170+ (IsStream(..), fromStreamS, toStreamS, fromStreamD, toStreamD)
173171import Streamly.Internal.Data.Unfold.Type (Unfold)
174172
173+import qualified Streamly.Internal.Data.Stream.IsStream.Type as IsStream
175174import qualified Streamly.Internal.Data.Stream.Parallel as Par
176175import qualified Streamly.Internal.Data.Stream.Serial as Serial
177176import 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
179178#ifdef USE_STREAMK_ONLY
180179import qualified Streamly.Internal.Data.Stream.StreamK as S
181180#else
182181import qualified Streamly.Internal.Data.Stream.StreamD as S
183182#endif
184−import qualified Streamly.Internal.Data.Stream.Zip as Z
183+import qualified Streamly.Internal.Data.Stream.Zip as Zip
185184
186−import Prelude hiding (concat, concatMap)
185+import Prelude hiding (concat, concatMap, zipWith)
187186
188187-- $setup
189188-- >>> :m
189+-- >>> import Control.Concurrent (threadDelay)
190190-- >>> import Data.IORef
191191-- >>> import Prelude hiding (zipWith, concatMap, concat)
192192-- >>> 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
194194-- >>> import qualified Streamly.Data.Fold as Fold
195195-- >>> import qualified Streamly.Internal.Data.Fold as Fold
196196-- >>> import qualified Streamly.Internal.Data.Unfold as Unfold
197197-- >>> import qualified Streamly.Internal.Data.Parser as Parser
198198-- >>> 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+--
199206
200207-------------------------------------------------------------------------------
201208-- Appending
@@ -218,10 +225,79 @@ import Prelude hiding (concat, concatMap)
218225append ::(IsStream t, Monad m) => t m b -> t m b -> t m b
219226append m1 m2 = fromStreamD $ D.append (toStreamD m1) (toStreamD m2)
220227
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+
221248-------------------------------------------------------------------------------
222249-- Interleaving
223250-------------------------------------------------------------------------------
224251
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+
225301-- XXX Same as 'wSerial'. We should perhaps rename wSerial to interleave.
226302-- XXX Document the interleaving behavior of side effects in all the
227303-- interleaving combinators.
@@ -341,6 +417,276 @@ interleaveMin m1 m2 = fromStreamD $ D.interleaveMin (toStreamD m1) (toStreamD m2
341417roundrobin ::(IsStream t, Monad m) => t m b -> t m b -> t m b
342418roundrobin m1 m2 = fromStreamD $ D.roundRobin (toStreamD m1) (toStreamD m2)
343419
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+
344690------------------------------------------------------------------------------
345691-- Merging (sorted streams)
346692------------------------------------------------------------------------------
@@ -510,7 +856,7 @@ unfoldManyRoundRobin u m =
510856interpose :: (IsStream t, Monad m)
511857 => c -> Unfold m b c -> t m b -> t m c
512858interpose x unf str =
513− D.fromStreamD $ D.interpose (return x) unf (D.toStreamD str)
859+ fromStreamD $ D.interpose (return x) unf (toStreamD str)
514860
515861-- interposeSuffix x unf str = gintercalateSuffix unf str UF.identity (repeat x)
516862--
@@ -524,7 +870,7 @@ interpose x unf str =
524870interposeSuffix :: (IsStream t, Monad m)
525871 => c -> Unfold m b c -> t m b -> t m c
526872interposeSuffix x unf str =
527− D.fromStreamD $ D.interposeSuffix (return x) unf (D.toStreamD str)
873+ fromStreamD $ D.interposeSuffix (return x) unf (toStreamD str)
528874
529875------------------------------------------------------------------------------
530876-- Combine N Streams - intercalate
@@ -546,9 +892,9 @@ gintercalate
546892 :: (IsStream t, Monad m)
547893 => Unfold m a c -> t m a -> Unfold m b c -> t m b -> t m c
548894gintercalate unf1 str1 unf2 str2 =
549− D.fromStreamD $ D.gintercalate
550− unf1 (D.toStreamD str1)
551− unf2 (D.toStreamD str2)
895+ fromStreamD $ D.gintercalate
896+ unf1 (toStreamD str1)
897+ unf2 (toStreamD str2)
552898
553899-- > intercalate unf seed str = gintercalate unf str unf (repeatM seed)
554900--
@@ -565,7 +911,7 @@ gintercalate unf1 str1 unf2 str2 =
565911{-# INLINE intercalate #-}
566912intercalate :: (IsStream t, Monad m)
567913 => Unfold m b c -> b -> t m b -> t m c
568−intercalate unf seed str = D.fromStreamD $
914+intercalate unf seed str = fromStreamD $
569915 D.unfoldMany unf $ D.intersperse seed (toStreamD str)
570916
571917-- | 'interleaveSuffix' followed by unfold and concat.
@@ -576,9 +922,9 @@ gintercalateSuffix
576922 :: (IsStream t, Monad m)
577923 => Unfold m a c -> t m a -> Unfold m b c -> t m b -> t m c
578924gintercalateSuffix unf1 str1 unf2 str2 =
579− D.fromStreamD $ D.gintercalateSuffix
580− unf1 (D.toStreamD str1)
581− unf2 (D.toStreamD str2)
925+ fromStreamD $ D.gintercalateSuffix
926+ unf1 (toStreamD str1)
927+ unf2 (toStreamD str2)
582928
583929-- > intercalateSuffix unf seed str = gintercalateSuffix unf str unf (repeatM seed)
584930--
@@ -596,7 +942,7 @@ gintercalateSuffix unf1 str1 unf2 str2 =
596942intercalateSuffix :: (IsStream t, Monad m)
597943 => Unfold m b c -> b -> t m b -> t m c
598944intercalateSuffix unf seed str = fromStreamD $ D.unfoldMany unf
599− $ D.intersperseSuffix (return seed) (D.toStreamD str)
945+ $ D.intersperseSuffix (return seed) (toStreamD str)
600946
601947{-
602948{-# INLINE iterateUnfold #-}
@@ -624,25 +970,6 @@ concat = concatMap id
624970-- Combine N Streams - concatMap
625971------------------------------------------------------------------------------
626972
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−
646973-- | Like 'concatMapWith' but carries a state which can be used to share
647974-- information across multiple steps of concat.
648975--
@@ -660,7 +987,8 @@ concatSmapMWith
660987 -> m s
661988 -> t m a
662989 -> t m b
663−concatSmapMWith combine f initial = concatMapWith combine id . smapM f initial
990+concatSmapMWith combine f initial =
991+ IsStream.concatMapWith combine id . smapM f initial
664992
665993-- Keep concating either streams as long as rights are generated, stop as soon
666994-- as a left is generated and concat the left stream.
@@ -700,7 +1028,12 @@ concatPairsWith :: IsStream t =>
7001028 -> (a -> t m b)
7011029 -> t m a
7021030 -> t m b
703−concatPairsWith = K.concatPairsWith
1031+concatPairsWith par f m =
1032+ fromStream
1033+ $ K.concatPairsWith
1034+ (\s1 s2 -> toStream $ fromStream s1 `par` fromStream s2)
1035+ (toStream . f)
1036+ (toStream m)
7041037
7051038------------------------------------------------------------------------------
7061039-- IterateMap - Map and flatten Trees of Streams
@@ -737,9 +1070,9 @@ iterateMapWith
7371070 -> (a -> t m a)
7381071 -> t m a
7391072 -> t m a
740−iterateMapWith combine f = concatMapWith combine go
1073+iterateMapWith combine f = IsStream.concatMapWith combine go
7411074 where
742− go x = fromPure x `combine` concatMapWith combine go (f x)
1075+ go x = fromPure x `combine` IsStream.concatMapWith combine go (f x)
7431076
7441077{-
7451078{-# INLINE iterateUnfold #-}
@@ -776,7 +1109,9 @@ iterateSmapMWith
7761109 -> t m a
7771110 -> t m a
7781111iterateSmapMWith combine f initial stream =
779− concatMap (\b -> concatMapWith combine (go b) stream) (fromEffect initial)
1112+ concatMap
1113+ (\b -> IsStream.concatMapWith combine (go b) stream)
1114+ (fromEffect initial)
7801115
7811116 where
7821117
@@ -784,7 +1119,7 @@ iterateSmapMWith combine f initial stream =
7841119
7851120 feedback b a =
7861121 concatMap
787− (\(b1, s) -> concatMapWith combine (go b1) s)
1122+ (\(b1, s) -> IsStream.concatMapWith combine (go b1) s)
7881123 (fromEffect $ f b a)
7891124
7901125------------------------------------------------------------------------------
@@ -813,4 +1148,5 @@ iterateMapLeftsWith
8131148 -> (a -> t m (Either a b))
8141149 -> t m (Either a b)
8151150 -> t m (Either a b)
816−iterateMapLeftsWith combine f = iterateMapWith combine (either f (const K.nil))
1151+iterateMapLeftsWith combine f =
1152+ iterateMapWith combine (either f (const IsStream.nil))
src/Streamly/Internal/Data/Stream/IsStream/Generate.hs+125−30
@@ -18,10 +18,10 @@
1818module Streamly.Internal.Data.Stream.IsStream.Generate
1919 (
2020 -- * Primitives
21− K.nil
22− , K.nilM
23− , K.cons
24− , (K..:)
21+ IsStream.nil
22+ , IsStream.nilM
23+ , IsStream.cons
24+ , (IsStream..:)
2525
2626 , consM
2727 , (|:)
@@ -68,17 +68,18 @@ module Streamly.Internal.Data.Stream.IsStream.Generate
6868 , iterateM
6969
7070 -- * Cyclic Elements
71− , K.mfix
71+ , mfix
7272
7373 -- * From Containers
74− , P.fromList
74+ , IsStream.fromList
7575 , fromListM
76− , K.fromFoldable
76+ , fromFoldable
7777 , fromFoldableM
7878 , fromCallback
79+ , fromPrimIORef
7980
8081 -- * Deprecated
81− , K.once
82+ , once
8283 , yield
8384 , yieldM
8485 , each
@@ -90,6 +91,7 @@ where
9091#include "inline.hs"
9192
9293import Control.Monad.IO.Class (MonadIO(..))
94+import Data.Primitive.Types (Prim)
9395import Data.Void (Void)
9496import Streamly.Internal.Control.Concurrent (MonadAsync)
9597import Streamly.Internal.Data.Unfold.Type (Unfold)
@@ -99,20 +101,21 @@ import Streamly.Internal.Data.Stream.IsStream.Enumeration
99101import Streamly.Internal.Data.Stream.IsStream.Common
100102 ( absTimesWith, concatM, relTimesWith, timesWith, fromPure, fromEffect
101103 , yield, yieldM, repeatM)
102−import Streamly.Internal.Data.Stream.Prelude (fromStreamS)
103−import Streamly.Internal.Data.Stream.StreamD (fromStreamD)
104−import Streamly.Internal.Data.Stream.StreamK (IsStream((|:), consM))
105−import Streamly.Internal.Data.Stream.Serial (SerialT, WSerialT)
104+import Streamly.Internal.Data.Stream.IsStream.Type
105+ (IsStream (..), fromSerial, consM, fromStreamD, fromStreamS)
106+import Streamly.Internal.Data.Stream.Serial (SerialT(..), WSerialT)
106107import Streamly.Internal.Data.Stream.Zip (ZipSerialM)
107108import Streamly.Internal.Data.Time.Units (AbsTime , RelTime64, addToAbsTime64)
108109
110+import qualified Streamly.Internal.Data.IORef.Prim as Prim
111+import qualified Streamly.Internal.Data.Stream.IsStream.Type as IsStream
109112import qualified Streamly.Internal.Data.Stream.Parallel as Par
110−import qualified Streamly.Internal.Data.Stream.Prelude as P
111113import qualified Streamly.Internal.Data.Stream.Serial as Serial
112114import 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
114116#ifdef USE_STREAMK_ONLY
115117import qualified Streamly.Internal.Data.Stream.StreamK as S
118+import qualified Streamly.Internal.Data.Stream.StreamK.Type as S
116119#else
117120import qualified Streamly.Internal.Data.Stream.StreamD.Generate as S
118121#endif
@@ -217,8 +220,9 @@ unfoldr step seed = fromStreamS (S.unfoldr step seed)
217220--
218221-- /Since: 0.1.0/
219222{-# INLINE_EARLY unfoldrM #-}
220−unfoldrM :: (IsStream t, MonadAsync m) => (b -> m (Maybe (a, b))) -> b -> t m a
221−unfoldrM = K.unfoldrM
223+unfoldrM :: forall t m a b. (IsStream t, MonadAsync m) =>
224+ (b -> m (Maybe (a, b))) -> b -> t m a
225+unfoldrM step = fromStream . K.unfoldrMWith (IsStream.toConsK (consM @t)) step
222226
223227{-# RULES "unfoldrM serial" unfoldrM = unfoldrMSerial #-}
224228{-# INLINE_EARLY unfoldrMSerial #-}
@@ -228,12 +232,13 @@ unfoldrMSerial = Serial.unfoldrM
228232{-# RULES "unfoldrM wSerial" unfoldrM = unfoldrMWSerial #-}
229233{-# INLINE_EARLY unfoldrMWSerial #-}
230234unfoldrMWSerial :: MonadAsync m => (b -> m (Maybe (a, b))) -> b -> WSerialT m a
231−unfoldrMWSerial = Serial.unfoldrM
235+unfoldrMWSerial f = fromSerial . Serial.unfoldrM f
232236
233237{-# RULES "unfoldrM zipSerial" unfoldrM = unfoldrMZipSerial #-}
234238{-# INLINE_EARLY unfoldrMZipSerial #-}
235−unfoldrMZipSerial :: MonadAsync m => (b -> m (Maybe (a, b))) -> b -> ZipSerialM m a
236−unfoldrMZipSerial = Serial.unfoldrM
239+unfoldrMZipSerial :: MonadAsync m =>
240+ (b -> m (Maybe (a, b))) -> b -> ZipSerialM m a
241+unfoldrMZipSerial f = fromSerial . Serial.unfoldrM f
237242
238243------------------------------------------------------------------------------
239244-- From Values
@@ -275,8 +280,9 @@ replicate n = fromStreamS . S.replicate n
275280--
276281-- @since 0.1.1
277282{-# INLINE_EARLY replicateM #-}
278−replicateM :: (IsStream t, MonadAsync m) => Int -> m a -> t m a
279−replicateM = K.replicateM
283+replicateM :: forall t m a. (IsStream t, MonadAsync m) => Int -> m a -> t m a
284+replicateM count =
285+ fromStream . K.replicateMWith (IsStream.toConsK (consM @t)) count
280286
281287{-# RULES "replicateM serial" replicateM = replicateMSerial #-}
282288{-# INLINE replicateMSerial #-}
@@ -422,8 +428,9 @@ fromIndices = fromStreamS . S.fromIndices
422428--
423429-- @since 0.6.0
424430{-# INLINE_EARLY fromIndicesM #-}
425−fromIndicesM :: (IsStream t, MonadAsync m) => (Int -> m a) -> t m a
426−fromIndicesM = K.fromIndicesM
431+fromIndicesM :: forall t m a. (IsStream t, MonadAsync m) =>
432+ (Int -> m a) -> t m a
433+fromIndicesM = fromStream . K.fromIndicesMWith (IsStream.toConsK (consM @t))
427434
428435{-# RULES "fromIndicesM serial" fromIndicesM = fromIndicesMSerial #-}
429436{-# INLINE fromIndicesMSerial #-}
@@ -482,18 +489,90 @@ iterate step = fromStreamS . S.iterate step
482489--
483490-- /Since: 0.7.0 (signature change)/
484491{-# INLINE_EARLY iterateM #-}
485−iterateM :: (IsStream t, MonadAsync m) => (a -> m a) -> m a -> t m a
486−iterateM = K.iterateM
492+iterateM :: forall t m a. (IsStream t, MonadAsync m) =>
493+ (a -> m a) -> m a -> t m a
494+iterateM f = fromStream . K.iterateMWith (IsStream.toConsK (consM @t)) f
487495
488496{-# RULES "iterateM serial" iterateM = iterateMSerial #-}
489497{-# INLINE iterateMSerial #-}
490498iterateMSerial :: MonadAsync m => (a -> m a) -> m a -> SerialT m a
491499iterateMSerial step = fromStreamS . S.iterateM step
492500
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+
493560------------------------------------------------------------------------------
494561-- Conversions
495562------------------------------------------------------------------------------
496563
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+
497576-- |
498577-- @
499578-- fromFoldableM = 'Prelude.foldr' 'consM' 'K.nil'
@@ -511,7 +590,7 @@ iterateMSerial step = fromStreamS . S.iterateM step
511590-- @since 0.3.0
512591{-# INLINE fromFoldableM #-}
513592fromFoldableM :: (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
515594
516595-- |
517596-- @
@@ -526,7 +605,7 @@ fromFoldableM = Prelude.foldr consM K.nil
526605fromListM :: (MonadAsync m, IsStream t) => [m a] -> t m a
527606fromListM = fromFoldableM
528607{-# 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 #-}
530609
531610{-# RULES "fromListM serial" fromListM = fromListMSerial #-}
532611{-# INLINE_EARLY fromListMSerial #-}
@@ -539,7 +618,7 @@ fromListMSerial = fromStreamD . D.fromListM
539618{-# DEPRECATED each "Please use fromFoldable instead." #-}
540619{-# INLINE each #-}
541620each :: (IsStream t, Foldable f) => f a -> t m a
542−each = K.fromFoldable
621+each = fromFoldable
543622
544623-- | Read lines from an IO Handle into a stream of Strings.
545624--
@@ -549,7 +628,7 @@ each = K.fromFoldable
549628fromHandle :: (IsStream t, MonadIO m) => IO.Handle -> t m String
550629fromHandle h = go
551630 where
552− go = K.mkStream $ \_ yld _ stp -> do
631+ go = IsStream.mkStream $ \_ yld _ stp -> do
553632 eof <- liftIO $ IO.hIsEOF h
554633 if eof
555634 then stp
@@ -570,4 +649,20 @@ fromCallback :: MonadAsync m => ((a -> m ()) -> m ()) -> SerialT m a
570649fromCallback setCallback = concatM $ do
571650 (callback, stream) <- Par.newCallbackStream
572651 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)
2828import Control.Monad.Trans.State.Strict (StateT)
2929import Control.Monad.Trans.Class (MonadTrans(..))
3030import 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)
3233import Streamly.Internal.Data.Stream.Serial (SerialT)
33−import Streamly.Internal.Data.Stream.StreamD (fromStreamD, toStreamD)
34−import Streamly.Internal.Data.Stream.StreamK (IsStream)
3534
3635import qualified Streamly.Internal.Data.Stream.StreamD as D
3736#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
163163 , fold
164164 , interjectSuffix
165165 , intersperseM
166+ , map
167+ , parallelFst
166168 , repeatM
167169 , scanlMAfter'
168170 , splitOnSeq
169171 , fromPure)
170−import Streamly.Internal.Data.Stream.StreamK (IsStream)
172+import Streamly.Internal.Data.Stream.IsStream.Type
173+ (IsStream(..), fromStreamD, toStreamD, cons)
171174import Streamly.Internal.Data.Time.Units
172175 ( AbsTime, MilliSecond64(..), addToAbsTime, toRelTime
173176 , toAbsTime)
@@ -179,12 +182,10 @@ import qualified Streamly.Internal.Data.Array.Foreign.Type as A
179182import qualified Streamly.Internal.Data.Fold as FL
180183import qualified Streamly.Internal.Data.Parser.ParserK.Type as PRK
181184import qualified Streamly.Internal.Data.Parser.ParserD as PRD
182−import qualified Streamly.Internal.Data.Stream.Parallel as Par
183−import qualified Streamly.Internal.Data.Stream.Serial as Serial
185+import qualified Streamly.Internal.Data.Stream.IsStream.Type as IsStream
184186import qualified Streamly.Internal.Data.Stream.StreamD as D
185−import qualified Streamly.Internal.Data.Stream.StreamK as K
186187
187−import Prelude hiding (concatMap)
188+import Prelude hiding (concatMap, map)
188189
189190-- $setup
190191-- >>> :m
@@ -265,7 +266,7 @@ foldManyPost
265266 => Fold m a b
266267 -> t m a
267268 -> 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)
269270
270271-- | Apply a 'Fold' repeatedly on a stream and emit the fold outputs in the
271272-- output stream.
@@ -292,7 +293,7 @@ foldMany
292293 => Fold m a b
293294 -> t m a
294295 -> 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)
296297
297298-- | Apply a stream of folds to an input stream and emit the results in the
298299-- output stream.
@@ -328,7 +329,7 @@ foldSequence _f _m = undefined
328329{-# INLINE foldIterateM #-}
329330foldIterateM ::
330331 (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)
332333
333334------------------------------------------------------------------------------
334335-- Parsing
@@ -365,7 +366,7 @@ parseMany
365366 -> t m a
366367 -> t m b
367368parseMany p m =
368− D.fromStreamD $ D.parseMany (PRK.fromParserK p) (D.toStreamD m)
369+ fromStreamD $ D.parseMany (PRK.fromParserK p) (toStreamD m)
369370
370371{-# INLINE parseManyD #-}
371372parseManyD
@@ -374,7 +375,7 @@ parseManyD
374375 -> t m a
375376 -> t m b
376377parseManyD p m =
377− D.fromStreamD $ D.parseMany p (D.toStreamD m)
378+ fromStreamD $ D.parseMany p (toStreamD m)
378379
379380-- | Apply a stream of parsers to an input stream and emit the results in the
380381-- output stream.
@@ -428,8 +429,8 @@ parseIterate
428429 -> b
429430 -> t m a
430431 -> t m b
431−parseIterate f i m = D.fromStreamD $
432− D.parseIterate (PRK.fromParserK . f) i (D.toStreamD m)
432+parseIterate f i m = fromStreamD $
433+ D.parseIterate (PRK.fromParserK . f) i (toStreamD m)
433434
434435------------------------------------------------------------------------------
435436-- Generalized grouping
@@ -492,7 +493,7 @@ groupsBy
492493 -> Fold m a b
493494 -> t m a
494495 -> 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)
496497
497498-- | Unlike @groupsBy@ this function performs a rolling comparison of two
498499-- successive elements in the input stream. @groupsByRolling cmp f $ S.fromList
@@ -513,7 +514,7 @@ groupsByRolling
513514 -> Fold m a b
514515 -> t m a
515516 -> 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)
517518
518519-- |
519520-- > groups = groupsBy (==)
@@ -736,7 +737,7 @@ wordsBy
736737 :: (IsStream t, Monad m)
737738 => (a -> Bool) -> Fold m a b -> t m a -> t m b
738739wordsBy predicate f m =
739− D.fromStreamD $ D.wordsBy predicate f (D.toStreamD m)
740+ fromStreamD $ D.wordsBy predicate f (toStreamD m)
740741
741742-- | Like 'splitOnSuffix' but keeps the suffix attached to the resulting
742743-- splits.
@@ -812,7 +813,8 @@ splitWithSuffix predicate f = foldMany (FL.takeEndBy predicate f)
812813splitOnAny
813814 :: (IsStream t, Monad m, Storable a, Integral a)
814815 => [Array a] -> Fold m a b -> t m a -> t m b
815−splitOnAny subseq f m = undefined -- D.fromStreamD $ D.splitOnAny f subseq (D.toStreamD m)
816+splitOnAny subseq f m = undefined
817+ -- fromStreamD $ D.splitOnAny f subseq (toStreamD m)
816818-}
817819
818820-- XXX use a non-monadic intersperse to remove the MonadAsync constraint.
@@ -907,7 +909,7 @@ splitOnSuffixSeq
907909 :: (IsStream t, MonadIO m, Storable a, Enum a, Eq a)
908910 => Array a -> Fold m a b -> t m a -> t m b
909911splitOnSuffixSeq patt f m =
910− D.fromStreamD $ D.splitOnSuffixSeq False patt f (D.toStreamD m)
912+ fromStreamD $ D.splitOnSuffixSeq False patt f (toStreamD m)
911913
912914{-
913915-- | Like 'splitOn' but drops any empty splits.
@@ -916,7 +918,8 @@ splitOnSuffixSeq patt f m =
916918wordsOn
917919 :: (IsStream t, Monad m, Storable a, Eq a)
918920 => Array a -> Fold m a b -> t m a -> t m b
919−wordsOn subseq f m = undefined -- D.fromStreamD $ D.wordsOn f subseq (D.toStreamD m)
921+wordsOn subseq f m = undefined
922+ -- fromStreamD $ D.wordsOn f subseq (toStreamD m)
920923-}
921924
922925-- | Like 'splitOnSuffixSeq' but keeps the suffix intact in the splits.
@@ -953,7 +956,7 @@ splitWithSuffixSeq
953956 :: (IsStream t, MonadIO m, Storable a, Enum a, Eq a)
954957 => Array a -> Fold m a b -> t m a -> t m b
955958splitWithSuffixSeq patt f m =
956− D.fromStreamD $ D.splitOnSuffixSeq True patt f (D.toStreamD m)
959+ fromStreamD $ D.splitOnSuffixSeq True patt f (toStreamD m)
957960
958961{-
959962-- This can be implemented easily using Rabin Karp
@@ -963,7 +966,7 @@ splitOnSuffixSeqAny
963966 :: (IsStream t, Monad m, Storable a, Integral a)
964967 => [Array a] -> Fold m a b -> t m a -> t m b
965968splitOnSuffixSeqAny subseq f m = undefined
966− -- D.fromStreamD $ D.splitPostAny f subseq (D.toStreamD m)
969+ -- fromStreamD $ D.splitPostAny f subseq (toStreamD m)
967970-}
968971
969972------------------------------------------------------------------------------
@@ -986,7 +989,7 @@ splitOnSuffixSeqAny subseq f m = undefined
986989chunksOf
987990 :: (IsStream t, Monad m)
988991 => 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
990993
991994-- |
992995--
@@ -995,7 +998,7 @@ chunksOf n f = D.fromStreamD . D.chunksOf n f . D.toStreamD
995998chunksOf2
996999 :: (IsStream t, Monad m)
9971000 => 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)
9991002
10001003-- | @arraysOf n stream@ groups the elements in the input stream into arrays of
10011004-- @n@ elements each.
@@ -1008,7 +1011,7 @@ chunksOf2 n action f m = D.fromStreamD $ D.groupsOf2 n action f (D.toStreamD m)
10081011{-# INLINE arraysOf #-}
10091012arraysOf :: (IsStream t, MonadIO m, Storable a)
10101013 => 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
10121015
10131016-- XXX we can implement this by repeatedly applying the 'lrunFor' fold.
10141017-- XXX add this example after fixing the serial stream rate control
@@ -1026,7 +1029,7 @@ intervalsOf
10261029 => Double -> Fold m a b -> t m a -> t m b
10271030intervalsOf n f xs =
10281031 splitWithSuffix isNothing (FL.catMaybes f)
1029− (interjectSuffix n (return Nothing) (Serial.map Just xs))
1032+ (interjectSuffix n (return Nothing) (map Just xs))
10301033
10311034------------------------------------------------------------------------------
10321035-- Windowed classification
@@ -1223,7 +1226,7 @@ classifySessionsBy tick reset ejectPred tmout
12231226 , sessionCount = 0
12241227 , sessionTimerHeap = H.empty
12251228 , sessionKeyValueMap = Map.empty
1226− , sessionOutputStream = K.nil
1229+ , sessionOutputStream = IsStream.nil
12271230 }
12281231
12291232 -- We can eject sessions based on the current session count to limit
@@ -1274,7 +1277,7 @@ classifySessionsBy tick reset ejectPred tmout
12741277 let acc = Tuple' timestamp fs1
12751278 (hp1, mp1, out1, cnt1) <- do
12761279 let vars = (sessionTimerHeap, sessionKeyValueMap,
1277− K.nil, sessionCount)
1280+ IsStream.nil, sessionCount)
12781281 case mOld of
12791282 -- inserting new entry
12801283 Nothing -> do
@@ -1323,7 +1326,7 @@ classifySessionsBy tick reset ejectPred tmout
13231326 ejectAll
13241327 ( sessionTimerHeap
13251328 , sessionKeyValueMap
1326− , K.nil
1329+ , IsStream.nil
13271330 , sessionCount
13281331 )
13291332 return $ session
@@ -1336,7 +1339,7 @@ classifySessionsBy tick reset ejectPred tmout
13361339 -- delete from map and output the fold accumulator
13371340 ejectEntry hp mp out cnt acc key = do
13381341 sess <- extract acc
1339− let out1 = (key, sess) `K.cons` out
1342+ let out1 = (key, sess) `cons` out
13401343 let mp1 = Map.delete key mp
13411344 return (hp, mp1, out1, cnt - 1)
13421345
@@ -1372,7 +1375,8 @@ classifySessionsBy tick reset ejectPred tmout
13721375
13731376 ejectExpired session@SessionState{..} curTime = do
13741377 (hp', mp', out, count) <-
1375− ejectLoop sessionTimerHeap sessionKeyValueMap K.nil sessionCount
1378+ ejectLoop
1379+ sessionTimerHeap sessionKeyValueMap IsStream.nil sessionCount
13761380 return $ session
13771381 { sessionCurTime = curTime
13781382 , sessionCount = count
@@ -1414,7 +1418,7 @@ classifySessionsBy tick reset ejectPred tmout
14141418 return (hp, mp, out, cnt)
14151419
14161420 -- merge timer events in the stream
1417− stream = Serial.map Just str `Par.parallelFst` repeatM timer
1421+ stream = map Just str `parallelFst` repeatM timer
14181422 timer = do
14191423 liftIO $ threadDelay (round $ tick * 1000000)
14201424 return Nothing
@@ -1510,7 +1514,7 @@ splitInnerBy
15101514 -> t m (f a)
15111515 -> t m (f a)
15121516splitInnerBy splitter joiner xs =
1513− D.fromStreamD $ D.splitInnerBy splitter joiner $ D.toStreamD xs
1517+ fromStreamD $ D.splitInnerBy splitter joiner $ toStreamD xs
15141518
15151519-- | Like 'splitInnerBy' but splits assuming the separator joins the segment in
15161520-- a suffix style.
@@ -1524,4 +1528,4 @@ splitInnerBySuffix
15241528 -> t m (f a)
15251529 -> t m (f a)
15261530splitInnerBySuffix 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(..))
6161#endif
6262import Streamly.Internal.Control.Concurrent (MonadAsync)
6363import 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)
6566import Streamly.Internal.Data.Stream.Serial (SerialT)
66−import Streamly.Internal.Data.Stream.StreamK (IsStream)
6767import Streamly.Internal.Data.Time.Units (NanoSecond64(..), toRelTime64)
6868
6969import qualified Data.List as List
@@ -75,7 +75,7 @@ import qualified Streamly.Internal.Data.Stream.IsStream.Generate as Stream
7575import qualified Streamly.Internal.Data.Stream.IsStream.Expand as Stream
7676import qualified Streamly.Internal.Data.Stream.IsStream.Reduce as Stream
7777import 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
7979
8080import Prelude hiding (filter, zipWith, concatMap, concat)
8181
@@ -272,7 +272,7 @@ innerJoin eq s1 s2 = do
272272 b <- s2
273273 if a `eq` b
274274 then return (a, b)
275− else StreamK.nil
275+ else Stream.nil
276276
277277-- If the second stream is too big it can be partitioned based on hashes and
278278-- then we can process one parition at a time.
@@ -338,8 +338,8 @@ leftJoin eq s1 s2 = Stream.evalStateT (return False) $ do
338338 let final = do
339339 r <- lift get
340340 if r
341− then StreamK.nil
342− else StreamK.fromPure Nothing
341+ then Stream.nil
342+ else Stream.fromPure Nothing
343343 b <- fmap Just (Stream.liftInner s2) <> final
344344 case b of
345345 Just b1 ->
@@ -347,7 +347,7 @@ leftJoin eq s1 s2 = Stream.evalStateT (return False) $ do
347347 then do
348348 lift $ put True
349349 return (a, Just b1)
350− else StreamK.nil
350+ else Stream.nil
351351 Nothing -> return (a, Nothing)
352352
353353-- | Like 'outerJoin' but uses a hashmap for efficiency.
@@ -415,11 +415,11 @@ outerJoin eq s1 s =
415415 let final = do
416416 r <- lift get
417417 if r
418− then StreamK.nil
419− else StreamK.fromPure Nothing
418+ then Stream.nil
419+ else Stream.fromPure Nothing
420420 (_i, b) <-
421− Stream.indexed
422− $ fmap Just (Stream.liftInner (Array.toStream arr)) <> final
421+ let stream = IsStream.fromSerial $ Array.toStream arr
422+ in Stream.indexed $ fmap Just (Stream.liftInner stream) <> final
423423 case b of
424424 Just (b1, _used) ->
425425 if a `eq` b1
@@ -428,7 +428,7 @@ outerJoin eq s1 s =
428428 -- XXX Need to use a mutable array
429429 -- when (not used) $ Array.writeIndex i True
430430 return (Just a, Just b1)
431− else StreamK.nil
431+ else Stream.nil
432432 Nothing -> return (Just a, Nothing)
433433
434434-- 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 =
496496 concatM
497497 $ do
498498 -- 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
500500 return $ Stream.filter (\x -> List.any (eq x) xs) s1
501501
502502-- | Like 'intersectBy' but works only on sorted streams.
@@ -546,7 +546,7 @@ differenceBy eq s1 s2 =
546546 -- not emitting an element if it was successfully deleted from s2.
547547 -- we will need a deleteBy that can return whether the element was
548548 -- deleted or not.
549− xs <- Stream.toList $ StreamK.adapt s1
549+ xs <- Stream.toList $ adapt s1
550550 fmap fromList $ foldl' (flip (List.deleteBy eq)) xs s2
551551
552552-- | Like 'differenceBy' but works only on sorted streams.
@@ -585,7 +585,7 @@ unionBy :: (IsStream t, MonadAsync m, Semigroup (t m a)) =>
585585unionBy eq s1 s2 =
586586 concatM
587587 $ do
588− xs <- Stream.toList $ StreamK.adapt s2
588+ xs <- Stream.toList $ adapt s2
589589 -- XXX we can use postscanlMAfter' instead of IORef
590590 ref <- liftIO $ newIORef $! List.nubBy eq xs
591591 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
1414
1515 -- * Folding
1616 , foldrS
17+ , foldrSShared
1718 , foldrT
1819
1920 -- * Mapping
2021 -- | Stateless one-to-one maps.
21− , Serial.map
22+ , map
2223 , sequence
2324 , mapM
2425 , smapM
@@ -30,6 +31,8 @@ module Streamly.Internal.Data.Stream.IsStream.Transform
3031 , tap
3132 , tapOffsetEvery
3233 , tapAsync
34+ , tapAsyncK
35+ , distributeAsync_
3336 , tapRate
3437 , pollCounts
3538
@@ -170,7 +173,8 @@ module Streamly.Internal.Data.Stream.IsStream.Transform
170173 -- ** Concurrent Pipelines
171174 -- | Run streaming stages concurrently.
172175
173− , Par.mkParallel
176+ , mkAsync
177+ , mkParallel
174178 , applyAsync
175179 , (|$)
176180 , (|&)
@@ -226,6 +230,7 @@ import Streamly.Internal.Data.Stream.IsStream.Common
226230 ( absTimesWith
227231 , drop
228232 , findIndices
233+ , map
229234 , postscanlM'
230235 , relTimesWith
231236 , reverse
@@ -236,31 +241,35 @@ import Streamly.Internal.Data.Stream.IsStream.Common
236241 , takeWhile
237242 , interjectSuffix
238243 , intersperseM
244+ , mkAsync
245+ , mkParallel
246+ , zipWith
239247 )
240248import 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)
242251import Streamly.Internal.Data.Stream.Serial (SerialT)
243−import Streamly.Internal.Data.Stream.StreamD (fromStreamD, toStreamD)
244−import Streamly.Internal.Data.Stream.StreamK (IsStream)
245252import Streamly.Internal.Data.SVar (Rate(..))
246253import Streamly.Internal.Data.Time.Units (TimeUnit64, AbsTime, RelTime64)
247254
248255import qualified Streamly.Internal.Data.Fold as FL
249256import qualified Streamly.Internal.Data.Stream.Parallel as Par
250−import qualified Streamly.Internal.Data.Stream.Prelude as P
251257import qualified Streamly.Internal.Data.Stream.Serial as Serial
252258import qualified Streamly.Internal.Data.Stream.StreamD as D
259+#if __GLASGOW_HASKELL__ == 802
253260import qualified Streamly.Internal.Data.Stream.StreamK as K
254−import qualified Streamly.Internal.Data.Stream.Zip as Z
261+#endif
262+import qualified Streamly.Internal.Data.Stream.StreamK.Type as K
255263#ifdef USE_STREAMK_ONLY
256264import qualified Streamly.Internal.Data.Stream.StreamK as S
257265#else
258266import qualified Streamly.Internal.Data.Stream.StreamD as S
259267#endif
268+import qualified Prelude
260269
261270import Prelude hiding
262271 ( filter, drop, dropWhile, take, takeWhile, foldr, map, mapM, sequence
263− , reverse, foldr1 , scanl, scanl1)
272+ , reverse, foldr1 , scanl, scanl1, zipWith)
264273
265274--
266275-- $setup
@@ -320,7 +329,21 @@ transform pipe xs = fromStreamD $ D.transform pipe (toStreamD xs)
320329-- /Pre-release/
321330{-# INLINE foldrS #-}
322331foldrS :: IsStream t => (a -> t m b -> t m b) -> t m b -> t m a -> t m b
323−foldrS = K.foldrS
332+foldrS f z xs =
333+ fromStream
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)
324347
325348-- | Right fold to a transformer monad. This is the most general right fold
326349-- function. 'foldrS' is a special case of 'foldrT', however 'foldrS'
@@ -370,8 +393,9 @@ foldrT f z s = S.foldrT f z (toStreamS s)
370393--
371394-- @since 0.1.0
372395{-# INLINE_EARLY mapM #-}
373−mapM :: (IsStream t, MonadAsync m) => (a -> m b) -> t m a -> t m b
374−mapM = K.mapM
396+mapM :: forall t m a b. (IsStream t, MonadAsync m) =>
397+ (a -> m b) -> t m a -> t m b
398+mapM f = fromStream . K.mapMWith (toConsK (consM @t)) f . toStream
375399
376400{-# RULES "mapM serial" mapM = mapMSerial #-}
377401{-# INLINE mapMSerial #-}
@@ -439,7 +463,7 @@ sequence m = fromStreamS $ S.sequence (toStreamS m)
439463-- @since 0.7.0
440464{-# INLINE tap #-}
441465tap :: (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)
443467
444468-- XXX Remove this. It can be expressed in terms of Fold.sampleFromThen.
445469--
@@ -458,7 +482,7 @@ tap f xs = D.fromStreamD $ D.tap f (D.toStreamD xs)
458482tapOffsetEvery :: (IsStream t, Monad m)
459483 => Int -> Int -> FL.Fold m a b -> t m a -> t m a
460484tapOffsetEvery offset n f xs =
461− D.fromStreamD $ D.tapOffsetEvery offset n f (D.toStreamD xs)
485+ fromStreamD $ D.tapOffsetEvery offset n f (toStreamD xs)
462486
463487-- | Redirect a copy of the stream to a supplied fold and run it concurrently
464488-- in an independent thread. The fold may buffer some elements. The buffer size
@@ -490,7 +514,61 @@ tapOffsetEvery offset n f xs =
490514-- /Pre-release/
491515{-# INLINE tapAsync #-}
492516tapAsync :: (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)
494572
495573-- | @pollCounts predicate transform fold stream@ counts those elements in the
496574-- stream that pass the @predicate@. The resulting count stream is sent to
@@ -518,9 +596,9 @@ pollCounts ::
518596 -> t m a
519597 -> t m a
520598pollCounts predicate transf f xs =
521− D.fromStreamD
522− $ D.pollCounts predicate (D.toStreamD . transf . D.fromStreamD) f
523− $ D.toStreamD xs
599+ fromStreamD
600+ $ D.pollCounts predicate (toStreamD . transf . fromStreamD) f
601+ $ toStreamD xs
524602
525603-- | Calls the supplied function with the number of elements consumed
526604-- every @n@ seconds. The given function is run in a separate thread
@@ -547,7 +625,7 @@ tapRate ::
547625 -> (Int -> m b)
548626 -> t m a
549627 -> 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
551629
552630-- | Apply a monadic function to each element flowing through the stream and
553631-- discard the results.
@@ -583,7 +661,7 @@ trace f = mapM (\x -> void (f x) >> return x)
583661-- /Pre-release/
584662{-# INLINE trace_ #-}
585663trace_ :: (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
587665
588666------------------------------------------------------------------------------
589667-- Scanning with a Fold
@@ -597,7 +675,8 @@ trace_ eff = Serial.mapM (\x -> eff >> return x)
597675-- @since 0.7.0
598676{-# INLINE scan #-}
599677scan :: (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
601680
602681-- | Postscan a stream using the given monadic fold.
603682--
@@ -617,7 +696,7 @@ scan = P.scanOnce
617696-- @since 0.7.0
618697{-# INLINE postscan #-}
619698postscan :: (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
621700
622701------------------------------------------------------------------------------
623702-- Scanning - Transformation by Folding
@@ -644,7 +723,7 @@ postscan = P.postscanOnce
644723{-# DEPRECATED scanx "Please use scanl followed by map instead." #-}
645724{-# INLINE scanx #-}
646725scanx :: (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
648727
649728-- XXX this needs to be concurrent
650729-- 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
807886filter p m = fromStreamS $ S.filter p $ toStreamS m
808887#else
809888filter :: IsStream t => (a -> Bool) -> t m a -> t m a
810−filter = K.filter
889+filter p m = fromStream $ K.filter p $ toStream m
811890#endif
812891
813892-- | Same as 'filter' but with a monadic predicate.
@@ -1365,7 +1444,7 @@ indexedR n = fromStreamD . D.indexedR n . toStreamD
13651444{-# INLINE timestampWith #-}
13661445timestampWith :: (IsStream t, MonadAsync m, Functor (t m))
13671446 => 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)
13691448
13701449-- TBD: check performance vs a custom implementation without using zipWith.
13711450--
@@ -1390,7 +1469,7 @@ timestamped = timestampWith 0.01
13901469{-# INLINE timeIndexWith #-}
13911470timeIndexWith :: (IsStream t, MonadAsync m, Functor (t m))
13921471 => 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)
13941473
13951474-- | Pair each element in a stream with relative times starting from 0, using a
13961475-- 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
14801559{-# INLINE_EARLY mapMaybeM #-}
14811560mapMaybeM :: (IsStream t, MonadAsync m, Functor (t m))
14821561 => (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
14841563
14851564{-# RULES "mapMaybeM serial" mapMaybeM = mapMaybeMSerial #-}
14861565{-# INLINE mapMaybeMSerial #-}
@@ -1559,8 +1638,8 @@ both = fmap (either id id)
15591638-- @since 0.8.0
15601639{-# INLINE (|$) #-}
15611640(|$) :: (IsStream t, MonadAsync m) => (t m a -> t m b) -> (t m a -> t m b)
1562−-- (|$) f = f . Async.mkAsync
1563−(|$) f = f . Par.mkParallel
1641+-- (|$) f = f . mkAsync
1642+(|$) f = f . mkParallel
15641643
15651644infixr 0 |$
15661645
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 @@
11{-# LANGUAGE UndecidableInstances #-}
22
3−#include "inline.hs"
4−
53-- |
64-- Module : Streamly.Internal.Data.Stream.Parallel
75-- Copyright : (c) 2017 Composewell Technologies
@@ -25,24 +23,22 @@
2523module Streamly.Internal.Data.Stream.Parallel
2624 (
2725 -- * Parallel Stream Type
28− ParallelT
26+ ParallelT(..)
2927 , Parallel
30− , fromParallel
28+ , consM
3129
3230 -- * Merge Concurrently
33− , parallel
34− , parallelFst
35− , parallelMin
31+ , parallelK
32+ , parallelFstK
33+ , parallelMinK
3634
3735 -- * Evaluate Concurrently
38− , mkParallel
3936 , mkParallelD
4037 , mkParallelK
4138
4239 -- * Tap Concurrently
43− , tapAsync
40+ , tapAsyncK
4441 , tapAsyncF
45− , distributeAsync_
4642
4743 -- * Callbacks
4844 , newCallbackStream
@@ -70,11 +66,10 @@ import qualified Data.Set as Set
7066
7167import Streamly.Internal.Control.Concurrent (MonadAsync)
7268import Streamly.Internal.Data.Fold.Type (Fold)
69+import Streamly.Internal.Data.Stream.Serial (SerialT(..))
7370import Streamly.Internal.Data.Stream.StreamD.Type (Step(..))
74−import Streamly.Internal.Data.Stream.StreamK
75− (IsStream(..), Stream, mkStream, foldStream, foldStreamShared, adapt)
71+import Streamly.Internal.Data.Stream.StreamK.Type (Stream)
7672
77−import qualified Streamly.Internal.Data.Stream.StreamK as K (withLocal)
7873import qualified Streamly.Internal.Data.Stream.StreamK.Type as K
7974import qualified Streamly.Internal.Data.Stream.StreamD.Type as D
8075import qualified Streamly.Internal.Data.Stream.SVar.Generate as SVar
@@ -82,6 +77,7 @@ import qualified Streamly.Internal.Data.Stream.SVar.Eliminate as SVar
8277
8378import Streamly.Internal.Data.SVar
8479
80+#include "inline.hs"
8581#include "Instances.hs"
8682
8783--
@@ -116,7 +112,7 @@ runOne st m0 winfo =
116112
117113 go m = do
118114 liftIO $ decrementBufferLimit sv
119− foldStreamShared st yieldk single stop m
115+ K.foldStreamShared st yieldk single stop m
120116
121117 sv = fromJust $ streamVar st
122118
@@ -139,7 +135,7 @@ runOneLimited st m0 winfo = go m0
139135 if yieldLimitOk
140136 then do
141137 liftIO $ decrementBufferLimit sv
142− foldStreamShared st yieldk single stop m
138+ K.foldStreamShared st yieldk single stop m
143139 else do
144140 liftIO $ cleanupSVarFromWorker sv
145141 liftIO $ sendStop sv winfo
@@ -165,23 +161,23 @@ runOneLimited st m0 winfo = go m0
165161-- remember the past state.
166162
167163{-# NOINLINE forkSVarPar #-}
168−forkSVarPar :: (IsStream t, MonadAsync m)
169− => SVarStopStyle -> t m a -> t m a -> t m a
170−forkSVarPar ss m r = mkStream $ \st yld sng stp -> do
164+forkSVarPar :: MonadAsync m
165+ => SVarStopStyle -> Stream m a -> Stream m a -> Stream m a
166+forkSVarPar ss m r = K.mkStream $ \st yld sng stp -> do
171167 sv <- newParallelVar ss st
172− pushWorkerPar sv (runOne st{streamVar = Just sv} $ toStream m)
168+ pushWorkerPar sv (runOne st{streamVar = Just sv} m)
173169 case ss of
174170 StopBy -> liftIO $ do
175171 set <- readIORef (workerThreads sv)
176172 writeIORef (svarStopBy sv) $ Set.elemAt 0 set
177173 _ -> return ()
178− pushWorkerPar sv (runOne st{streamVar = Just sv} $ toStream r)
179− foldStream st yld sng stp (SVar.fromSVar sv)
174+ pushWorkerPar sv (runOne st{streamVar = Just sv} r)
175+ K.foldStream st yld sng stp $ getSerialT (SVar.fromSVar sv)
180176
181177{-# INLINE joinStreamVarPar #-}
182−joinStreamVarPar :: (IsStream t, MonadAsync m)
183− => SVarStyle -> SVarStopStyle -> t m a -> t m a -> t m a
184−joinStreamVarPar style ss m1 m2 = mkStream $ \st yld sng stp ->
178+joinStreamVarPar :: MonadAsync m
179+ => SVarStyle -> SVarStopStyle -> Stream m a -> Stream m a -> Stream m a
180+joinStreamVarPar style ss m1 m2 = K.mkStream $ \st yld sng stp ->
185181 case streamVar st of
186182 Just sv | svarStyle sv == style && svarStopStyle sv == ss -> do
187183 -- 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 ->
217213 -- worker spawned by that worker would fork, thus creating layer
218214 -- over layer of workers and a chain of threads leading to a very
219215 -- inefficient execution.
220− pushWorkerPar sv (runOne st $ toStream m1)
221− foldStreamShared st yld sng stp m2
216+ pushWorkerPar sv (runOne st m1)
217+ K.foldStreamShared st yld sng stp m2
222218 _ ->
223219 -- Here WE ARE IN THE CONSUMER THREAD, we create a new SVar, fork
224220 -- worker threads to execute m1 and m2 and this thread starts
225221 -- 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)
227223
228224-------------------------------------------------------------------------------
229225-- User facing APIs
230226-------------------------------------------------------------------------------
231227
228+{-# INLINE parallelK #-}
229+parallelK :: MonadAsync m => Stream m a -> Stream m a -> Stream m a
230+parallelK = joinStreamVarPar ParallelVar StopNone
231+
232232-- | XXX we can implement it more efficienty by directly implementing instead
233233-- of combining streams using parallel.
234−{-# INLINE consMParallel #-}
235−{-# SPECIALIZE consMParallel :: IO a -> ParallelT IO a -> ParallelT IO a #-}
236−consMParallel :: MonadAsync m => m a -> ParallelT m a -> ParallelT m a
237−consMParallel m r = fromStream $ K.fromEffect m `parallel` toStream 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
234+{-# INLINE consM #-}
235+{-# SPECIALIZE consM :: IO a -> ParallelT IO a -> ParallelT IO a #-}
236+consM :: MonadAsync m => m a -> ParallelT m a -> ParallelT m a
237+consM m (ParallelT r) = ParallelT $ parallelK (K.fromEffect m) r
270238
271239-- This is a co-parallel like combinator for streams, where first stream is the
272240-- main stream and the rest are just supporting it, when the first ends
@@ -275,9 +243,9 @@ parallel = joinStreamVarPar ParallelVar StopNone
275243-- | Like `parallel` but stops the output as soon as the first stream stops.
276244--
277245-- /Pre-release/
278−{-# INLINE parallelFst #-}
279−parallelFst :: (IsStream t, MonadAsync m) => t m a -> t m a -> t m a
280−parallelFst = joinStreamVarPar ParallelVar StopBy
246+{-# INLINE parallelFstK #-}
247+parallelFstK :: MonadAsync m => Stream m a -> Stream m a -> Stream m a
248+parallelFstK = joinStreamVarPar ParallelVar StopBy
281249
282250-- This is a race like combinator for streams.
283251--
@@ -285,9 +253,9 @@ parallelFst = joinStreamVarPar ParallelVar StopBy
285253-- stops.
286254--
287255-- /Pre-release/
288−{-# INLINE parallelMin #-}
289−parallelMin :: (IsStream t, MonadAsync m) => t m a -> t m a -> t m a
290−parallelMin = joinStreamVarPar ParallelVar StopAny
256+{-# INLINE parallelMinK #-}
257+parallelMinK :: MonadAsync m => Stream m a -> Stream m a -> Stream m a
258+parallelMinK = joinStreamVarPar ParallelVar StopAny
291259
292260------------------------------------------------------------------------------
293261-- Convert a stream to parallel
@@ -297,16 +265,12 @@ parallelMin = joinStreamVarPar ParallelVar StopAny
297265--
298266-- /Pre-release/
299267--
300−mkParallelK :: (IsStream t, MonadAsync m) => t m a -> t m a
301−mkParallelK m = mkStream $ \st yld sng stp -> do
268+mkParallelK :: MonadAsync m => Stream m a -> Stream m a
269+mkParallelK m = K.mkStream $ \st yld sng stp -> do
302270 sv <- newParallelVar StopNone (adaptState st)
303271 -- pushWorkerPar sv (runOne st{streamVar = Just sv} $ toStream m)
304− SVar.toSVarParallel st sv $ D.toStreamD m
305− foldStream st yld sng stp $ SVar.fromSVar sv
306−
307−-------------------------------------------------------------------------------
308−-- Concurrent application and fold
309−-------------------------------------------------------------------------------
272+ SVar.toSVarParallel st sv $ D.fromStreamK m
273+ K.foldStream st yld sng stp $ getSerialT $ SVar.fromSVar sv
310274
311275-- | Same as 'mkParallel' but for StreamD stream.
312276--
@@ -328,25 +292,6 @@ mkParallelD m = D.Stream step Nothing
328292 Skip s -> Skip (Just $ D.Stream step1 s)
329293 Stop -> Stop
330294
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−
350295-------------------------------------------------------------------------------
351296-- Concurrent tap
352297-------------------------------------------------------------------------------
@@ -392,11 +337,12 @@ mkParallel = D.fromStreamD . mkParallelD . D.toStreamD
392337-- Compare with 'tap'.
393338--
394339-- /Pre-release/
395−{-# INLINE tapAsync #-}
396−tapAsync :: (IsStream t, MonadAsync m) => (t m a -> m b) -> t m a -> t m a
397−tapAsync f m = mkStream $ \st yld sng stp -> do
398− sv <- SVar.newFoldSVar st f
399− foldStreamShared st yld sng stp (SVar.teeToSVar sv m)
340+{-# INLINE tapAsyncK #-}
341+tapAsyncK :: MonadAsync m => (Stream m a -> m b) -> Stream m a -> Stream m a
342+tapAsyncK f m = K.mkStream $ \st yld sng stp -> do
343+ sv <- SVar.newFoldSVar st (f . getSerialT)
344+ K.foldStreamShared st yld sng stp
345+ $ getSerialT (SVar.teeToSVar sv $ SerialT m)
400346
401347data TapState fs st a = TapInit | Tapping !fs st | TapDone st
402348
@@ -450,29 +396,6 @@ tapAsyncF f (D.Stream step1 state1) = D.Stream step TapInit
450396 Skip s -> Skip (TapDone s)
451397 Stop -> Stop
452398
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−
476399------------------------------------------------------------------------------
477400-- ParallelT
478401------------------------------------------------------------------------------
@@ -504,44 +427,24 @@ newtype ParallelT m a = ParallelT {getParallelT :: Stream m a}
504427-- @since 0.8.0
505428type Parallel = ParallelT IO
506429
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−
527430------------------------------------------------------------------------------
528431-- Semigroup
529432------------------------------------------------------------------------------
530433
531−{-# INLINE mappendParallel #-}
532−{-# SPECIALIZE mappendParallel :: ParallelT IO a -> ParallelT IO a -> ParallelT IO a #-}
533−mappendParallel :: MonadAsync m => ParallelT m a -> ParallelT m a -> ParallelT m a
534−mappendParallel m1 m2 = fromStream $ parallel (toStream m1) (toStream m2)
434+{-# INLINE append #-}
435+{-# SPECIALIZE append :: ParallelT IO a -> ParallelT IO a -> ParallelT IO a #-}
436+append :: MonadAsync m => ParallelT m a -> ParallelT m a -> ParallelT m a
437+append (ParallelT m1) (ParallelT m2) = ParallelT $ parallelK m1 m2
535438
536439instance MonadAsync m => Semigroup (ParallelT m a) where
537− (<>) = mappendParallel
440+ (<>) = append
538441
539442------------------------------------------------------------------------------
540443-- Monoid
541444------------------------------------------------------------------------------
542445
543446instance MonadAsync m => Monoid (ParallelT m a) where
544− mempty = K.nil
447+ mempty = ParallelT K.nil
545448 mappend = (<>)
546449
547450------------------------------------------------------------------------------
@@ -549,15 +452,18 @@ instance MonadAsync m => Monoid (ParallelT m a) where
549452------------------------------------------------------------------------------
550453
551454{-# INLINE apParallel #-}
552−{-# SPECIALIZE apParallel :: ParallelT IO (a -> b) -> ParallelT IO a -> ParallelT IO b #-}
553−apParallel :: MonadAsync m => ParallelT m (a -> b) -> ParallelT m a -> ParallelT m b
455+{-# SPECIALIZE apParallel ::
456+ ParallelT IO (a -> b) -> ParallelT IO a -> ParallelT IO b #-}
457+apParallel :: MonadAsync m =>
458+ ParallelT m (a -> b) -> ParallelT m a -> ParallelT m b
554459apParallel (ParallelT m1) (ParallelT m2) =
555− let f x1 = K.concatMapBy parallel (pure . x1) m2
556− in ParallelT $ K.concatMapBy parallel f m1
460+ let f x1 = K.concatMapWith parallelK (pure . x1) m2
461+ in ParallelT $ K.concatMapWith parallelK f m1
557462
558463instance (Monad m, MonadAsync m) => Applicative (ParallelT m) where
559464 {-# INLINE pure #-}
560465 pure = ParallelT . K.fromPure
466+
561467 {-# INLINE (<*>) #-}
562468 (<*>) = apParallel
563469
@@ -565,14 +471,17 @@ instance (Monad m, MonadAsync m) => Applicative (ParallelT m) where
565471-- Monad
566472------------------------------------------------------------------------------
567473
568−{-# INLINE bindParallel #-}
569−{-# SPECIALIZE bindParallel :: ParallelT IO a -> (a -> ParallelT IO b) -> ParallelT IO b #-}
570−bindParallel :: 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)
474+{-# INLINE bind #-}
475+{-# SPECIALIZE bind ::
476+ ParallelT IO a -> (a -> ParallelT IO b) -> ParallelT IO b #-}
477+bind :: MonadAsync m => ParallelT m a -> (a -> ParallelT m b) -> ParallelT m b
478+bind (ParallelT m) f = ParallelT $ K.bindWith parallelK m (getParallelT . f)
572479
573480instance MonadAsync m => Monad (ParallelT m) where
574481 return = pure
575− (>>=) = bindParallel
482+
483+ {-# INLINE (>>=) #-}
484+ (>>=) = bind
576485
577486------------------------------------------------------------------------------
578487-- Other instances
@@ -594,7 +503,7 @@ MONAD_COMMON_INSTANCES(ParallelT, MONADPARALLEL)
594503-- /Pre-release/
595504--
596505{-# 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)
598507newCallbackStream = do
599508 sv <- newParallelVar StopNone defState
600509
@@ -606,4 +515,4 @@ newCallbackStream = do
606515 let callback a = liftIO $ void $ send sv (ChildYield a)
607516 -- XXX we can return an SVar and then the consumer can unfold from the
608517 -- 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 #-}
12{-# OPTIONS_GHC -Wno-orphans #-}
23
3−#include "inline.hs"
4−
54-- |
65-- Module : Streamly.Internal.Data.Stream.Prelude
76-- Copyright : (c) 2017 Composewell Technologies
8−--
9−-- License : BSD3
7+-- License : BSD-3-Clause
108-- Maintainer : streamly@composewell.com
119-- Stability : experimental
1210-- Portability : GHC
1311--
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..
1415--
1516module Streamly.Internal.Data.Stream.Prelude
1617 (
17− -- * Stream Conversion
18− fromStreamS
19− , toStreamS
20−
2118 -- * Running Effects
22− , drain
19+ drain
2320
2421 -- * Conversion operations
2522 , fromList
@@ -35,318 +32,26 @@ module Streamly.Internal.Data.Stream.Prelude
3532 , foldl'
3633 , fold
3734
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−
4935 -- * Zip style operations
5036 , eqBy
5137 , 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
6538 )
6639where
6740
68−import Control.Monad.Trans.Class (MonadTrans(..))
69−import Prelude hiding (foldr, minimum, maximum)
70−import qualified Prelude
41+#include "inline.hs"
7142
7243import Streamly.Internal.Data.Fold.Type (Fold (..))
7344
7445#ifdef USE_STREAMK_ONLY
7546import qualified Streamly.Internal.Data.Stream.StreamK as S
47+import qualified Streamly.Internal.Data.Stream.StreamK.Type as S
7648#else
77−import qualified Streamly.Internal.Data.Stream.StreamD as S
49+import qualified Streamly.Internal.Data.Stream.StreamD.Type as S
7850#endif
7951
80−import Streamly.Internal.Data.Stream.StreamK (IsStream(..))
81−import qualified Streamly.Internal.Data.Stream.StreamK as K
82−import qualified Streamly.Internal.Data.Stream.StreamD 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
52+import qualified Streamly.Internal.Data.Stream.StreamK.Type as K
53+import qualified Streamly.Internal.Data.Stream.StreamD.Type as D
19454
195−------------------------------------------------------------------------------
196−-- Scans
197−------------------------------------------------------------------------------
55+import Prelude hiding (foldr, repeat)
19856
199−-- postscanlM' followed by mapM
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
57+#include "PreludeCommon.hs"
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)
3535import Streamly.Internal.Data.Atomics (atomicModifyIORefCAS_)
3636import Streamly.Internal.Data.Fold.SVar (write, writeLimited)
3737import Streamly.Internal.Data.Fold.Type (Fold(..))
38+import Streamly.Internal.Data.Stream.Serial (SerialT(..))
3839import Streamly.Internal.Data.Time.Clock (Clock(Monotonic), getTime)
3940
4041import qualified Streamly.Internal.Data.Stream.StreamD.Type as D
@@ -203,8 +204,8 @@ fromProducer sv = K.mkStream $ \st yld sng stp -> do
203204-- function.
204205--
205206{-# INLINE newFoldSVar #-}
206−newFoldSVar :: (K.IsStream t, MonadAsync m)
207− => State K.Stream m a -> (t m a -> m b) -> m (SVar K.Stream m a)
207+newFoldSVar :: MonadAsync m
208+ => State K.Stream m a -> (SerialT m a -> m b) -> m (SVar K.Stream m a)
208209newFoldSVar stt f = do
209210 -- Buffer size for the SVar is derived from the current state
210211 sv <- newParallelVar StopAny (adaptState stt)
@@ -212,7 +213,7 @@ newFoldSVar stt f = do
212213 -- Add the producer thread-id to the SVar.
213214 liftIO myThreadId >>= modifyThread sv
214215
215− void $ doFork (void $ f $ K.fromStream $ fromProducer sv)
216+ void $ doFork (void $ f $ SerialT $ fromProducer sv)
216217 (svarMrun sv)
217218 (handleFoldException sv)
218219 return sv
@@ -365,9 +366,9 @@ pushToFold sv a = do
365366-- @
366367--
367368{-# INLINE teeToSVar #-}
368−teeToSVar :: (K.IsStream t, MonadAsync m) =>
369− SVar K.Stream m a -> t m a -> t m a
370−teeToSVar svr m = K.mkStream $ \st yld sng stp -> do
369+teeToSVar :: MonadAsync m =>
370+ SVar K.Stream m a -> SerialT m a -> SerialT m a
371+teeToSVar svr (SerialT m) = SerialT $ K.mkStream $ \st yld sng stp -> do
371372 K.foldStreamShared st yld sng stp (go False m)
372373
373374 where
src/Streamly/Internal/Data/Stream/SVar/Generate.hs+7−13
@@ -19,8 +19,7 @@
1919module Streamly.Internal.Data.Stream.SVar.Generate
2020 (
2121 -- * Write to SVar
22− toStreamVar
23− , toSVar
22+ toSVar
2423
2524 -- * Read from SVar
2625 -- $concurrentEval
@@ -39,6 +38,7 @@ import Control.Monad.IO.Class (MonadIO(liftIO))
3938import Data.IORef (newIORef, readIORef, mkWeakIORef, writeIORef)
4039import Data.Maybe (isNothing)
4140import Streamly.Internal.Control.Concurrent (MonadAsync, captureMonadState)
41+import Streamly.Internal.Data.Stream.Serial (SerialT(..))
4242import Streamly.Internal.Data.Time.Clock (Clock(Monotonic), getTime)
4343import System.Mem (performMajorGC)
4444
@@ -88,8 +88,8 @@ import Test.Inspection (inspect, hasNoTypeClassesExcept)
8888-- XXX this errors out for Parallel/Ahead SVars
8989-- | Write a stream to an 'SVar' in a non-blocking manner. The stream can then
9090-- be read back from the SVar using 'fromSVar'.
91−toStreamVar :: MonadAsync m => SVar t m a -> t m a -> m ()
92−toStreamVar sv m = do
91+toSVar :: MonadAsync m => SVar SerialT m a -> SerialT m a -> m ()
92+toSVar sv m = do
9393 runIn <- captureMonadState
9494 liftIO $ enqueue sv (runIn, m)
9595 done <- allThreadsDone sv
@@ -103,12 +103,6 @@ toStreamVar sv m = do
103103 Nothing -> pushWorker 0 sv
104104 Just _ -> pushWorker 1 sv
105105
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−
112106-------------------------------------------------------------------------------
113107-- Read a stream from an SVar
114108-------------------------------------------------------------------------------
@@ -191,16 +185,16 @@ inspect $ hasNoTypeClassesExcept 'fromStreamVar
191185-- combinators.
192186--
193187{-# 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
195189fromSVar sv =
196− K.mkStream $ \st yld sng stp -> do
190+ SerialT $ K.mkStream $ \st yld sng stp -> do
197191 ref <- liftIO $ newIORef ()
198192 _ <- liftIO $ mkWeakIORef ref hook
199193 -- We pass a copy of sv to fromStreamVar, so that we know that it has
200194 -- no other references, when that copy gets garbage collected "ref"
201195 -- will get garbage collected and our hook will be called.
202196 K.foldStreamShared st yld sng stp $
203− K.fromStream $ fromStreamVar sv{svarRef = Just ref}
197+ fromStreamVar sv{svarRef = Just ref}
204198 where
205199
206200 hook = do
src/Streamly/Internal/Data/Stream/Serial.hs+85−114
@@ -16,21 +16,28 @@
1616module Streamly.Internal.Data.Stream.Serial
1717 (
1818 -- * Serial appending stream
19− SerialT
19+ SerialT(..)
2020 , Serial
21− , K.serial
22− , fromSerial
21+ , serial
2322
2423 -- * Serial interleaving stream
25− , WSerialT
24+ , WSerialT(..)
2625 , WSerial
26+ , wSerialK
2727 , wSerial
2828 , wSerialFst
2929 , wSerialMin
30− , fromWSerial
30+ , consMWSerial
3131
3232 -- * Construction
33+ , cons
34+ , consM
35+ , repeat
3336 , unfoldrM
37+ , fromList
38+
39+ -- * Elimination
40+ , toList
3441
3542 -- * Transformation
3643 , map
@@ -39,8 +46,6 @@ module Streamly.Internal.Data.Stream.Serial
3946 -- * Deprecated
4047 , StreamT
4148 , InterleavedT
42− , (<=>)
43− , interleaving
4449 )
4550where
4651
@@ -67,18 +72,16 @@ import Text.Read
6772 ( Lexeme(Ident), lexP, parens, prec, readPrec, readListPrec
6873 , readListPrecDefault)
6974import Streamly.Internal.BaseCompat ((#.), errorWithoutStackTrace, oneShot)
70−import Streamly.Internal.Data.Stream.StreamK.Type
71− (IsStream(..), adapt, Stream, mkStream, foldStream)
7275import Streamly.Internal.Data.Maybe.Strict (Maybe'(..), toMaybe)
76+import Streamly.Internal.Data.Stream.StreamK.Type
77+ (Stream, mkStream, foldStream)
7378
7479import 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
7981import qualified Streamly.Internal.Data.Stream.StreamD.Type as D
82+import qualified Streamly.Internal.Data.Stream.StreamK.Type as K
8083
81−import Prelude hiding (map, mapM, errorWithoutStackTrace)
84+import Prelude hiding (map, mapM, errorWithoutStackTrace, repeat)
8285
8386#include "Instances.hs"
8487#include "inline.hs"
@@ -136,24 +139,33 @@ type Serial = SerialT IO
136139{-# DEPRECATED StreamT "Please use 'SerialT' instead." #-}
137140type StreamT = SerialT
138141
139−-- | Fix the type of a polymorphic stream as 'SerialT'.
140−--
141−-- /Since: 0.1.0 ("Streamly")/
142+------------------------------------------------------------------------------
143+-- Generation
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.
142157--
143−-- @since 0.8.0
144−fromSerial :: IsStream t => SerialT m a -> t m a
145−fromSerial = adapt
158+{-# INLINE_NORMAL repeat #-}
159+repeat :: Monad m => a -> SerialT m a
160+repeat = SerialT . D.toStreamK . D.repeat
146161
147−{-# INLINE consMSerial #-}
148−{-# SPECIALIZE consMSerial :: IO a -> SerialT IO a -> SerialT IO a #-}
149−consMSerial :: Monad m => m a -> SerialT m a -> SerialT m a
150−consMSerial m ms = fromStream $ K.consMStream m (toStream ms)
162+------------------------------------------------------------------------------
163+-- Combining
164+------------------------------------------------------------------------------
151165
152−instance IsStream SerialT where
153− toStream = getSerialT
154− fromStream = SerialT
155− consM = consMSerial
156− (|:) = consMSerial
166+{-# INLINE serial #-}
167+serial :: SerialT m a -> SerialT m a -> SerialT m a
168+serial = (<>)
157169
158170------------------------------------------------------------------------------
159171-- Monad
@@ -173,7 +185,7 @@ instance Monad m => Monad (SerialT m) where
173185 -- n binds, breakAfterSome, filterAllIn, state transformer (~2x)
174186 --
175187 {-# INLINE (>>=) #-}
176− (>>=) = K.bindWith K.serial
188+ (>>=) (SerialT m) f = SerialT $ K.bindWith K.serial m (getSerialT . f)
177189
178190 {-# INLINE (>>) #-}
179191 (>>) = (*>)
@@ -183,8 +195,8 @@ instance Monad m => Monad (SerialT m) where
183195------------------------------------------------------------------------------
184196
185197{-# INLINE mapM #-}
186−mapM :: (IsStream t, Monad m) => (a -> m b) -> t m a -> t m b
187−mapM f m = D.fromStreamD $ D.mapM f $ D.toStreamD m
198+mapM :: Monad m => (a -> m b) -> SerialT m a -> SerialT m b
199+mapM f (SerialT m) = SerialT $ D.toStreamK $ D.mapM f $ D.fromStreamK m
188200
189201-- |
190202-- @
@@ -200,23 +212,23 @@ mapM f m = D.fromStreamD $ D.mapM f $ D.toStreamD m
200212--
201213-- @since 0.4.0
202214{-# 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
204216map f = mapM (return . f)
205217
206218{-# INLINE apSerial #-}
207219apSerial :: Monad m => SerialT m (a -> b) -> SerialT m a -> SerialT m b
208220apSerial (SerialT m1) (SerialT m2) =
209− D.fromStreamD $ D.toStreamD m1 <*> D.toStreamD m2
221+ SerialT $ D.toStreamK $ D.fromStreamK m1 <*> D.fromStreamK m2
210222
211223{-# INLINE apSequence #-}
212224apSequence :: Monad m => SerialT m a -> SerialT m b -> SerialT m b
213225apSequence (SerialT m1) (SerialT m2) =
214− D.fromStreamD $ D.toStreamD m1 *> D.toStreamD m2
226+ SerialT $ D.toStreamK $ D.fromStreamK m1 *> D.fromStreamK m2
215227
216228{-# INLINE apDiscardSnd #-}
217229apDiscardSnd :: Monad m => SerialT m a -> SerialT m b -> SerialT m a
218230apDiscardSnd (SerialT m1) (SerialT m2) =
219− D.fromStreamD $ D.toStreamD m1 <* D.toStreamD m2
231+ SerialT $ D.toStreamK $ D.fromStreamK m1 <* D.fromStreamK m2
220232
221233-- Note: we need to define all the typeclass operations because we want to
222234-- INLINE them.
@@ -285,7 +297,7 @@ TRAVERSABLE_INSTANCE(SerialT)
285297-- @2@:
286298--
287299-- >>> 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)]
289301-- [(1,3),(2,3),(1,4),(2,4)]
290302--
291303-- The @W@ in the name stands for @wide@ or breadth wise scheduling in
@@ -310,37 +322,10 @@ type WSerial = WSerialT IO
310322{-# DEPRECATED InterleavedT "Please use 'WSerialT' instead." #-}
311323type InterleavedT = WSerialT
312324
313−-- | Fix the type of a polymorphic stream as 'WSerialT'.
314−--
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−
325+{-# INLINE consMWSerial #-}
326+{-# SPECIALIZE consMWSerial :: IO a -> WSerialT IO a -> WSerialT IO a #-}
328327consMWSerial :: Monad m => m a -> WSerialT m a -> WSerialT m a
329−consMWSerial m ms = fromStream $ K.consMStream m (toStream 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
328+consMWSerial m (WSerialT ms) = WSerialT $ K.consM m ms
344329
345330------------------------------------------------------------------------------
346331-- Semigroup
@@ -355,25 +340,17 @@ infixr 6 `wSerial`
355340--
356341-- Similar combinators can be implemented using WAhead style.
357342
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+
358351-- | Interleaves two streams, yielding one element from each stream
359352-- alternately. When one stream stops the rest of the other stream is used in
360353-- 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")/
377354
378355-- Scheduling Notes:
379356--
@@ -387,19 +364,15 @@ infixr 6 `wSerial`
387364-- each subexpression on the right.
388365--
389366{-# INLINE wSerial #-}
390−wSerial :: IsStream t => t m a -> t m a -> t m a
391−wSerial m1 m2 = mkStream $ \st yld sng stp -> do
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
367+wSerial :: WSerialT m a -> WSerialT m a -> WSerialT m a
368+wSerial (WSerialT m1) (WSerialT m2) = WSerialT $ wSerialK m1 m2
396369
397370-- | Like `wSerial` but stops interleaving as soon as the first stream stops.
398371--
399372-- @since 0.7.0
400−{-# INLINE wSerialFst #-}
401−wSerialFst :: IsStream t => t m a -> t m a -> t m a
402−wSerialFst m1 m2 = mkStream $ \st yld sng stp -> do
373+{-# INLINE wSerialFstK #-}
374+wSerialFstK :: Stream m a -> Stream m a -> Stream m a
375+wSerialFstK m1 m2 = mkStream $ \st yld sng stp -> do
403376 let yieldFirst a r = yld a (yieldSecond r m2)
404377 in foldStream st yieldFirst sng stp m1
405378
@@ -408,49 +381,47 @@ wSerialFst m1 m2 = mkStream $ \st yld sng stp -> do
408381 yieldSecond s1 s2 = mkStream $ \st yld sng stp -> do
409382 let stop = foldStream st yld sng stp s1
410383 single a = yld a s1
411− yieldk a r = yld a (wSerial s1 r)
384+ yieldk a r = yld a (wSerialK s1 r)
412385 in foldStream st yieldk single stop s2
413386
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+
414391-- | Like `wSerial` but stops interleaving as soon as any of the two streams
415392-- stops.
416393--
417394-- @since 0.7.0
418−{-# INLINE wSerialMin #-}
419−wSerialMin :: IsStream t => t m a -> t m a -> t m a
420−wSerialMin m1 m2 = mkStream $ \st yld _ stp -> do
395+{-# INLINE wSerialMinK #-}
396+wSerialMinK :: Stream m a -> Stream m a -> Stream m a
397+wSerialMinK m1 m2 = mkStream $ \st yld _ stp -> do
421398 let stop = stp
422399 -- "single a" is defined as "yld a (wSerialMin m2 K.nil)" instead of
423400 -- "sng a" to keep the behaviour consistent with the yield continuation.
424− single a = yld a (wSerialMin m2 K.nil)
425− yieldk a r = yld a (wSerialMin m2 r)
401+ single a = yld a (wSerialMinK m2 K.nil)
402+ yieldk a r = yld a (wSerialMinK m2 r)
426403 foldStream st yieldk single stop m1
427404
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+
428409instance Semigroup (WSerialT m a) where
429410 (<>) = wSerial
430411
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−
441412------------------------------------------------------------------------------
442413-- Monoid
443414------------------------------------------------------------------------------
444415
445416instance Monoid (WSerialT m a) where
446− mempty = K.nil
417+ mempty = WSerialT K.nil
447418 mappend = (<>)
448419
449420{-# INLINE apWSerial #-}
450421apWSerial :: Monad m => WSerialT m (a -> b) -> WSerialT m a -> WSerialT m b
451422apWSerial (WSerialT m1) (WSerialT m2) =
452− let f x1 = K.concatMapBy wSerial (pure . x1) m2
453− in WSerialT $ K.concatMapBy wSerial f m1
423+ let f x1 = K.concatMapWith wSerialK (pure . x1) m2
424+ in WSerialT $ K.concatMapWith wSerialK f m1
454425
455426instance Monad m => Applicative (WSerialT m) where
456427 {-# INLINE pure #-}
@@ -465,7 +436,7 @@ instance Monad m => Applicative (WSerialT m) where
465436instance Monad m => Monad (WSerialT m) where
466437 return = pure
467438 {-# INLINE (>>=) #-}
468− (>>=) = K.bindWith wSerial
439+ (>>=) (WSerialT m) f = WSerialT $ K.bindWith wSerialK m (getWSerialT . f)
469440
470441------------------------------------------------------------------------------
471442-- Other instances
@@ -503,5 +474,5 @@ TRAVERSABLE_INSTANCE(WSerialT)
503474-- /Pre-release/
504475--
505476{-# INLINE unfoldrM #-}
506−unfoldrM :: (IsStream t, Monad m) => (b -> m (Maybe (a, b))) -> b -> t m a
507−unfoldrM step seed = D.fromStreamD (D.unfoldrM step seed)
477+unfoldrM :: Monad m => (b -> m (Maybe (a, b))) -> b -> SerialT m a
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
228228-- Specialized Folds
229229------------------------------------------------------------------------------
230230
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−
244231{-# INLINE_NORMAL null #-}
245232null :: Monad m => Stream m a -> m Bool
246233null = 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
8282 -- * Conversions
8383 , fromStreamK
8484 , toStreamK
85− , fromStreamD
86− , toStreamD
8785 )
8886where
8987
src/Streamly/Internal/Data/Stream/StreamD/Transform.hs+3−13
@@ -99,7 +99,7 @@ module Streamly.Internal.Data.Stream.StreamD.Transform
9999 -- * Reordering
100100 -- | Produce strictly the same set but reordered.
101101 , reverse
102− , reverse'
102+ -- , reverse'
103103
104104 -- * Position Indexing
105105 , indexed
@@ -129,7 +129,6 @@ import Control.Monad.IO.Class (MonadIO(..))
129129import Control.Monad.Trans.Class (MonadTrans(lift))
130130import Data.IORef (newIORef, mkWeakIORef)
131131import Data.Maybe (fromJust, isJust)
132−import Foreign.Storable (Storable(..))
133132import GHC.Types (SPEC(..))
134133import qualified Control.Monad.Catch as MC
135134
@@ -140,13 +139,10 @@ import Streamly.Internal.Data.SVar.Type (defState, adaptState)
140139import Streamly.Internal.Data.Time.Clock (Clock(Monotonic), getTime)
141140import Streamly.Internal.Data.Time.Units
142141 (TimeUnit64, toRelTime64, diffAbsTime64)
143−import Streamly.Internal.System.IO (defaultChunkSize)
144142
145−import qualified Streamly.Internal.Data.Array.Foreign.Type as A
146143import qualified Streamly.Internal.Data.Fold.Type as FL
147144import qualified Streamly.Internal.Data.IORef.Prim as Prim
148145import qualified Streamly.Internal.Data.Pipe.Type as Pipe
149−import qualified Streamly.Internal.Data.Stream.StreamK as K
150146
151147import Prelude hiding
152148 ( drop, dropWhile, filter, map, mapM, reverse
@@ -1100,12 +1096,12 @@ reverse m = Stream step Nothing
11001096 step _ (Just []) = return Stop
11011097
11021098-- Much faster reverse for Storables
1099+{-
11031100{-# INLINE_NORMAL reverse' #-}
11041101reverse' :: forall m a. (MonadIO m, Storable a) => Stream m a -> Stream m a
1105−{-
11061102-- This commented implementation copies the whole stream into one single array
11071103-- 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
11091105-- unbounded large allocations. However, if we use an idiomatic implementation
11101106-- of arraysOf instead of the custom implementation then the chunked code
11111107-- becomes worse by 6 times. Need to investigate if that can be improved.
@@ -1130,12 +1126,6 @@ reverse' m = Stream step Nothing
11301126 next = p `plusPtr` negate (sizeOf (undefined :: a))
11311127 return $ Yield x (Just (start, next))
11321128-}
1133−reverse' =
1134− A.flattenArraysRev -- unfoldMany A.readRev
1135− . fromStreamK
1136− . K.reverse
1137− . toStreamK
1138− . A.arraysOf defaultChunkSize
11391129
11401130------------------------------------------------------------------------------
11411131-- Position Indexing
src/Streamly/Internal/Data/Stream/StreamD/Type.hs+21−13
@@ -39,8 +39,6 @@ module Streamly.Internal.Data.Stream.StreamD.Type
3939 -- * Conversions From/To
4040 , fromStreamK
4141 , toStreamK
42− , toStreamD
43− , fromStreamD
4442
4543 -- * Running a 'Fold'
4644 , fold
@@ -59,6 +57,9 @@ module Streamly.Internal.Data.Stream.StreamD.Type
5957 , foldlx'
6058 , foldlMx'
6159
60+ -- * Special Folds
61+ , drain
62+
6263 -- * To Containers
6364 , toList
6465
@@ -239,7 +240,7 @@ fromStreamK = Stream step
239240toStreamK :: Monad m => Stream m a -> K.Stream m a
240241toStreamK (Stream step state) = go state
241242 where
242− go st = K.mkStream $ \gst yld _ stp ->
243+ go st = K.MkStream $ \gst yld _ stp ->
243244 let go' ss = do
244245 r <- step gst ss
245246 case r of
@@ -255,16 +256,6 @@ toStreamK (Stream step state) = go state
255256 forall s. fromStreamK (toStreamK s) = s #-}
256257#endif
257258
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−
268259------------------------------------------------------------------------------
269260-- Running a 'Fold'
270261------------------------------------------------------------------------------
@@ -443,6 +434,23 @@ foldlM' fstep mbegin (Stream step state) = do
443434foldl' :: Monad m => (b -> a -> b) -> b -> Stream m a -> m b
444435foldl' fstep begin = foldlM' (\b a -> return (fstep b a)) (return begin)
445436
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+
446454------------------------------------------------------------------------------
447455-- To Containers
448456------------------------------------------------------------------------------
src/Streamly/Internal/Data/Stream/StreamK.hs+82−343
@@ -21,12 +21,8 @@
2121--
2222module Streamly.Internal.Data.Stream.StreamK
2323 (
24− -- * A class for streams
25− IsStream (..)
26− , adapt
27−
2824 -- * The stream type
29− , Stream(..)
25+ Stream(..)
3026
3127 -- * Construction Primitives
3228 , mkStream
@@ -65,15 +61,12 @@ module Streamly.Internal.Data.Stream.StreamK
6561 , fromEffect
6662 , fromFoldable
6763 , fromList
68− , fromStreamK
6964
7065 -- * foldr/build
7166 , foldrS
7267 , foldrSM
7368 , buildS
74− , buildM
7569 , augmentS
76− , augmentSM
7770
7871 -- * Elimination
7972 -- ** General Folds
@@ -116,7 +109,6 @@ module Streamly.Internal.Data.Stream.StreamK
116109
117110 -- ** Conversions
118111 , toList
119− , toStreamK
120112 , hoist
121113
122114 -- * Transformation
@@ -134,7 +126,6 @@ module Streamly.Internal.Data.Stream.StreamK
134126 -- ** Mapping
135127 , map
136128 , mapM
137− , mapMSerial
138129 , sequence
139130
140131 -- ** Inserting
@@ -160,7 +151,7 @@ module Streamly.Internal.Data.Stream.StreamK
160151 , mergeByM
161152
162153 -- ** Nesting
163− , concatMapBy
154+ , concatMapWith
164155 , concatMap
165156 , bindWith
166157 , concatPairsWith
@@ -176,24 +167,16 @@ module Streamly.Internal.Data.Stream.StreamK
176167 , serial
177168
178169 -- * Utilities
179− , consMStream
170+ , consM
180171 , withLocal
181172 , mfix
182−
183− -- * Deprecated
184− , Streaming -- deprecated
185− , once -- deprecated
186173 )
187174where
188175
189176import Control.Monad.Trans.Class (MonadTrans(lift))
190177import Control.Monad (void, join)
191−import Control.Monad.Reader.Class (MonadReader(..))
192−import Data.Function (fix)
193−import Streamly.Internal.Control.Concurrent (MonadAsync)
194178import Streamly.Internal.Data.SVar.Type (adaptState, defState)
195179
196−import qualified Prelude
197180import qualified Streamly.Internal.Data.Fold.Type as FL
198181
199182import Prelude
@@ -207,41 +190,13 @@ import Streamly.Internal.Data.Stream.StreamK.Type
207190-- $setup
208191-- >>> :m
209192
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−
222193-------------------------------------------------------------------------------
223194-- Generation
224195-------------------------------------------------------------------------------
225196
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−
235197{-# INLINE unfoldrM #-}
236−unfoldrM :: (IsStream t, MonadAsync m) => (b -> m (Maybe (a, b))) -> b -> t m a
237−unfoldrM step = go
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−
198+unfoldrM :: Monad m => (b -> m (Maybe (a, b))) -> b -> Stream m a
199+unfoldrM = unfoldrMWith consM
245200{-
246201-- Generalization of concurrent streams/SVar via unfoldr.
247202--
@@ -255,7 +210,8 @@ unfoldrM step = go
255210-- concurrent version could be async or ahead etc. Depending on how we queue
256211-- back the feedback portion b, it could be DFS or BFS style.
257212--
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
259215unfoldrA = undefined
260216-}
261217
@@ -263,110 +219,58 @@ unfoldrA = undefined
263219-- Special generation
264220-------------------------------------------------------------------------------
265221
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
272−once = fromEffect
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
222+repeatM :: Monad m => m a -> Stream m a
223+repeatM = repeatMWith consM
293224
294225{-# INLINE replicateM #-}
295−replicateM :: (IsStream t, MonadAsync m) => Int -> m a -> t m a
296−replicateM n m = go n
297− where
298− go cnt = if cnt <= 0 then nil else m |: go (cnt - 1)
299−
226+replicateM :: Monad m => Int -> m a -> Stream m a
227+replicateM = replicateMWith consM
300228{-# INLINE replicate #-}
301−replicate :: IsStream t => Int -> a -> t m a
229+replicate :: Int -> a -> Stream m a
302230replicate n a = go n
303231 where
304232 go cnt = if cnt <= 0 then nil else a `cons` go (cnt - 1)
305233
306234{-# INLINE fromIndicesM #-}
307−fromIndicesM :: (IsStream t, MonadAsync m) => (Int -> m a) -> t m a
308−fromIndicesM gen = go 0
309− where
310− go i = mkStream $ \st stp sng yld -> do
311− foldStreamShared st stp sng yld (gen i |: go (i + 1))
312−
235+fromIndicesM :: Monad m => (Int -> m a) -> Stream m a
236+fromIndicesM = fromIndicesMWith consM
313237{-# INLINE fromIndices #-}
314−fromIndices :: IsStream t => (Int -> a) -> t m a
238+fromIndices :: (Int -> a) -> Stream m a
315239fromIndices gen = go 0
316240 where
317241 go n = gen n `cons` go (n + 1)
318242
319243{-# INLINE iterate #-}
320−iterate :: IsStream t => (a -> a) -> a -> t m a
244+iterate :: (a -> a) -> a -> Stream m a
321245iterate step = go
322246 where
323247 go !s = cons s (go (step s))
324248
325249{-# INLINE iterateM #-}
326−iterateM :: (IsStream t, MonadAsync m) => (a -> m a) -> m a -> t m a
327−iterateM step = go
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))
250+iterateM :: Monad m => (a -> m a) -> m a -> Stream m a
251+iterateM = iterateMWith consM
332252
333253-------------------------------------------------------------------------------
334254-- Conversions
335255-------------------------------------------------------------------------------
336256
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−
349257{-# INLINE fromList #-}
350−fromList :: IsStream t => [a] -> t m a
258+fromList :: [a] -> Stream m a
351259fromList = fromFoldable
352260
353−{-# INLINE fromStreamK #-}
354−fromStreamK :: IsStream t => Stream m a -> t m a
355−fromStreamK = fromStream
356−
357261-------------------------------------------------------------------------------
358262-- Elimination by Folding
359263-------------------------------------------------------------------------------
360264
361265-- | Lazy right associative fold.
362266{-# 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
364268foldr step acc = foldrM (\x xs -> xs >>= \b -> return (step x b)) (return acc)
365269
366270-- | Right associative fold to an arbitrary transformer monad.
367271{-# INLINE foldrT #-}
368−foldrT :: (IsStream t, Monad m, Monad (s m), MonadTrans s)
369− => (a -> s m b -> s m b) -> s m b -> t m a -> s m b
272+foldrT :: (Monad m, Monad (s m), MonadTrans s)
273+ => (a -> s m b -> s m b) -> s m b -> Stream m a -> s m b
370274foldrT step final = go
371275 where
372276 go m1 = do
@@ -376,7 +280,7 @@ foldrT step final = go
376280 Nothing -> final
377281
378282{-# 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)
380284foldr1 step m = do
381285 r <- uncons m
382286 case r of
@@ -392,8 +296,8 @@ foldr1 step m = do
392296-- XXX replace the recursive "go" with explicit continuations.
393297-- | Like 'foldx', but with a monadic step function.
394298{-# INLINABLE foldlMx' #-}
395−foldlMx' :: (IsStream t, Monad m)
396− => (x -> a -> m x) -> m x -> (x -> m b) -> t m a -> m b
299+foldlMx' :: Monad m
300+ => (x -> a -> m x) -> m x -> (x -> m b) -> Stream m a -> m b
397301foldlMx' step begin done = go begin
398302 where
399303 go !acc m1 =
@@ -403,7 +307,7 @@ foldlMx' step begin done = go begin
403307 in foldStream defState yieldk single stop m1
404308
405309{-# 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
407311fold (FL.Fold step begin done) m = do
408312 res <- begin
409313 case res of
@@ -425,25 +329,13 @@ fold (FL.Fold step begin done) m = do
425329
426330-- | Like 'foldl'' but with a monadic step function.
427331{-# 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
429333foldlM' step begin = foldlMx' step begin return
430334
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−
443335-- | Lazy left fold to an arbitrary transformer monad.
444336{-# INLINE foldlT #-}
445−foldlT :: (IsStream t, Monad m, Monad (s m), MonadTrans s)
446− => (s m b -> a -> s m b) -> s m b -> t m a -> s m b
337+foldlT :: (Monad m, Monad (s m), MonadTrans s)
338+ => (s m b -> a -> s m b) -> s m b -> Stream m a -> s m b
447339foldlT step = go
448340 where
449341 go acc m1 = do
@@ -456,39 +348,8 @@ foldlT step = go
456348-- Specialized folds
457349------------------------------------------------------------------------------
458350
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−
490351{-# INLINE head #-}
491−head :: (IsStream t, Monad m) => t m a -> m (Maybe a)
352+head :: Monad m => Stream m a -> m (Maybe a)
492353-- head = foldrM (\x _ -> return $ Just x) (return Nothing)
493354head m =
494355 let stop = return Nothing
@@ -496,112 +357,8 @@ head m =
496357 yieldk a _ = return (Just a)
497358 in foldStream defState yieldk single stop m
498359
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−
603360{-# 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
605362elem e = go
606363 where
607364 go m1 =
@@ -611,7 +368,7 @@ elem e = go
611368 in foldStream defState yieldk single stop m1
612369
613370{-# 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
615372notElem e = go
616373 where
617374 go m1 =
@@ -621,7 +378,7 @@ notElem e = go
621378 in foldStream defState yieldk single stop m1
622379
623380{-# 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
625382all p = go
626383 where
627384 go m1 =
@@ -632,7 +389,7 @@ all p = go
632389 in foldStream defState yieldk single (return True) m1
633390
634391{-# 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
636393any p = go
637394 where
638395 go m1 =
@@ -644,11 +401,11 @@ any p = go
644401
645402-- | Extract the last element of the stream, if any.
646403{-# INLINE last #-}
647−last :: (IsStream t, Monad m) => t m a -> m (Maybe a)
404+last :: Monad m => Stream m a -> m (Maybe a)
648405last = foldlx' (\_ y -> Just y) Nothing id
649406
650407{-# 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)
652409minimum = go Nothing
653410 where
654411 go Nothing m1 =
@@ -671,8 +428,8 @@ minimum = go Nothing
671428
672429{-# INLINE minimumBy #-}
673430minimumBy
674− :: (IsStream t, Monad m)
675− => (a -> a -> Ordering) -> t m a -> m (Maybe a)
431+ :: (Monad m)
432+ => (a -> a -> Ordering) -> Stream m a -> m (Maybe a)
676433minimumBy cmp = go Nothing
677434 where
678435 go Nothing m1 =
@@ -692,7 +449,7 @@ minimumBy cmp = go Nothing
692449 in foldStream defState yieldk single stop m1
693450
694451{-# 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)
696453maximum = go Nothing
697454 where
698455 go Nothing m1 =
@@ -714,7 +471,7 @@ maximum = go Nothing
714471 in foldStream defState yieldk single stop m1
715472
716473{-# 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)
718475maximumBy cmp = go Nothing
719476 where
720477 go Nothing m1 =
@@ -734,7 +491,7 @@ maximumBy cmp = go Nothing
734491 in foldStream defState yieldk single stop m1
735492
736493{-# INLINE (!!) #-}
737−(!!) :: (IsStream t, Monad m) => t m a -> Int -> m (Maybe a)
494+(!!) :: Monad m => Stream m a -> Int -> m (Maybe a)
738495m !! i = go i m
739496 where
740497 go n m1 =
@@ -746,7 +503,7 @@ m !! i = go i m
746503 in foldStream defState yieldk single (return Nothing) m1
747504
748505{-# 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)
750507lookup e = go
751508 where
752509 go m1 =
@@ -757,7 +514,7 @@ lookup e = go
757514 in foldStream defState yieldk single (return Nothing) m1
758515
759516{-# 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)
761518findM p = go
762519 where
763520 go m1 =
@@ -770,11 +527,11 @@ findM p = go
770527 in foldStream defState yieldk single (return Nothing) m1
771528
772529{-# 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)
774531find p = findM (return . p)
775532
776533{-# INLINE findIndices #-}
777−findIndices :: IsStream t => (a -> Bool) -> t m a -> t m Int
534+findIndices :: (a -> Bool) -> Stream m a -> Stream m Int
778535findIndices p = go 0
779536 where
780537 go offset m1 = mkStream $ \st yld sng stp ->
@@ -792,7 +549,7 @@ findIndices p = go 0
792549-- | Apply a monadic action to each element of the stream and discard the
793550-- output of the action.
794551{-# 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 ()
796553mapM_ f = go
797554 where
798555 go m1 =
@@ -801,22 +558,22 @@ mapM_ f = go
801558 yieldk a r = f a >> go r
802559 in foldStream defState yieldk single stop m1
803560
561+{-# INLINE mapM #-}
562+mapM :: Monad m => (a -> m b) -> Stream m a -> Stream m b
563+mapM = mapMWith consM
564+
804565------------------------------------------------------------------------------
805566-- Converting folds
806567------------------------------------------------------------------------------
807568
808569{-# INLINABLE toList #-}
809−toList :: (IsStream t, Monad m) => t m a -> m [a]
570+toList :: Monad m => Stream m a -> m [a]
810571toList = foldr (:) []
811572
812−{-# INLINE toStreamK #-}
813−toStreamK :: Stream m a -> Stream m a
814−toStreamK = id
815−
816573-- Based on suggestions by David Feuer and Pranay Sashank
817574{-# INLINE hoist #-}
818−hoist :: (IsStream t, Monad m, Monad n)
819− => (forall x. m x -> n x) -> t m a -> t n a
575+hoist :: (Monad m, Monad n)
576+ => (forall x. m x -> n x) -> Stream m a -> Stream n a
820577hoist f str =
821578 mkStream $ \st yld sng stp ->
822579 let single = return . sng
@@ -830,7 +587,7 @@ hoist f str =
830587-------------------------------------------------------------------------------
831588
832589{-# 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
834591scanlx' step begin done m =
835592 cons (done begin) $ go m begin
836593 where
@@ -842,7 +599,7 @@ scanlx' step begin done m =
842599 in foldStream (adaptState st) yieldk single stp m1
843600
844601{-# 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
846603scanl' step begin = scanlx' step begin id
847604
848605-------------------------------------------------------------------------------
@@ -850,7 +607,7 @@ scanl' step begin = scanlx' step begin id
850607-------------------------------------------------------------------------------
851608
852609{-# INLINE filter #-}
853−filter :: IsStream t => (a -> Bool) -> t m a -> t m a
610+filter :: (a -> Bool) -> Stream m a -> Stream m a
854611filter p = go
855612 where
856613 go m1 = mkStream $ \st yld sng stp ->
@@ -861,7 +618,7 @@ filter p = go
861618 in foldStream st yieldk single stp m1
862619
863620{-# INLINE take #-}
864−take :: IsStream t => Int -> t m a -> t m a
621+take :: Int -> Stream m a -> Stream m a
865622take = go
866623 where
867624 go n1 m1 = mkStream $ \st yld sng stp ->
@@ -871,7 +628,7 @@ take = go
871628 else foldStream st yieldk sng stp m1
872629
873630{-# INLINE takeWhile #-}
874−takeWhile :: IsStream t => (a -> Bool) -> t m a -> t m a
631+takeWhile :: (a -> Bool) -> Stream m a -> Stream m a
875632takeWhile p = go
876633 where
877634 go m1 = mkStream $ \st yld sng stp ->
@@ -882,8 +639,8 @@ takeWhile p = go
882639 in foldStream st yieldk single stp m1
883640
884641{-# INLINE drop #-}
885−drop :: IsStream t => Int -> t m a -> t m a
886−drop n m = fromStream $ unShare (go n (toStream m))
642+drop :: Int -> Stream m a -> Stream m a
643+drop n m = unShare (go n m)
887644 where
888645 go n1 m1 = mkStream $ \st yld sng stp ->
889646 let single _ = stp
@@ -894,7 +651,7 @@ drop n m = fromStream $ unShare (go n (toStream m))
894651 else foldStreamShared st yieldk single stp m1
895652
896653{-# INLINE dropWhile #-}
897−dropWhile :: IsStream t => (a -> Bool) -> t m a -> t m a
654+dropWhile :: (a -> Bool) -> Stream m a -> Stream m a
898655dropWhile p = go
899656 where
900657 go m1 = mkStream $ \st yld sng stp ->
@@ -911,12 +668,12 @@ dropWhile p = go
911668-- Be careful when modifying this, this uses a consM (|:) deliberately to allow
912669-- other stream types to overload it.
913670{-# 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
915672sequence = go
916673 where
917674 go m1 = mkStream $ \st yld sng stp ->
918675 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
920677 in foldStream (adaptState st) yieldk single stp m1
921678
922679-------------------------------------------------------------------------------
@@ -924,23 +681,26 @@ sequence = go
924681-------------------------------------------------------------------------------
925682
926683{-# 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
928685intersperseM a = prependingStart
929686 where
930687 prependingStart m1 = mkStream $ \st yld sng stp ->
931− let yieldk i x = foldStreamShared st yld sng stp $ return i |: go x
688+ let yieldk i x =
689+ foldStreamShared st yld sng stp $ return i `consM` go x
932690 in foldStream st yieldk sng stp m1
933691 go m2 = mkStream $ \st yld sng stp ->
934− let single i = foldStreamShared st yld sng stp $ a |: fromPure i
935− yieldk i x = foldStreamShared st yld sng stp $ a |: return i |: go x
692+ let single i = foldStreamShared st yld sng stp $ a `consM` fromPure i
693+ yieldk i x =
694+ foldStreamShared
695+ st yld sng stp $ a `consM` return i `consM` go x
936696 in foldStream st yieldk single stp m2
937697
938698{-# 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
940700intersperse a = intersperseM (return a)
941701
942702{-# 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
944704insertBy cmp x = go
945705 where
946706 go m1 = mkStream $ \st yld _ _ ->
@@ -958,7 +718,7 @@ insertBy cmp x = go
958718------------------------------------------------------------------------------
959719
960720{-# 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
962722deleteBy eq x = go
963723 where
964724 go m1 = mkStream $ \st yld sng stp ->
@@ -968,20 +728,12 @@ deleteBy eq x = go
968728 else yld a (go r)
969729 in foldStream st yieldk single stp m1
970730
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−
979731-------------------------------------------------------------------------------
980732-- Map and Filter
981733-------------------------------------------------------------------------------
982734
983735{-# 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
985737mapMaybe f = go
986738 where
987739 go m1 = mkStream $ \st yld sng stp ->
@@ -999,7 +751,7 @@ mapMaybe f = go
999751--
1000752-- @since 0.1.0
1001753{-# 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
1003755zipWith f = go
1004756 where
1005757 go mx my = mkStream $ \st yld sng stp -> do
@@ -1015,7 +767,8 @@ zipWith f = go
1015767--
1016768-- @since 0.1.0
1017769{-# 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
1019772zipWithM f = go
1020773 where
1021774 go mx my = mkStream $ \st yld sng stp -> do
@@ -1033,9 +786,8 @@ zipWithM f = go
1033786------------------------------------------------------------------------------
1034787
1035788{-# INLINE mergeByM #-}
1036−mergeByM
1037− :: (IsStream t, Monad m)
1038− => (a -> a -> m Ordering) -> t m a -> t m a -> t m a
789+mergeByM :: Monad m =>
790+ (a -> a -> m Ordering) -> Stream m a -> Stream m a -> Stream m a
1039791mergeByM cmp = go
1040792 where
1041793 go mx my = mkStream $ \st yld sng stp -> do
@@ -1058,9 +810,8 @@ mergeByM cmp = go
1058810 foldStream st yieldX singleX stopX mx
1059811
1060812{-# INLINABLE mergeBy #-}
1061−mergeBy
1062− :: (IsStream t, Monad m)
1063− => (a -> a -> Ordering) -> t m a -> t m a -> t m a
813+mergeBy :: Monad m =>
814+ (a -> a -> Ordering) -> Stream m a -> Stream m a -> Stream m a
1064815mergeBy cmp = mergeByM (\a b -> return $ cmp a b)
1065816
1066817------------------------------------------------------------------------------
@@ -1068,7 +819,7 @@ mergeBy cmp = mergeByM (\a b -> return $ cmp a b)
1068819------------------------------------------------------------------------------
1069820
1070821{-# 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)
1072823the m = do
1073824 r <- uncons m
1074825 case r of
@@ -1091,18 +842,6 @@ _alt m1 m2 = mkStream $ \st yld sng stp ->
1091842 let stop = foldStream st yld sng stp m2
1092843 in foldStream st yld sng stop m1
1093844
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−
1106845------------------------------------------------------------------------------
1107846-- MonadError
1108847------------------------------------------------------------------------------
src/Streamly/Internal/Data/Stream/StreamK/Type.hs+479−371
@@ -17,26 +17,15 @@
1717--
1818module Streamly.Internal.Data.Stream.StreamK.Type
1919 (
20− -- * A class for streams
21− IsStream (..)
22− , adapt
23−
2420 -- * The stream type
25− , Stream (..)
21+ Stream (..)
22+ , toStreamK
23+ , fromStreamK
2624
27− -- * Construction
25+ -- * foldr/build
2826 , mkStream
29− , fromStopK
30− , fromYieldK
31− , consK
32−
33− -- * Elimination
3427 , foldStream
3528 , foldStreamShared
36− , foldl'
37− , foldlx'
38−
39− -- * foldr/build
4029 , foldrM
4130 , foldrS
4231 , foldrSShared
@@ -45,27 +34,51 @@ module Streamly.Internal.Data.Stream.StreamK.Type
4534 , buildS
4635 , buildM
4736 , buildSM
48− , sharedM
4937 , augmentS
5038 , augmentSM
5139
52− -- instances
40+ -- * Construction
41+ , fromStopK
42+ , fromYieldK
43+ , consK
5344 , cons
5445 , (.:)
55− , consMStream
46+ , consM
5647 , consMBy
48+ , nil
49+ , nilM
50+
51+ -- * Generation
5752 , fromEffect
5853 , fromPure
54+ , unfoldr
55+ , unfoldrMWith
56+ , repeat
57+ , repeatMWith
58+ , replicateMWith
59+ , fromIndicesMWith
60+ , iterateMWith
61+ , fromFoldable
62+ , fromFoldableM
63+ , mfix
5964
60− , nil
61− , nilM
65+ -- * Elimination
66+ , uncons
67+ , foldl'
68+ , foldlx'
69+ , drain
70+ , null
71+ , tail
72+ , init
73+
74+ -- * Transformation
6275 , conjoin
6376 , serial
6477 , map
65− , mapM
78+ , mapMWith
6679 , mapMSerial
6780 , unShare
68− , concatMapBy
81+ , concatMapWith
6982 , concatMap
7083 , bindWith
7184 , concatPairsWith
@@ -73,23 +86,25 @@ module Streamly.Internal.Data.Stream.StreamK.Type
7386 , apSerial
7487 , apSerialDiscardFst
7588 , apSerialDiscardSnd
89+ , foldlS
90+ , reverse
7691
77− , Streaming -- deprecated
92+ -- * Reader
93+ , withLocal
7894 )
7995where
8096
8197import Control.Monad (ap, (>=>))
98+import Control.Monad.Reader.Class (MonadReader(..))
8299import Control.Monad.Trans.Class (MonadTrans(lift))
83−import Data.Kind (Type)
84−#if __GLASGOW_HASKELL__ < 808
100+import Data.Function (fix)
101+#if __GLASGOW_HASKELL__ < 804
85102import Data.Semigroup (Semigroup(..))
86103#endif
87−import Streamly.Internal.Control.Concurrent (MonadAsync)
88104import Streamly.Internal.Data.SVar.Type (State, adaptState, defState)
89−import Prelude hiding (map, mapM, concatMap, foldr)
90−
91−-- $setup
92−-- >>> import Streamly.Prelude as Stream
105+import Prelude hiding
106+ (map, mapM, concatMap, foldr, repeat, null, reverse, tail, init)
107+import qualified Prelude
93108
94109------------------------------------------------------------------------------
95110-- Basic stream type
@@ -124,140 +139,22 @@ newtype Stream m a =
124139 -> m r
125140 )
126141
127−------------------------------------------------------------------------------
128−-- Types that can behave as a Stream
129−------------------------------------------------------------------------------
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−------------------------------------------------------------------------------
142+{-# INLINE fromStreamK #-}
143+fromStreamK :: Stream m a -> Stream m a
144+fromStreamK = id
217145
218−-- XXX The State is always parameterized by "Stream" which means State is not
219−-- different for different stream types. So we have to manually make sure that
220−-- when converting from one stream to another we migrate the state correctly.
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
146+{-# INLINE toStreamK #-}
147+toStreamK :: Stream m a -> Stream m a
148+toStreamK = id
251149
252−{-# RULES "mkStream stream" mkStream = mkStreamStream #-}
253−mkStreamStream
150+mkStream
254151 :: (forall r. State Stream m a
255152 -> (a -> Stream m a -> m r)
256153 -> (a -> m r)
257154 -> m r
258155 -> m r)
259156 -> Stream m a
260−mkStreamStream = MkStream
157+mkStream = MkStream
261158
262159-- | A terminal function that has no continuation to follow.
263160type StopK m = forall r. m r -> m r
@@ -272,17 +169,17 @@ _wrapM :: Monad m => m a -> YieldK m a
272169_wrapM m = (m >>=)
273170
274171-- | Make an empty stream from a stop function.
275−fromStopK :: IsStream t => StopK m -> t m a
172+fromStopK :: StopK m -> Stream m a
276173fromStopK k = mkStream $ \_ _ _ stp -> k stp
277174
278175-- | Make a singleton stream from a callback function. The callback function
279176-- 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
281178fromYieldK k = mkStream $ \_ _ sng _ -> k sng
282179
283180-- | Add a yield function at the head of the stream.
284−consK :: IsStream t => YieldK m a -> t m a -> t m a
285−consK k r = mkStream $ \_ yld _ _ -> k (`yld` r)
181+consK :: YieldK m a -> Stream m a -> Stream m a
182+consK k r = mkStream $ \_ yld _ _ -> k (\x -> yld x r)
286183
287184-- XXX Build a stream from a repeating callback function.
288185
@@ -305,8 +202,8 @@ infixr 5 `cons`
305202--
306203-- @since 0.1.0
307204{-# INLINE_NORMAL cons #-}
308−cons :: IsStream t => a -> t m a -> t m a
309−cons a r = mkStream $ \_ yld _ _ -> yld a r
205+cons :: a -> Stream m a -> Stream m a
206+cons a r = mkStream $ \_ yield _ _ -> yield a r
310207
311208infixr 5 .:
312209
@@ -319,7 +216,7 @@ infixr 5 .:
319216--
320217-- @since 0.1.1
321218{-# INLINE (.:) #-}
322−(.:) :: IsStream t => a -> t m a -> t m a
219+(.:) :: a -> Stream m a -> Stream m a
323220(.:) = cons
324221
325222-- | An empty stream.
@@ -331,7 +228,7 @@ infixr 5 .:
331228--
332229-- @since 0.1.0
333230{-# INLINE_NORMAL nil #-}
334−nil :: IsStream t => t m a
231+nil :: Stream m a
335232nil = mkStream $ \_ _ _ stp -> stp
336233
337234-- | An empty stream producing a side effect.
@@ -344,22 +241,32 @@ nil = mkStream $ \_ _ _ stp -> stp
344241--
345242-- /Pre-release/
346243{-# INLINE_NORMAL nilM #-}
347−nilM :: (IsStream t, Monad m) => m b -> t m a
244+nilM :: Monad m => m b -> Stream m a
348245nilM m = mkStream $ \_ _ _ stp -> m >> stp
349246
350247{-# INLINE_NORMAL fromPure #-}
351−fromPure :: IsStream t => a -> t m a
248+fromPure :: a -> Stream m a
352249fromPure a = mkStream $ \_ _ single _ -> single a
353250
354251{-# INLINE_NORMAL fromEffect #-}
355−fromEffect :: (Monad m, IsStream t) => m a -> t m a
356−fromEffect m = fromStream $ mkStream $ \_ _ single _ -> m >>= single
252+fromEffect :: Monad m => m a -> Stream m a
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
357264
358265-- XXX specialize to IO?
359266{-# INLINE consMBy #-}
360−consMBy :: (IsStream t, MonadAsync m) => (t m a -> t m a -> t m a)
361− -> m a -> t m a -> t m a
362−consMBy f m r = fromStream (fromEffect m) `f` r
267+consMBy :: Monad m =>
268+ (Stream m a -> Stream m a -> Stream m a) -> m a -> Stream m a -> Stream m a
269+consMBy f m r = fromEffect m `f` r
363270
364271------------------------------------------------------------------------------
365272-- Folding a stream
@@ -370,78 +277,27 @@ consMBy f m r = fromStream (fromEffect m) `f` r
370277-- SVar passed via the State.
371278{-# INLINE_EARLY foldStreamShared #-}
372279foldStreamShared
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
389280 :: State Stream m a
390281 -> (a -> Stream m a -> m r)
391282 -> (a -> m r)
392283 -> m r
393284 -> Stream m a
394285 -> m r
395−foldStreamSharedStream st yld sng stp m =
396− let MkStream k = toStream m
397− in k st yld sng stp
286+foldStreamShared s yield single stop (MkStream k) = k s yield single stop
398287
399288-- | Fold a stream by providing a State, stop continuation, a singleton
400289-- continuation and a yield continuation. The stream will not use the SVar
401290-- passed via State.
402291{-# INLINE foldStream #-}
403292foldStream
404− :: IsStream t
405− => State Stream m a
406− -> (a -> t m a -> m r)
293+ :: State Stream m a
294+ -> (a -> Stream m a -> m r)
407295 -> (a -> m r)
408296 -> m r
409− -> t m a
297+ -> Stream m a
410298 -> m r
411−foldStream st yld sng stp m =
412− let yieldk a x = yld a (fromStream x)
413− MkStream k = toStream m
414− in k (adaptState st) yieldk sng stp
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
299+foldStream s yield single stop (MkStream k) =
300+ k (adaptState s) yield single stop
445301
446302-------------------------------------------------------------------------------
447303-- foldr/build fusion
@@ -454,15 +310,18 @@ instance IsStream Stream where
454310-- reconstruct using a shared state (SVar) or without sharing the state.
455311--
456312{-# INLINE foldrSWith #-}
457−foldrSWith :: IsStream t
458− => (forall r. State Stream m b
459− -> (b -> t m b -> m r)
313+foldrSWith ::
314+ (forall r. State Stream m b
315+ -> (b -> Stream m b -> m r)
460316 -> (b -> m r)
461317 -> m r
462− -> t m b
318+ -> Stream m b
463319 -> m r)
464− -> (a -> t m b -> t m b) -> t m b -> t m a -> t m b
465−foldrSWith f step final = go
320+ -> (a -> Stream m b -> Stream m b)
321+ -> Stream m b
322+ -> Stream m a
323+ -> Stream m b
324+foldrSWith f step final m = go m
466325 where
467326 go m1 = mkStream $ \st yld sng stp ->
468327 let run x = f st yld sng stp x
@@ -480,7 +339,11 @@ foldrSWith f step final = go
480339
481340-- | Fold sharing the SVar state within the reconstructed stream
482341{-# 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
484347foldrSShared = foldrSWith foldStreamShared
485348
486349-- XXX consM is a typeclass method, therefore rewritten already. Instead maybe
@@ -495,7 +358,11 @@ foldrSShared = foldrSWith foldStreamShared
495358
496359-- | Lazy right associative fold to a stream.
497360{-# 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
499366foldrS = foldrSWith foldStream
500367
501368{-# RULES "foldrS/id" foldrS cons nil = \x -> x #-}
@@ -512,15 +379,18 @@ foldrS = foldrSWith foldStream
512379-------------------------------------------------------------------------------
513380
514381{-# INLINE foldrSMWith #-}
515−foldrSMWith :: (IsStream t, Monad m)
382+foldrSMWith :: Monad m
516383 => (forall r. State Stream m b
517− -> (b -> t m b -> m r)
384+ -> (b -> Stream m b -> m r)
518385 -> (b -> m r)
519386 -> m r
520− -> t m b
387+ -> Stream m b
521388 -> m r)
522− -> (m a -> t m b -> t m b) -> t m b -> t m a -> t m b
523−foldrSMWith f step final = go
389+ -> (m a -> Stream m b -> Stream m b)
390+ -> Stream m b
391+ -> Stream m a
392+ -> Stream m b
393+foldrSMWith f step final m = go m
524394 where
525395 go m1 = mkStream $ \st yld sng stp ->
526396 let run x = f st yld sng stp x
@@ -530,8 +400,11 @@ foldrSMWith f step final = go
530400 in foldStream (adaptState st) yieldk single stop m1
531401
532402{-# INLINE_NORMAL foldrSM #-}
533−foldrSM :: (IsStream t, Monad m)
534− => (m a -> t m b -> t m b) -> t m b -> t m a -> t m b
403+foldrSM :: Monad m
404+ => (m a -> Stream m b -> Stream m b)
405+ -> Stream m b
406+ -> Stream m a
407+ -> Stream m b
535408foldrSM = foldrSMWith foldStream
536409
537410-- {-# RULES "foldrSM/id" foldrSM consM nil = \x -> x #-}
@@ -542,8 +415,11 @@ foldrSM = foldrSMWith foldStream
542415
543416-- Like foldrSM but sharing the SVar state within the recostructed stream.
544417{-# INLINE_NORMAL foldrSMShared #-}
545−foldrSMShared :: (IsStream t, Monad m)
546− => (m a -> t m b -> t m b) -> t m b -> t m a -> t m b
418+foldrSMShared :: Monad m
419+ => (m a -> Stream m b -> Stream m b)
420+ -> Stream m b
421+ -> Stream m a
422+ -> Stream m b
547423foldrSMShared = foldrSMWith foldStreamShared
548424
549425-- {-# RULES "foldrSM/id" foldrSM consM nil = \x -> x #-}
@@ -559,7 +435,7 @@ foldrSMShared = foldrSMWith foldStreamShared
559435-------------------------------------------------------------------------------
560436
561437{-# 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
563439build g = g cons nil
564440
565441{-# RULES "foldrM/build"
@@ -584,37 +460,46 @@ build g = g cons nil
584460
585461-- build a stream by applying cons and nil to a build function
586462{-# 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
588466buildS g = g cons nil
589467
590468{-# 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).
592471 foldrS k z (buildS g) = g k z #-}
593472
594473{-# 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).
596476 foldrS k z (x `cons` buildS g) = k x (g k z) #-}
597477
598478{-# 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).
600481 foldrSShared k z (buildS g) = g k z #-}
601482
602483{-# 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).
604486 foldrSShared k z (x `cons` buildS g) = k x (g k z) #-}
605487
606488-- build a stream by applying consM and nil to a build function
607489{-# INLINE_NORMAL buildSM #-}
608−buildSM :: (IsStream t, MonadAsync m)
609− => ((m a -> t m a -> t m a) -> t m a -> t m a) -> t m a
490+buildSM :: Monad m
491+ => ((m a -> Stream m a -> Stream m a) -> Stream m a -> Stream m a)
492+ -> Stream m a
610493buildSM g = g consM nil
611494
612495{-# 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).
614498 foldrSM k z (buildSM g) = g k z #-}
615499
616500{-# 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).
618503 foldrSMShared k z (buildSM g) = g k z #-}
619504
620505-- Disabled because this may not fire as consM is a class Op
@@ -629,71 +514,79 @@ buildSM g = g consM nil
629514-- Build using monadic build functions (continuations) instead of
630515-- reconstructing a stream.
631516{-# INLINE_NORMAL buildM #-}
632−buildM :: (IsStream t, MonadAsync m)
633− => (forall r. (a -> t m a -> m r)
517+buildM :: Monad m
518+ => (forall r. (a -> Stream m a -> m r)
634519 -> (a -> m r)
635520 -> m r
636521 -> m r
637522 )
638− -> t m a
523+ -> Stream m a
639524buildM g = mkStream $ \st yld sng stp ->
640525 g (\a r -> foldStream st yld sng stp (return a `consM` r)) sng stp
641526
642527-- | Like 'buildM' but shares the SVar state across computations.
643−{-# INLINE_NORMAL sharedM #-}
644−sharedM :: (IsStream t, MonadAsync m)
645− => (forall r. (a -> t m a -> m r)
528+{-# INLINE_NORMAL sharedMWith #-}
529+sharedMWith :: Monad m
530+ => (m a -> Stream m a -> Stream m a)
531+ -> (forall r. (a -> Stream m a -> m r)
646532 -> (a -> m r)
647533 -> m r
648534 -> m r
649535 )
650− -> t m a
651−sharedM g = mkStream $ \st yld sng stp ->
652− g (\a r -> foldStreamShared st yld sng stp (return a `consM` r)) sng stp
536+ -> Stream m a
537+sharedMWith cns g = mkStream $ \st yld sng stp ->
538+ g (\a r -> foldStreamShared st yld sng stp (return a `cns` r)) sng stp
653539
654540-------------------------------------------------------------------------------
655541-- augment
656542-------------------------------------------------------------------------------
657543
658544{-# INLINE_NORMAL augmentS #-}
659−augmentS :: IsStream t
660− => ((a -> t m a -> t m a) -> t m a -> t m a) -> t m a -> t m a
661−augmentS g = g cons
545+augmentS ::
546+ ((a -> Stream m a -> Stream m a) -> Stream m a -> Stream m a)
547+ -> Stream m a
548+ -> Stream m a
549+augmentS g xs = g cons xs
662550
663551{-# 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).
665553 augmentS g nil = buildS g
666554 #-}
667555
668556{-# 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).
670559 foldrS k z (augmentS g xs) = g k (foldrS k z xs)
671560 #-}
672561
673562{-# RULES "augmentS/buildS"
674− forall (g :: (a -> t m a -> t m a) -> t m a -> t m a)
675− (h :: (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)
564+ (h :: (a -> Stream m a -> Stream m a) -> Stream m a -> Stream m a).
676565 augmentS g (buildS h) = buildS (\c n -> g c (h c n))
677566 #-}
678567
679568{-# INLINE_NORMAL augmentSM #-}
680−augmentSM :: (IsStream t, MonadAsync m)
681− => ((m a -> t m a -> t m a) -> t m a -> t m a) -> t m a -> t m a
682−augmentSM g = g consM
569+augmentSM :: Monad m =>
570+ ((m a -> Stream m a -> Stream m a) -> Stream m a -> Stream m a)
571+ -> Stream m a -> Stream m a
572+augmentSM g xs = g consM xs
683573
684574{-# 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).
686577 augmentSM g nil = buildSM g
687578 #-}
688579
689580{-# 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).
691583 foldrSM k z (augmentSM g xs) = g k (foldrSM k z xs)
692584 #-}
693585
694586{-# RULES "augmentSM/buildSM"
695− forall (g :: (m a -> t m a -> t m a) -> t m a -> t m a)
696− (h :: (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)
589+ (h :: (m a -> Stream m a -> Stream m a) -> Stream m a -> Stream m a).
697590 augmentSM g (buildSM h) = buildSM (\c n -> g c (h c n))
698591 #-}
699592
@@ -703,8 +596,8 @@ augmentSM g = g consM
703596
704597-- | Lazy right fold with a monadic step function.
705598{-# INLINE_NORMAL foldrM #-}
706−foldrM :: IsStream t => (a -> m b -> m b) -> m b -> t m a -> m b
707−foldrM step acc = go
599+foldrM :: (a -> m b -> m b) -> m b -> Stream m a -> m b
600+foldrM step acc m = go m
708601 where
709602 go m1 =
710603 let stop = acc
@@ -715,14 +608,14 @@ foldrM step acc = go
715608{-# INLINE_NORMAL foldrMKWith #-}
716609foldrMKWith
717610 :: (State Stream m a
718− -> (a -> t m a -> m b)
611+ -> (a -> Stream m a -> m b)
719612 -> (a -> m b)
720613 -> m b
721− -> t m a
614+ -> Stream m a
722615 -> m b)
723616 -> (a -> m b -> m b)
724617 -> 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)
726619 -> m b
727620foldrMKWith f step acc = go
728621 where
@@ -742,7 +635,7 @@ foldrMKWith f step acc = go
742635-- XXX in which case will foldrM/buildM fusion be useful?
743636{-# RULES "foldrM/buildM"
744637 forall step acc (g :: (forall r.
745− (a -> t m a -> m r)
638+ (a -> Stream m a -> m r)
746639 -> (a -> m r)
747640 -> m r
748641 -> m r
@@ -750,15 +643,17 @@ foldrMKWith f step acc = go
750643 foldrM step acc (buildM g) = foldrMKWith foldStream step acc g
751644 #-}
752645
646+{-
753647{-# RULES "foldrM/sharedM"
754648 forall step acc (g :: (forall r.
755− (a -> t m a -> m r)
649+ (a -> Stream m a -> m r)
756650 -> (a -> m r)
757651 -> m r
758652 -> m r
759653 )).
760654 foldrM step acc (sharedM g) = foldrMKWith foldStreamShared step acc g
761655 #-}
656+-}
762657
763658------------------------------------------------------------------------------
764659-- Left fold
@@ -771,12 +666,12 @@ foldrMKWith f step acc = go
771666--
772667-- Note that the accumulator is always evaluated including the initial value.
773668{-# INLINE foldlx' #-}
774−foldlx' :: forall t m a b x. (IsStream t, Monad m)
775− => (x -> a -> x) -> x -> (x -> b) -> t m a -> m b
669+foldlx' :: forall m a b x. Monad m
670+ => (x -> a -> x) -> x -> (x -> b) -> Stream m a -> m b
776671foldlx' step begin done m = get $ go m begin
777672 where
778673 {-# NOINLINE get #-}
779− get :: t m x -> m b
674+ get :: Stream m x -> m b
780675 get m1 =
781676 -- XXX we are not strictly evaluating the accumulator here. Is this
782677 -- okay?
@@ -788,7 +683,7 @@ foldlx' step begin done m = get $ go m begin
788683 -- however that is more expensive because of unnecessary recursion
789684 -- that cannot be tail call optimized. Unfolding recursion explicitly via
790685 -- continuations is much more efficient.
791− go :: t m a -> x -> t m x
686+ go :: Stream m a -> x -> Stream m x
792687 go m1 !acc = mkStream $ \_ yld sng _ ->
793688 let stop = sng acc
794689 single a = sng $ step acc a
@@ -799,9 +694,44 @@ foldlx' step begin done m = get $ go m begin
799694
800695-- | Strict left associative fold.
801696{-# 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
803698foldl' step begin = foldlx' step begin id
804699
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+
805735------------------------------------------------------------------------------
806736-- Semigroup
807737------------------------------------------------------------------------------
@@ -811,19 +741,8 @@ infixr 6 `serial`
811741-- | Appends two streams sequentially, yielding all elements from the first
812742-- stream, and then all elements from the second stream.
813743--
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
825744{-# 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
827746-- XXX This doubles the time of toNullAp benchmark, may not be fusing properly
828747-- serial xs ys = augmentS (\c n -> foldrS c n xs) ys
829748serial m1 m2 = go m1
@@ -836,7 +755,7 @@ serial m1 m2 = go m1
836755
837756-- join/merge/append streams depending on consM
838757{-# 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
840759conjoin xs = augmentSM (\c n -> foldrSM c n xs)
841760
842761instance Semigroup (Stream m a) where
@@ -856,10 +775,13 @@ instance Monoid (Stream m a) where
856775
857776-- Note eta expanded
858777{-# INLINE_LATE mapFB #-}
859−mapFB :: forall (t :: (Type -> Type) -> Type -> Type) b m a.
860− (b -> t m b -> t m b) -> (a -> b) -> a -> t m b -> t m b
861−mapFB c f x ys = c (f x) ys
862−#undef Type
778+mapFB :: forall b m a.
779+ (b -> Stream m b -> Stream m b)
780+ -> (a -> b)
781+ -> a
782+ -> Stream m b
783+ -> Stream m b
784+mapFB c f = \x ys -> c (f x) ys
863785
864786{-# RULES
865787"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
867789 #-}
868790
869791{-# INLINE map #-}
870−map :: IsStream t => (a -> b) -> t m a -> t m b
792+map :: (a -> b) -> Stream m a -> Stream m b
871793map f xs = buildS (\c n -> foldrS (mapFB c f) n xs)
872794
873795-- XXX This definition might potentially be more efficient, but the cost in the
@@ -898,21 +820,6 @@ mapMFB c f x = c (x >>= f)
898820"mapMFB/return" forall c. mapMFB c (\x -> return x) = c
899821-}
900822
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−
916823-- This is experimental serial version supporting fusion.
917824--
918825-- XXX what if we do not want to fuse two concurrent mapMs?
@@ -921,9 +828,27 @@ mapM f m = go m
921828-- XXX fusion would be easier for monomoprhic stream types.
922829-- {-# RULES "mapM serial" mapM = mapMSerial #-}
923830{-# 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
925832mapMSerial f xs = buildSM (\c n -> foldrSMShared (mapMFB c f) n xs)
926833
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+
927852-- XXX in fact use the Stream type everywhere and only use polymorphism in the
928853-- high level modules/prelude.
929854instance Monad m => Functor (Stream m) where
@@ -943,18 +868,17 @@ instance MonadTrans Stream where
943868
944869-- | Detach a stream from an SVar
945870{-# INLINE unShare #-}
946−unShare :: IsStream t => t m a -> t m a
871+unShare :: Stream m a -> Stream m a
947872unShare x = mkStream $ \st yld sng stp ->
948873 foldStream st yld sng stp x
949874
950875-- XXX the function stream and value stream can run in parallel
951876{-# INLINE apWith #-}
952−apWith
953− :: IsStream t
954− => (t m b -> t m b -> t m b)
955− -> t m (a -> b)
956− -> t m a
957− -> t m b
877+apWith ::
878+ (Stream m b -> Stream m b -> Stream m b)
879+ -> Stream m (a -> b)
880+ -> Stream m a
881+ -> Stream m b
958882apWith par fstream stream = go1 fstream
959883
960884 where
@@ -973,11 +897,10 @@ apWith par fstream stream = go1 fstream
973897 in foldStream (adaptState st) yieldk single stp m
974898
975899{-# INLINE apSerial #-}
976−apSerial
977− :: IsStream t
978− => t m (a -> b)
979− -> t m a
980− -> t m b
900+apSerial ::
901+ Stream m (a -> b)
902+ -> Stream m a
903+ -> Stream m b
981904apSerial fstream stream = go1 fstream
982905
983906 where
@@ -1004,11 +927,10 @@ apSerial fstream stream = go1 fstream
1004927 in foldStream (adaptState st) yieldk single stp m
1005928
1006929{-# INLINE apSerialDiscardFst #-}
1007−apSerialDiscardFst
1008− :: IsStream t
1009− => t m a
1010− -> t m b
1011− -> t m b
930+apSerialDiscardFst ::
931+ Stream m a
932+ -> Stream m b
933+ -> Stream m b
1012934apSerialDiscardFst fstream stream = go1 fstream
1013935
1014936 where
@@ -1029,11 +951,10 @@ apSerialDiscardFst fstream stream = go1 fstream
1029951 in foldStream st yieldk single stop m
1030952
1031953{-# INLINE apSerialDiscardSnd #-}
1032−apSerialDiscardSnd
1033− :: IsStream t
1034− => t m a
1035− -> t m b
1036− -> t m a
954+apSerialDiscardSnd ::
955+ Stream m a
956+ -> Stream m b
957+ -> Stream m a
1037958apSerialDiscardSnd fstream stream = go1 fstream
1038959
1039960 where
@@ -1059,17 +980,16 @@ apSerialDiscardSnd fstream stream = go1 fstream
1059980 yieldk _ r = yld f (go3 f r)
1060981 in foldStream (adaptState st) yieldk single stp m
1061982
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
1063984-- instead of using a concatMap style definition because the bind
1064985-- implementation in Async and WAsync streams show significant perf degradation
1065986-- if the argument order is changed.
1066987{-# INLINE bindWith #-}
1067−bindWith
1068− :: IsStream t
1069− => (t m b -> t m b -> t m b)
1070− -> t m a
1071− -> (a -> t m b)
1072− -> t m b
988+bindWith ::
989+ (Stream m b -> Stream m b -> Stream m b)
990+ -> Stream m a
991+ -> (a -> Stream m b)
992+ -> Stream m b
1073993bindWith par m1 f = go m1
1074994 where
1075995 go m =
@@ -1094,21 +1014,18 @@ bindWith par m1 f = go m1
10941014-- function.
10951015--
10961016-- @since 0.7.0
1097−{-# INLINE concatMapBy #-}
1098−concatMapBy
1099− :: IsStream t
1100− => (t m b -> t m b -> t m b)
1101− -> (a -> t m b)
1102− -> t m a
1103− -> t m b
1104−concatMapBy par f xs = bindWith par xs f
1017+{-# INLINE concatMapWith #-}
1018+concatMapWith
1019+ ::
1020+ (Stream m b -> Stream m b -> Stream m b)
1021+ -> (a -> Stream m b)
1022+ -> Stream m a
1023+ -> Stream m b
1024+concatMapWith par f xs = bindWith par xs f
11051025
11061026{-# INLINE concatMap #-}
1107−concatMap :: IsStream t => (a -> t m b) -> t m a -> t m b
1108−concatMap f m = fromStream $
1109− concatMapBy serial
1110− (adapt . toStream . f)
1111− (adapt $ toStream m)
1027+concatMap :: (a -> Stream m b) -> Stream m a -> Stream m b
1028+concatMap = concatMapWith serial
11121029
11131030{-
11141031-- Fused version.
@@ -1133,11 +1050,11 @@ concatMap_ f xs = buildS
11331050--
11341051{-# INLINE concatPairsWith #-}
11351052concatPairsWith
1136− :: IsStream t
1137− => (t m b -> t m b -> t m b)
1138− -> (a -> t m b)
1139− -> t m a
1140− -> t m b
1053+ ::
1054+ (Stream m b -> Stream m b -> Stream m b)
1055+ -> (a -> Stream m b)
1056+ -> Stream m a
1057+ -> Stream m b
11411058concatPairsWith combine f = go Nothing
11421059
11431060 where
@@ -1195,3 +1112,194 @@ concatUnfoldr :: IsStream t
11951112 => (b -> t m (Maybe (a, b))) -> t m b -> t m a
11961113concatUnfoldr = undefined
11971114-}
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 @@
1515--
1616module Streamly.Internal.Data.Stream.Zip
1717 (
18− ZipSerialM
18+ ZipSerialM (..)
1919 , ZipSerial
20− , fromZipSerial
20+ , consMZip
21+ , zipWithK
22+ , zipWithMK
2123
22− , ZipAsyncM
24+ , ZipAsyncM(..)
2325 , ZipAsync
24− , fromZipAsync
25−
26− , zipWith
27− , zipWithM
28− , zipAsyncWith
29− , zipAsyncWithM
26+ , consMZipAsync
27+ , zipAsyncWithK
28+ , zipAsyncWithMK
3029
3130 -- * Deprecated
3231 , ZipStream
33− , zipping
34− , zippingAsync
3532 )
3633where
3734
@@ -51,23 +48,18 @@ import GHC.Exts (IsList(..), IsString(..))
5148import Text.Read
5249 ( Lexeme(Ident), lexP, parens, prec, readPrec, readListPrec
5350 , readListPrecDefault)
54−import Streamly.Internal.Control.Concurrent (MonadAsync)
5551import Streamly.Internal.BaseCompat ((#.), errorWithoutStackTrace, oneShot)
56−import Streamly.Internal.Data.Stream.StreamK (IsStream(..), Stream)
52+import Streamly.Internal.Control.Concurrent (MonadAsync)
5753import Streamly.Internal.Data.Maybe.Strict (Maybe'(..), toMaybe)
54+import Streamly.Internal.Data.Stream.Serial (SerialT(..))
55+import Streamly.Internal.Data.Stream.StreamK.Type (Stream)
5856
5957import qualified Streamly.Internal.Data.Stream.Parallel as Par
6058import qualified Streamly.Internal.Data.Stream.Prelude as P
61− (cmpBy, eqBy, foldl', foldr, fromList, toList, fromStreamS, toStreamS)
62−import qualified Streamly.Internal.Data.Stream.StreamK as K (repeat)
59+ (cmpBy, eqBy, foldl', foldr, fromList, toList)
6360import qualified Streamly.Internal.Data.Stream.StreamK.Type as K
64−import qualified Streamly.Internal.Data.Stream.StreamD as D (zipWithM)
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)
68−#else
69−import qualified Streamly.Internal.Data.Stream.StreamD as S (zipWith, zipWithM)
70−#endif
61+import qualified Streamly.Internal.Data.Stream.StreamD as D
62+import qualified Streamly.Internal.Data.Stream.Serial as Serial
7163
7264import Prelude hiding (map, repeat, zipWith, errorWithoutStackTrace)
7365
@@ -83,29 +75,16 @@ import Prelude hiding (map, repeat, zipWith, errorWithoutStackTrace)
8375-- return n -- IO Int
8476-- :}
8577
86−-- | Like 'zipWith' but using a monadic zipping function.
87−--
88−-- @since 0.4.0
89−{-# INLINABLE zipWithM #-}
90−zipWithM :: (IsStream t, Monad m) => (a -> b -> m c) -> t m a -> t m b -> t m c
91−zipWithM f m1 m2 = P.fromStreamS $ S.zipWithM f (P.toStreamS m1) (P.toStreamS m2)
78+{-# INLINE zipWithMK #-}
79+zipWithMK :: Monad m =>
80+ (a -> b -> m c) -> Stream m a -> Stream m b -> Stream m c
81+zipWithMK f m1 m2 =
82+ D.toStreamK $ D.zipWithM f (D.fromStreamK m1) (D.fromStreamK m2)
9283
93−-- | Stream @a@ is evaluated first, followed by stream @b@, the resulting
94−-- elements @a@ and @b@ are then zipped using the supplied zip function and the
95−-- result @c@ is yielded to the consumer.
96−--
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)
84+{-# INLINE zipWithK #-}
85+zipWithK :: Monad m
86+ => (a -> b -> c) -> Stream m a -> Stream m b -> Stream m c
87+zipWithK f = zipWithMK (\a b -> return (f a b))
10988
11089------------------------------------------------------------------------------
11190-- Parallel Zipping
@@ -114,12 +93,12 @@ zipWith f m1 m2 = P.fromStreamS $ S.zipWith f (P.toStreamS m1) (P.toStreamS m2)
11493-- | Like 'zipAsyncWith' but with a monadic zipping function.
11594--
11695-- @since 0.4.0
117−{-# INLINE zipAsyncWithM #-}
118−zipAsyncWithM :: (IsStream t, MonadAsync m)
119− => (a -> b -> m c) -> t m a -> t m b -> t m c
120−zipAsyncWithM f m1 m2 = D.fromStreamD $
121− D.zipWithM f (Par.mkParallelD $ D.toStreamD m1)
122− (Par.mkParallelD $ D.toStreamD m2)
96+{-# INLINE zipAsyncWithMK #-}
97+zipAsyncWithMK :: MonadAsync m
98+ => (a -> b -> m c) -> Stream m a -> Stream m b -> Stream m c
99+zipAsyncWithMK f m1 m2 = D.toStreamK $
100+ D.zipWithM f (Par.mkParallelD $ D.fromStreamK m1)
101+ (Par.mkParallelD $ D.fromStreamK m2)
123102
124103-- XXX Should we rename this to zipParWith or zipParallelWith? This can happen
125104-- along with the change of behvaior to end the stream concurrently.
@@ -136,10 +115,10 @@ zipAsyncWithM f m1 m2 = D.fromStreamD $
136115-- as soon as any of the stream end is detected.
137116--
138117-- @since 0.1.0
139−{-# INLINE zipAsyncWith #-}
140−zipAsyncWith :: (IsStream t, MonadAsync m)
141− => (a -> b -> c) -> t m a -> t m b -> t m c
142−zipAsyncWith f = zipAsyncWithM (\a b -> return (f a b))
118+{-# INLINE zipAsyncWithK #-}
119+zipAsyncWithK :: MonadAsync m
120+ => (a -> b -> c) -> Stream m a -> Stream m b -> Stream m c
121+zipAsyncWithK f = zipAsyncWithMK (\a b -> return (f a b))
143122
144123------------------------------------------------------------------------------
145124-- Serially Zipping Streams
@@ -178,49 +157,21 @@ type ZipStream = ZipSerialM
178157-- @since 0.8.0
179158type ZipSerial = ZipSerialM IO
180159
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−
196160consMZip :: Monad m => m a -> ZipSerialM m a -> ZipSerialM m a
197−consMZip m ms = fromStream $ K.consMStream m (toStream ms)
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
161+consMZip m (ZipSerialM r) = ZipSerialM $ K.consM m r
212162
213163LIST_INSTANCES(ZipSerialM)
214164NFDATA1_INSTANCE(ZipSerialM)
215165
216166instance Monad m => Functor (ZipSerialM m) where
217167 {-# 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)
219169
220170instance Monad m => Applicative (ZipSerialM m) where
221− pure = ZipSerialM . K.repeat
171+ pure = ZipSerialM . getSerialT . Serial.repeat
172+
222173 {-# INLINE (<*>) #-}
223− (<*>) = zipWith id
174+ ZipSerialM m1 <*> ZipSerialM m2 = ZipSerialM $ zipWithK id m1 m2
224175
225176FOLDABLE_INSTANCE(ZipSerialM)
226177TRAVERSABLE_INSTANCE(ZipSerialM)
@@ -257,43 +208,15 @@ newtype ZipAsyncM m a = ZipAsyncM {getZipAsyncM :: Stream m a}
257208-- @since 0.8.0
258209type ZipAsync = ZipAsyncM IO
259210
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−
275211consMZipAsync :: Monad m => m a -> ZipAsyncM m a -> ZipAsyncM m a
276−consMZipAsync m ms = fromStream $ K.consMStream m (toStream ms)
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
212+consMZipAsync m (ZipAsyncM r) = ZipAsyncM $ K.consM m r
291213
292214instance Monad m => Functor (ZipAsyncM m) where
293215 {-# 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)
295217
296218instance MonadAsync m => Applicative (ZipAsyncM m) where
297− pure = ZipAsyncM . K.repeat
219+ pure = ZipAsyncM . getSerialT . Serial.repeat
220+
298221 {-# 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)
255255import Streamly.Internal.Data.Fold.Type (Fold(..))
256256import Streamly.Internal.Data.IOFinalizer
257257 (newIOFinalizer, runIOFinalizer, clearingIOFinalizer)
258+import Streamly.Internal.Data.Stream.IsStream.Type (IsStream)
258259import Streamly.Internal.Data.Stream.StreamD.Type (Stream(..), Step(..))
259260import Streamly.Internal.Data.SVar.Type (defState)
260261
261262import qualified Control.Monad.Catch as MC
262263import qualified Data.Tuple as Tuple
263264import qualified Streamly.Internal.Data.Fold.Type as FL
265+import qualified Streamly.Internal.Data.Stream.IsStream.Type as IsStream
264266import qualified Streamly.Internal.Data.Stream.StreamD.Type as D
265−import qualified Streamly.Internal.Data.Stream.StreamK as K (uncons)
266267import qualified Streamly.Internal.Data.Stream.StreamK.Type as K
267268
268269import Streamly.Internal.Data.Unfold.Enumeration
@@ -485,8 +486,8 @@ fromStreamK = Unfold step return
485486-- /Since: 0.8.0/
486487--
487488{-# INLINE_NORMAL fromStream #-}
488−fromStream :: (K.IsStream t, Monad m) => Unfold m (t m a) a
489−fromStream = lmap K.toStream fromStreamK
489+fromStream :: (IsStream t, Monad m) => Unfold m (t m a) a
490+fromStream = lmap IsStream.toStream fromStreamK
490491
491492-------------------------------------------------------------------------------
492493-- Unfolds
src/Streamly/Internal/FileSystem/Dir.hs+1−1
@@ -68,7 +68,7 @@ import Streamly.Internal.Data.Unfold.Type (Unfold(..))
6868-- (Array(..), writeNUnsafe, defaultChunkSize, shrinkToFit,
6969-- lpackArraysChunksOf)
7070-- 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)
7272-- import Streamly.String (encodeUtf8, decodeUtf8, foldLines)
7373
7474-- 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
135135import Streamly.Internal.Data.Array.Foreign.Mut.Type (mutableArray)
136136import Streamly.Internal.System.IO (defaultChunkSize)
137137import Streamly.Internal.Data.Stream.Serial (SerialT)
138−import Streamly.Internal.Data.Stream.StreamK.Type (IsStream, mkStream)
139−
138+import Streamly.Internal.Data.Stream.IsStream.Type
139+ (IsStream, mkStream, fromStreamD)
140140#if !defined(mingw32_HOST_OS)
141+import Streamly.Internal.Data.Stream.IsStream.Type (toStreamD)
141142import Streamly.Internal.System.IOVec (groupIOVecsOf)
142−import Streamly.Internal.Data.Stream.StreamD (toStreamD)
143−import Streamly.Internal.Data.Stream.StreamD.Type (fromStreamD)
144143import qualified Streamly.Internal.FileSystem.FDIO as RawIO hiding (write)
145144import qualified Streamly.Internal.System.IOVec.Type as RawIO
146145#endif
@@ -290,7 +289,7 @@ _readArraysOfUpto size h = go
290289{-# INLINE_NORMAL readArraysOfUpto #-}
291290readArraysOfUpto :: (IsStream t, MonadIO m)
292291 => Int -> Handle -> t m (Array Word8)
293−readArraysOfUpto size h = D.fromStreamD (D.Stream step ())
292+readArraysOfUpto size h = fromStreamD (D.Stream step ())
294293 where
295294 {-# INLINE_LATE step #-}
296295 step _ _ = do
src/Streamly/Internal/FileSystem/File.hs+2−2
@@ -99,17 +99,17 @@ import Streamly.Internal.Data.Fold.Type (Fold(..))
9999import Streamly.Internal.Data.Unfold.Type (Unfold(..))
100100import Streamly.Internal.Data.Array.Foreign.Type (Array(..), writeNUnsafe)
101101import Streamly.Internal.Data.Stream.Serial (SerialT)
102−import Streamly.Internal.Data.Stream.StreamK.Type (IsStream)
102+import Streamly.Internal.Data.Stream.IsStream.Type (IsStream)
103103-- import Streamly.Data.Fold (Fold)
104104-- import Streamly.String (encodeUtf8, decodeUtf8, foldLines)
105105import Streamly.Internal.System.IO (defaultChunkSize)
106106
107+import qualified Streamly.Internal.Data.Array.Foreign as A
107108import qualified Streamly.Internal.Data.Fold.Type as FL
108109import qualified Streamly.Internal.Data.Unfold as UF
109110import qualified Streamly.Internal.FileSystem.Handle as FH
110111import qualified Streamly.Internal.Data.Array.Stream.Foreign as AS
111112import qualified Streamly.Internal.Data.Stream.IsStream as S
112−import qualified Streamly.Data.Array.Foreign as A
113113
114114-------------------------------------------------------------------------------
115115-- References
src/Streamly/Internal/FileSystem/Handle.hs+8−7
@@ -110,25 +110,26 @@ import System.IO (Handle, SeekMode(..), hGetBufSome, hPutBuf, hSeek)
110110import Prelude hiding (read)
111111
112112import Streamly.Internal.BaseCompat
113−import Streamly.Data.Fold (Fold)
113+import Streamly.Internal.Data.Fold (Fold)
114114import Streamly.Internal.Data.Fold.Type (Fold2(..))
115115import Streamly.Internal.Data.Unfold.Type (Unfold(..))
116116import Streamly.Internal.Data.Array.Foreign.Type
117117 (Array(..), writeNUnsafe, unsafeFreezeWithShrink)
118118import Streamly.Internal.Data.Array.Foreign.Mut.Type (mutableArray)
119119import 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)
121122import Streamly.Internal.Data.Array.Stream.Foreign (lpackArraysChunksOf)
122123-- import Streamly.String (encodeUtf8, decodeUtf8, foldLines)
123124import Streamly.Internal.System.IO (defaultChunkSize)
124125
125−import qualified Streamly.Data.Fold as FL
126−import qualified Streamly.Internal.Data.Fold.Type as FL
127−import qualified Streamly.Internal.Data.Unfold as UF
126+import qualified Streamly.Internal.Data.Array.Foreign as A
128127import 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
129130import qualified Streamly.Internal.Data.Stream.IsStream as S
130−import qualified Streamly.Data.Array.Foreign as A
131131import qualified Streamly.Internal.Data.Stream.StreamD.Type as D
132+import qualified Streamly.Internal.Data.Unfold as UF
132133
133134-- $setup
134135-- >>> import qualified Streamly.Data.Array.Foreign as Array
@@ -219,7 +220,7 @@ _toChunksWithBufferOf size h = go
219220{-# INLINE_NORMAL toChunksWithBufferOf #-}
220221toChunksWithBufferOf :: (IsStream t, MonadIO m) =>
221222 Int -> Handle -> t m (Array Word8)
222−toChunksWithBufferOf size h = D.fromStreamD (D.Stream step ())
223+toChunksWithBufferOf size h = fromStreamD (D.Stream step ())
223224 where
224225 {-# INLINE_LATE step #-}
225226 step _ _ = do
src/Streamly/Internal/Network/Inet/TCP.hs+3−3
@@ -106,8 +106,8 @@ import Prelude hiding (read)
106106import Streamly.Internal.Control.Concurrent (MonadAsync, fork)
107107import Streamly.Internal.Data.Array.Foreign.Type (Array(..), writeNUnsafe)
108108import Streamly.Internal.Data.Fold.Type (Fold(..))
109+import Streamly.Internal.Data.Stream.IsStream.Type (IsStream)
109110import Streamly.Internal.Data.Stream.Serial (SerialT)
110−import Streamly.Internal.Data.Stream.StreamK.Type (IsStream)
111111import Streamly.Internal.Data.Tuple.Strict (Tuple'(..))
112112import Streamly.Internal.Data.Unfold.Type (Unfold(..))
113113import Streamly.Internal.Network.Socket (SockSpec(..), accept, connections)
@@ -121,7 +121,6 @@ import qualified Streamly.Internal.Data.Array.Foreign as A
121121import qualified Streamly.Internal.Data.Array.Stream.Foreign as AS
122122import qualified Streamly.Internal.Data.Fold.Type as FL
123123import qualified Streamly.Internal.Data.Stream.IsStream as S
124−import qualified Streamly.Network.Socket as SK
125124import qualified Streamly.Internal.Network.Socket as ISK
126125
127126-------------------------------------------------------------------------------
@@ -356,7 +355,8 @@ writeChunks addr port = Fold step initial extract
356355 where
357356 initial = do
358357 skt <- liftIO (connect addr port)
359− fld <- FL.initialize (SK.writeChunks skt) `MC.onException` liftIO (Net.close skt)
358+ fld <- FL.initialize (ISK.writeChunks skt)
359+ `MC.onException` liftIO (Net.close skt)
360360 return $ FL.Partial (Tuple' fld skt)
361361 step (Tuple' fld skt) x = do
362362 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)
8686import qualified Network.Socket as Net
8787
8888import Streamly.Internal.BaseCompat
89−import Streamly.Internal.Data.Unfold.Type (Unfold(..))
90−import Streamly.Internal.Data.Array.Stream.Foreign (lpackArraysChunksOf)
91−import Streamly.Internal.Data.Array.Foreign.Type (Array(..))
89+import Streamly.Internal.Control.Concurrent (MonadAsync)
9290import 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)
9496import Streamly.Internal.Data.Stream.Serial (SerialT)
95−import Streamly.Internal.Data.Stream.StreamK.Type (IsStream, mkStream)
96−import Streamly.Data.Fold (Fold)
97+import Streamly.Internal.Data.Unfold.Type (Unfold(..))
9798-- import Streamly.String (encodeUtf8, decodeUtf8, foldLines)
9899import Streamly.Internal.System.IO (defaultChunkSize)
99100
100−import qualified Streamly.Data.Fold as FL
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
101+import qualified Streamly.Internal.Data.Array.Foreign as A
104102import 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
105105import qualified Streamly.Internal.Data.Stream.IsStream as S
106106import qualified Streamly.Internal.Data.Stream.StreamD.Type as D
107+import qualified Streamly.Internal.Data.Unfold as UF
107108
108109-- | @'forSocketM' action socket@ runs the monadic computation @action@ passing
109110-- the socket handle to it. The handle will be closed on exit from
@@ -343,7 +344,7 @@ _readChunksUptoWith f size h = go
343344toChunksWithBufferOf :: (IsStream t, MonadIO m)
344345 => Int -> Socket -> t m (Array Word8)
345346-- toChunksWithBufferOf = _readChunksUptoWith readChunk
346−toChunksWithBufferOf size h = D.fromStreamD (D.Stream step ())
347+toChunksWithBufferOf size h = fromStreamD (D.Stream step ())
347348 where
348349 {-# INLINE_LATE step #-}
349350 step _ _ = do
src/Streamly/Internal/Unicode/Char.hs+3−6
@@ -32,14 +32,11 @@ import Data.Char (isAsciiUpper, isAsciiLower, chr, ord)
3232import Data.Typeable (Typeable)
3333
3434import Unicode.Char (DecomposeMode(..))
35−import Streamly.Internal.Data.Stream.IsStream (IsStream)
35+import Streamly.Internal.Data.Stream.IsStream.Type
36+ (IsStream, fromStreamD, toStreamD)
3637import Streamly.Internal.Data.Stream.StreamD (Stream(..), Step (..))
3738
3839import qualified Unicode.Char as Char
39−import qualified Streamly.Internal.Data.Stream.StreamD as StreamD
40−
41−
42−-- import Streamly.Prelude (IsStream)
4340
4441-------------------------------------------------------------------------------
4542-- Unicode aware operations on strings
@@ -319,4 +316,4 @@ normalizeD NFC = partialComposeD . decomposeD False Canonical
319316normalizeD NFKC = partialComposeD . decomposeD False Kompat
320317
321318normalize :: (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 (..))
9090import GHC.IO.Encoding.Failure (isSurrogate)
9191import GHC.Ptr (Ptr (..), plusPtr)
9292import System.IO.Unsafe (unsafePerformIO)
93−import Streamly.Data.Fold (Fold)
94−import Streamly.Data.Array.Foreign (Array)
95−import Streamly.Internal.Data.Unfold (Unfold)
96−import Streamly.Internal.Data.SVar (adaptState)
97−import Streamly.Internal.Data.Stream.IsStream (IsStream)
93+import Streamly.Internal.Data.Array.Foreign (Array)
94+import Streamly.Internal.Data.Fold (Fold)
95+import Streamly.Internal.Data.Stream.IsStream.Type
96+ (IsStream, fromStreamD, toStreamD, adapt)
9897import Streamly.Internal.Data.Stream.Serial (SerialT)
9998import Streamly.Internal.Data.Stream.StreamD (Stream(..), Step (..))
99+import Streamly.Internal.Data.SVar (adaptState)
100100import Streamly.Internal.Data.Tuple.Strict (Tuple'(..))
101+import Streamly.Internal.Data.Unfold (Unfold)
101102import Streamly.Internal.System.IO (unsafeInlineIO)
102103
103104import qualified Streamly.Internal.Data.Unfold as Unfold
@@ -396,7 +397,7 @@ decodeUtf8EitherD = resumeDecodeUtf8EitherD 0 0
396397{-# INLINE decodeUtf8Either #-}
397398decodeUtf8Either :: (Monad m, IsStream t)
398399 => t m Word8 -> t m (Either DecodeError Char)
399−decodeUtf8Either = D.fromStreamD . decodeUtf8EitherD . D.toStreamD
400+decodeUtf8Either = fromStreamD . decodeUtf8EitherD . toStreamD
400401
401402-- |
402403--
@@ -409,7 +410,7 @@ resumeDecodeUtf8Either
409410 -> t m Word8
410411 -> t m (Either DecodeError Char)
411412resumeDecodeUtf8Either st cp =
412− D.fromStreamD . resumeDecodeUtf8EitherD st cp . D.toStreamD
413+ fromStreamD . resumeDecodeUtf8EitherD st cp . toStreamD
413414
414415-------------------------------------------------------------------------------
415416-- One shot decoding
@@ -533,7 +534,7 @@ decodeUtf8D = decodeUtf8WithD TransliterateCodingFailure
533534-- /Since: 0.8.0 (Lenient Behaviour)/
534535{-# INLINE decodeUtf8 #-}
535536decodeUtf8 :: (Monad m, IsStream t) => t m Word8 -> t m Char
536−decodeUtf8 = D.fromStreamD . decodeUtf8D . D.toStreamD
537+decodeUtf8 = fromStreamD . decodeUtf8D . toStreamD
537538
538539{-# INLINE decodeUtf8D' #-}
539540decodeUtf8D' :: Monad m => Stream m Word8 -> Stream m Char
@@ -545,7 +546,7 @@ decodeUtf8D' = decodeUtf8WithD ErrorOnCodingFailure
545546-- @since 0.8.0
546547{-# INLINE decodeUtf8' #-}
547548decodeUtf8' :: (Monad m, IsStream t) => t m Word8 -> t m Char
548−decodeUtf8' = D.fromStreamD . decodeUtf8D' . D.toStreamD
549+decodeUtf8' = fromStreamD . decodeUtf8D' . toStreamD
549550
550551{-# INLINE decodeUtf8D_ #-}
551552decodeUtf8D_ :: Monad m => Stream m Word8 -> Stream m Char
@@ -557,7 +558,7 @@ decodeUtf8D_ = decodeUtf8WithD DropOnCodingFailure
557558-- @since 0.8.0
558559{-# INLINE decodeUtf8_ #-}
559560decodeUtf8_ :: (Monad m, IsStream t) => t m Word8 -> t m Char
560−decodeUtf8_ = D.fromStreamD . decodeUtf8D_ . D.toStreamD
561+decodeUtf8_ = fromStreamD . decodeUtf8D_ . toStreamD
561562
562563-- | Same as 'decodeUtf8'
563564--
@@ -715,7 +716,7 @@ decodeUtf8ArraysD = decodeUtf8ArraysWithD TransliterateCodingFailure
715716decodeUtf8Arrays ::
716717 (MonadIO m, IsStream t) => t m (Array Word8) -> t m Char
717718decodeUtf8Arrays =
718− D.fromStreamD . decodeUtf8ArraysD . D.toStreamD
719+ fromStreamD . decodeUtf8ArraysD . toStreamD
719720
720721{-# INLINE decodeUtf8ArraysD' #-}
721722decodeUtf8ArraysD' ::
@@ -729,7 +730,7 @@ decodeUtf8ArraysD' = decodeUtf8ArraysWithD ErrorOnCodingFailure
729730-- /Pre-release/
730731{-# INLINE decodeUtf8Arrays' #-}
731732decodeUtf8Arrays' :: (MonadIO m, IsStream t) => t m (Array Word8) -> t m Char
732−decodeUtf8Arrays' = D.fromStreamD . decodeUtf8ArraysD' . D.toStreamD
733+decodeUtf8Arrays' = fromStreamD . decodeUtf8ArraysD' . toStreamD
733734
734735{-# INLINE decodeUtf8ArraysD_ #-}
735736decodeUtf8ArraysD_ ::
@@ -745,7 +746,7 @@ decodeUtf8ArraysD_ = decodeUtf8ArraysWithD DropOnCodingFailure
745746decodeUtf8Arrays_ ::
746747 (MonadIO m, IsStream t) => t m (Array Word8) -> t m Char
747748decodeUtf8Arrays_ =
748− D.fromStreamD . decodeUtf8ArraysD_ . D.toStreamD
749+ fromStreamD . decodeUtf8ArraysD_ . toStreamD
749750
750751-------------------------------------------------------------------------------
751752-- Encoding Unicode (UTF-8) Characters
@@ -867,7 +868,7 @@ encodeUtf8D' = encodeUtf8DGeneric ErrorInvalid
867868-- @since 0.8.0
868869{-# INLINE encodeUtf8' #-}
869870encodeUtf8' :: (Monad m, IsStream t) => t m Char -> t m Word8
870−encodeUtf8' = D.fromStreamD . encodeUtf8D' . D.toStreamD
871+encodeUtf8' = fromStreamD . encodeUtf8D' . toStreamD
871872
872873-- | See section "3.9 Unicode Encoding Forms" in
873874-- https://www.unicode.org/versions/Unicode13.0.0/UnicodeStandard-13.0.pdf
@@ -885,7 +886,7 @@ encodeUtf8D = encodeUtf8DGeneric ReplaceInvalid
885886-- /Since: 0.8.0 (Lenient Behaviour)/
886887{-# INLINE encodeUtf8 #-}
887888encodeUtf8 :: (Monad m, IsStream t) => t m Char -> t m Word8
888−encodeUtf8 = D.fromStreamD . encodeUtf8D . D.toStreamD
889+encodeUtf8 = fromStreamD . encodeUtf8D . toStreamD
889890
890891{-# INLINE_NORMAL encodeUtf8D_ #-}
891892encodeUtf8D_ :: Monad m => Stream m Char -> Stream m Word8
@@ -897,7 +898,7 @@ encodeUtf8D_ = encodeUtf8DGeneric DropInvalid
897898-- @since 0.8.0
898899{-# INLINE encodeUtf8_ #-}
899900encodeUtf8_ :: (Monad m, IsStream t) => t m Char -> t m Word8
900−encodeUtf8_ = D.fromStreamD . encodeUtf8D_ . D.toStreamD
901+encodeUtf8_ = fromStreamD . encodeUtf8D_ . toStreamD
901902
902903-- | Same as 'encodeUtf8'
903904--
@@ -932,7 +933,7 @@ encodeObjects :: (MonadIO m, IsStream t) =>
932933 -> Unfold m a Char
933934 -> t m a
934935 -> t m (Array Word8)
935−encodeObjects encode u = Serial.mapM (encodeObject encode u)
936+encodeObjects encode u = adapt . Serial.mapM (encodeObject encode u) . adapt
936937
937938-- | Encode a stream of 'String' using the supplied encoding scheme. Each
938939-- string is encoded as an @Array Word8@.
src/Streamly/Prelude.hs+1
@@ -936,6 +936,7 @@ module Streamly.Prelude
936936 )
937937where
938938
939+import Streamly.Internal.Control.Concurrent (MonadAsync)
939940import Prelude
940941 hiding (filter, drop, dropWhile, take, takeWhile, zipWith, foldr,
941942 foldl, map, mapM, mapM_, sequence, all, any, sum, product, elem,
streamly.cabal+10−6
@@ -77,6 +77,7 @@ extra-source-files:
7777 docs/*.hs
7878 docs/streamly-docs.cabal
7979 src/Streamly/Internal/Data/Stream/Instances.hs
80+ src/Streamly/Internal/Data/Stream/PreludeCommon.hs
8081 src/Streamly/Internal/Data/Time/Clock/config-clock.h
8182 src/Streamly/Internal/Data/Array/PrimInclude.hs
8283 src/Streamly/Internal/Data/Array/Prim/TypesInclude.hs
@@ -263,6 +264,7 @@ common default-extensions
263264 RecordWildCards
264265 ScopedTypeVariables
265266 TupleSections
267+ TypeApplications
266268 TypeFamilies
267269 ViewPatterns
268270
@@ -301,13 +303,11 @@ common lib-options
301303library
302304 import: lib-options
303305
304− if impl(ghc >= 8.1)
305− default-extensions: TypeApplications
306306 if impl(ghc >= 8.6)
307307 default-extensions: QuantifiedConstraints
308308
309309 js-sources: jsbits/clock.js
310− include-dirs: src
310+ include-dirs: src, src/Streamly/Internal/Data/Stream
311311 if os(windows)
312312 c-sources: src/Streamly/Internal/Data/Time/Clock/Windows.c
313313 exposed-modules: Streamly.Internal.FileSystem.Event.Windows
@@ -412,7 +412,6 @@ library
412412 , Streamly.Internal.Data.SmallArray.Type
413413
414414 -- streamly-base-streams
415− , Streamly.Internal.Data.Stream.StreamK
416415 -- StreamD depends on streamly-core-array
417416 , Streamly.Internal.Data.Stream.StreamD.Generate
418417 , Streamly.Internal.Data.Stream.StreamD.Eliminate
@@ -434,6 +433,7 @@ library
434433 , Streamly.Internal.Data.Fold.Tee
435434 , Streamly.Internal.Data.Fold
436435 , Streamly.Internal.Data.Fold.SVar
436+ , Streamly.Internal.Data.Fold.Async
437437 , Streamly.Internal.Data.Sink
438438 , Streamly.Internal.Data.Parser
439439 , Streamly.Internal.Data.Pipe
@@ -445,9 +445,11 @@ library
445445 , Streamly.Internal.Data.Stream.Parallel
446446 , Streamly.Internal.Data.Stream.Ahead
447447 , Streamly.Internal.Data.Stream.Zip
448+ , Streamly.Internal.Data.List
449+
450+ , Streamly.Internal.Data.Stream.IsStream.Type
448451 , Streamly.Internal.Data.Stream.IsStream.Combinators
449452 , Streamly.Internal.Data.Stream.IsStream.Common
450− , Streamly.Internal.Data.Stream.IsStream.Types
451453 , Streamly.Internal.Data.Stream.IsStream.Enumeration
452454 , Streamly.Internal.Data.Stream.IsStream.Generate
453455 , Streamly.Internal.Data.Stream.IsStream.Eliminate
@@ -458,7 +460,6 @@ library
458460 , Streamly.Internal.Data.Stream.IsStream.Lift
459461 , Streamly.Internal.Data.Stream.IsStream.Top
460462 , Streamly.Internal.Data.Stream.IsStream
461− , Streamly.Internal.Data.List
462463
463464 -- streamly-arrays
464465 -- May depend on streamly-core
@@ -501,6 +502,9 @@ library
501502 , Streamly.Internal.Network.Socket
502503 , Streamly.Internal.Network.Inet.TCP
503504
505+ -- Only used for benchmarks
506+ , Streamly.Internal.Data.Stream.StreamK
507+
504508 build-depends:
505509 -- Core libraries shipped with ghc, the min and max
506510 -- constraints of these libraries should match with
test/Streamly/Test/Prelude/WSerial.hs+2−1
@@ -60,7 +60,8 @@ interleaveCheck t f =
6060wSerialMinLengthProp :: Property
6161wSerialMinLengthProp =
6262 forAll (chooseInt (0, 10))
63− $ \len -> S.length (combined len) `shouldReturn` 2 * len + 1
63+ $ \len ->
64+ S.length (fromWSerial $ combined len) `shouldReturn` 2 * len + 1
6465
6566 where
6667