on master help sign in
Merge pull request #151 from composewell/unstream-safe
0133e74Harendra Kumar
benchmark/BaseStreams.hs+1
@@ -165,6 +165,7 @@ main =
165 ]
165 ]
166 , bgroup "elimination"
166 , bgroup "elimination"
167 [ benchIO "toNull" K.toNull K.sourceUnfoldrM
167 [ benchIO "toNull" K.toNull K.sourceUnfoldrM
168+ , benchIO "mapM_" K.mapM_ K.sourceUnfoldrM
168 , benchIO "uncons" K.uncons K.sourceUnfoldrM
169 , benchIO "uncons" K.uncons K.sourceUnfoldrM
169 , benchFold "init" K.init K.sourceUnfoldrM
170 , benchFold "init" K.init K.sourceUnfoldrM
170 , benchFold "tail" K.tail K.sourceUnfoldrM
171 , benchFold "tail" K.tail K.sourceUnfoldrM
benchmark/Linear.hs+1
@@ -97,6 +97,7 @@ main =
97 -- These are essentially appends
97 -- These are essentially appends
98 , benchIOSrc serially "foldMapWith" Ops.sourceFoldMapWith
98 , benchIOSrc serially "foldMapWith" Ops.sourceFoldMapWith
99 , benchIOSrc serially "foldMapWithM" Ops.sourceFoldMapWithM
99 , benchIOSrc serially "foldMapWithM" Ops.sourceFoldMapWithM
100+ , benchIOSrc serially "foldMapM" Ops.sourceFoldMapM
100 ]
101 ]
101 , bgroup "elimination"
102 , bgroup "elimination"
102 [ benchIOSink "toNull" $ Ops.toNull serially
103 [ benchIOSink "toNull" $ Ops.toNull serially
benchmark/LinearAsync.hs+26−13
@@ -40,12 +40,15 @@ main :: IO ()
40main =
40main =
41 defaultMain
41 defaultMain
42 [ bgroup "asyncly"
42 [ bgroup "asyncly"
43− [ -- benchIO "unfoldr" $ Ops.toNull asyncly
43+ [ benchSrcIO asyncly "unfoldr" Ops.sourceUnfoldr
44− benchSrcIO asyncly "unfoldrM" Ops.sourceUnfoldrM
44+ , benchSrcIO asyncly "unfoldrM" Ops.sourceUnfoldrM
45− -- , benchSrcIO asyncly "fromFoldable" Ops.sourceFromFoldable
45+ , benchSrcIO asyncly "fromFoldable" Ops.sourceFromFoldable
46 , benchSrcIO asyncly "fromFoldableM" Ops.sourceFromFoldableM
46 , benchSrcIO asyncly "fromFoldableM" Ops.sourceFromFoldableM
47− -- , benchSrcIO asyncly "foldMapWith" Ops.sourceFoldMapWith
47+ , benchSrcIO asyncly "foldMapWith" Ops.sourceFoldMapWith
48 , benchSrcIO asyncly "foldMapWithM" Ops.sourceFoldMapWithM
48 , benchSrcIO asyncly "foldMapWithM" Ops.sourceFoldMapWithM
49+ , benchSrcIO asyncly "foldMapM" Ops.sourceFoldMapM
50+ , benchIO "map" $ Ops.map' asyncly 1
51+ , benchIO "fmap" $ Ops.fmap' asyncly 1
49 , benchIO "mapM" $ Ops.mapM asyncly 1
52 , benchIO "mapM" $ Ops.mapM asyncly 1
50 , benchSrcIO asyncly "unfoldrM maxThreads 1"
53 , benchSrcIO asyncly "unfoldrM maxThreads 1"
51 (maxThreads 1 . Ops.sourceUnfoldrM)
54 (maxThreads 1 . Ops.sourceUnfoldrM)
@@ -53,23 +56,29 @@ main =
53 (maxBuffer 1 . Ops.sourceUnfoldrMN 1000)
56 (maxBuffer 1 . Ops.sourceUnfoldrMN 1000)
54 ]
57 ]
55 , bgroup "wAsyncly"
58 , bgroup "wAsyncly"
56− [ -- benchIO "unfoldr" $ Ops.toNull wAsyncly
59+ [ benchSrcIO wAsyncly "unfoldr" Ops.sourceUnfoldr
57− benchSrcIO wAsyncly "unfoldrM" Ops.sourceUnfoldrM
60+ , benchSrcIO wAsyncly "unfoldrM" Ops.sourceUnfoldrM
58− -- , benchSrcIO wAsyncly "fromFoldable" Ops.sourceFromFoldable
61+ , benchSrcIO wAsyncly "fromFoldable" Ops.sourceFromFoldable
59 , benchSrcIO wAsyncly "fromFoldableM" Ops.sourceFromFoldableM
62 , benchSrcIO wAsyncly "fromFoldableM" Ops.sourceFromFoldableM
60− -- , benchSrcIO wAsyncly "foldMapWith" Ops.sourceFoldMapWith
63+ , benchSrcIO wAsyncly "foldMapWith" Ops.sourceFoldMapWith
61 , benchSrcIO wAsyncly "foldMapWithM" Ops.sourceFoldMapWithM
64 , benchSrcIO wAsyncly "foldMapWithM" Ops.sourceFoldMapWithM
65+ , benchSrcIO wAsyncly "foldMapM" Ops.sourceFoldMapM
66+ , benchIO "map" $ Ops.map' wAsyncly 1
67+ , benchIO "fmap" $ Ops.fmap' wAsyncly 1
62 , benchIO "mapM" $ Ops.mapM wAsyncly 1
68 , benchIO "mapM" $ Ops.mapM wAsyncly 1
63 ]
69 ]
64 -- unfoldr and fromFoldable are always serial and thereofore the same for
70 -- unfoldr and fromFoldable are always serial and thereofore the same for
65 -- all stream types.
71 -- all stream types.
66 , bgroup "aheadly"
72 , bgroup "aheadly"
67− [ -- benchIO "unfoldr" $ Ops.toNull aheadly
73+ [ benchSrcIO aheadly "unfoldr" Ops.sourceUnfoldr
68− benchSrcIO aheadly "unfoldrM" Ops.sourceUnfoldrM
74+ , benchSrcIO aheadly "unfoldrM" Ops.sourceUnfoldrM
69 , benchSrcIO aheadly "fromFoldableM" Ops.sourceFromFoldableM
75 , benchSrcIO aheadly "fromFoldableM" Ops.sourceFromFoldableM
70 -- , benchSrcIO aheadly "foldMapWith" Ops.sourceFoldMapWith
76 -- , benchSrcIO aheadly "foldMapWith" Ops.sourceFoldMapWith
71 , benchSrcIO aheadly "foldMapWithM" Ops.sourceFoldMapWithM
77 , benchSrcIO aheadly "foldMapWithM" Ops.sourceFoldMapWithM
78+ , benchSrcIO aheadly "foldMapM" Ops.sourceFoldMapM
79+ , benchIO "map" $ Ops.map' aheadly 1
80+ , benchIO "fmap" $ Ops.fmap' aheadly 1
72− , benchIO "mapM" $ Ops.mapM aheadly 1
81+ , benchIO "mapM" $ Ops.mapM aheadly 1
73 , benchSrcIO aheadly "unfoldrM maxThreads 1"
82 , benchSrcIO aheadly "unfoldrM maxThreads 1"
74 (maxThreads 1 . Ops.sourceUnfoldrM)
83 (maxThreads 1 . Ops.sourceUnfoldrM)
75 , benchSrcIO aheadly "unfoldrM maxBuffer 1 (1000 ops)"
84 , benchSrcIO aheadly "unfoldrM maxBuffer 1 (1000 ops)"
@@ -78,15 +87,19 @@ main =
78 ]
87 ]
79 -- XXX need to use smaller streams to finish in reasonable time
88 -- XXX need to use smaller streams to finish in reasonable time
80 , bgroup "parallely"
89 , bgroup "parallely"
81− [ --benchIO "unfoldr" $ Ops.toNull parallely
90+ [ benchSrcIO parallely "unfoldr" Ops.sourceUnfoldr
82− benchSrcIO parallely "unfoldrM" Ops.sourceUnfoldrM
91+ , benchSrcIO parallely "unfoldrM" Ops.sourceUnfoldrM
83 --, benchSrcIO parallely "fromFoldable" Ops.sourceFromFoldable
92 --, benchSrcIO parallely "fromFoldable" Ops.sourceFromFoldable
84 , benchSrcIO parallely "fromFoldableM" Ops.sourceFromFoldableM
93 , benchSrcIO parallely "fromFoldableM" Ops.sourceFromFoldableM
85 -- , benchSrcIO parallely "foldMapWith" Ops.sourceFoldMapWith
94 -- , benchSrcIO parallely "foldMapWith" Ops.sourceFoldMapWith
86 , benchSrcIO parallely "foldMapWithM" Ops.sourceFoldMapWithM
95 , benchSrcIO parallely "foldMapWithM" Ops.sourceFoldMapWithM
96+ , benchSrcIO parallely "foldMapM" Ops.sourceFoldMapM
97+ , benchIO "map" $ Ops.map' parallely 1
98+ , benchIO "fmap" $ Ops.fmap' parallely 1
87 , benchIO "mapM" $ Ops.mapM parallely 1
99 , benchIO "mapM" $ Ops.mapM parallely 1
88 -- Zip has only one parallel flavor
100 -- Zip has only one parallel flavor
89 , benchIO "zip" Ops.zipAsync
101 , benchIO "zip" Ops.zipAsync
90 , benchIO "zipM" Ops.zipAsyncM
102 , benchIO "zipM" Ops.zipAsyncM
103+ , benchIO "zipAp" Ops.zipAsyncAp
91 ]
104 ]
92 ]
105 ]
benchmark/LinearOps.hs+26−4
@@ -19,7 +19,7 @@ import Data.Maybe (fromJust)
19import Prelude
19import Prelude
20 (Monad, Int, (+), ($), (.), return, fmap, even, (>), (<=), (==), (>=),
20 (Monad, Int, (+), ($), (.), return, fmap, even, (>), (<=), (==), (>=),
21 subtract, undefined, Maybe(..), odd, Bool, not, (>>=), mapM_, curry,
21 subtract, undefined, Maybe(..), odd, Bool, not, (>>=), mapM_, curry,
22− maxBound, div, IO, compare, Double, fromIntegral, Integer)
22+ maxBound, div, IO, compare, Double, fromIntegral, Integer, (<$>), (<*>))
23import qualified Prelude as P
23import qualified Prelude as P
24import qualified Data.Foldable as F
24import qualified Data.Foldable as F
25import qualified GHC.Exts as GHC
25import qualified GHC.Exts as GHC
@@ -49,7 +49,7 @@ type Stream m a = S.SerialT m a
49
49
50{-# INLINE source #-}
50{-# INLINE source #-}
51source :: (S.MonadAsync m, S.IsStream t) => Int -> t m Int
51source :: (S.MonadAsync m, S.IsStream t) => Int -> t m Int
52−source n = S.serially $ sourceUnfoldrM n
52+source n = sourceUnfoldrM n
53
53
54{-# INLINE sourceIntFromTo #-}
54{-# INLINE sourceIntFromTo #-}
55sourceIntFromTo :: (Monad m, S.IsStream t) => Int -> t m Int
55sourceIntFromTo :: (Monad m, S.IsStream t) => Int -> t m Int
@@ -98,6 +98,11 @@ sourceFoldMapWithM :: (S.IsStream t, Monad m, S.Semigroup (t m Int))
98 => Int -> t m Int
98 => Int -> t m Int
99sourceFoldMapWithM n = S.foldMapWith (S.<>) (S.yieldM . return) [n..n+value]
99sourceFoldMapWithM n = S.foldMapWith (S.<>) (S.yieldM . return) [n..n+value]
100
100
101+{-# INLINE sourceFoldMapM #-}
102+sourceFoldMapM :: (S.IsStream t, Monad m, P.Monoid (t m Int))
103+ => Int -> t m Int
104+sourceFoldMapM n = F.foldMap (S.yieldM . return) [n..n+value]
105+
101{-# INLINE sourceUnfoldr #-}
106{-# INLINE sourceUnfoldr #-}
102sourceUnfoldr :: (Monad m, S.IsStream t) => Int -> t m Int
107sourceUnfoldr :: (Monad m, S.IsStream t) => Int -> t m Int
103sourceUnfoldr n = S.unfoldr step n
108sourceUnfoldr n = S.unfoldr step n
@@ -173,6 +178,8 @@ last, minimum, maximum, find, findIndex, elemIndex, foldl1', foldr1
173minimumBy, maximumBy :: Monad m => Stream m Int -> m (Maybe Int)
178minimumBy, maximumBy :: Monad m => Stream m Int -> m (Maybe Int)
174
179
175{-# INLINE foldl' #-}
180{-# INLINE foldl' #-}
181+{-# INLINE foldr #-}
182+{-# INLINE foldrM #-}
176{-# INLINE length #-}
183{-# INLINE length #-}
177{-# INLINE sum #-}
184{-# INLINE sum #-}
178{-# INLINE product #-}
185{-# INLINE product #-}
@@ -307,7 +314,12 @@ scan, scanl1', map, fmap, mapMaybe, filterEven, filterAllOut,
307mapMaybeM :: S.MonadAsync m => Int -> Stream m Int -> m ()
314mapMaybeM :: S.MonadAsync m => Int -> Stream m Int -> m ()
308
315
309{-# INLINE mapM #-}
316{-# INLINE mapM #-}
317+{-# INLINE map' #-}
318+{-# INLINE fmap' #-}
319+mapM, map' :: (S.IsStream t, S.MonadAsync m)
320+ => (t m Int -> S.SerialT m Int) -> Int -> t m Int -> m ()
321+
310−mapM :: (S.IsStream t, S.MonadAsync m)
322+fmap' :: (S.IsStream t, S.MonadAsync m, P.Functor (t m))
311 => (t m Int -> S.SerialT m Int) -> Int -> t m Int -> m ()
323 => (t m Int -> S.SerialT m Int) -> Int -> t m Int -> m ()
312
324
313{-# INLINE sequence #-}
325{-# INLINE sequence #-}
@@ -317,7 +329,9 @@ sequence :: (S.IsStream t, S.MonadAsync m)
317scan n = composeN n $ S.scanl' (+) 0
329scan n = composeN n $ S.scanl' (+) 0
318scanl1' n = composeN n $ S.scanl1' (+)
330scanl1' n = composeN n $ S.scanl1' (+)
319fmap n = composeN n $ Prelude.fmap (+1)
331fmap n = composeN n $ Prelude.fmap (+1)
332+fmap' t n = composeN' n $ t . Prelude.fmap (+1)
320map n = composeN n $ S.map (+1)
333map n = composeN n $ S.map (+1)
334+map' t n = composeN' n $ t . S.map (+1)
321mapM t n = composeN' n $ t . S.mapM return
335mapM t n = composeN' n $ t . S.mapM return
322mapMaybe n = composeN n $ S.mapMaybe
336mapMaybe n = composeN n $ S.mapMaybe
323 (\x -> if Prelude.odd x then Nothing else Just x)
337 (\x -> if Prelude.odd x then Nothing else Just x)
@@ -421,17 +435,25 @@ stripPrefix src = do
421
435
422{-# INLINE zipAsync #-}
436{-# INLINE zipAsync #-}
423{-# INLINE zipAsyncM #-}
437{-# INLINE zipAsyncM #-}
438+{-# INLINE zipAsyncAp #-}
424−zipAsync, zipAsyncM :: S.MonadAsync m => Stream m Int -> m ()
439+zipAsync, zipAsyncAp, zipAsyncM :: S.MonadAsync m => Stream m Int -> m ()
425
440
426zipAsync src = do
441zipAsync src = do
427 r <- S.tail src
442 r <- S.tail src
428 let src1 = fromJust r
443 let src1 = fromJust r
429 transform (S.zipAsyncWith (,) src src1)
444 transform (S.zipAsyncWith (,) src src1)
445+
430zipAsyncM src = do
446zipAsyncM src = do
431 r <- S.tail src
447 r <- S.tail src
432 let src1 = fromJust r
448 let src1 = fromJust r
433 transform (S.zipAsyncWithM (curry return) src src1)
449 transform (S.zipAsyncWithM (curry return) src src1)
434
450
451+zipAsyncAp src = do
452+ r <- S.tail src
453+ let src1 = fromJust r
454+ transform (S.zipAsyncly $ (,) <$> S.serially src
455+ <*> S.serially src1)
456+
435{-# INLINE eqBy #-}
457{-# INLINE eqBy #-}
436eqBy :: (Monad m, P.Eq a) => Stream m a -> m P.Bool
458eqBy :: (Monad m, P.Eq a) => Stream m a -> m P.Bool
437eqBy src = S.eqBy (==) src src
459eqBy src = S.eqBy (==) src src
benchmark/NanoBenchmarks.hs+18−4
@@ -3,15 +3,18 @@
3-- at GHC generated code for optimizing specific problematic cases.
3-- at GHC generated code for optimizing specific problematic cases.
4-------------------------------------------------------------------------------
4-------------------------------------------------------------------------------
5
5
6+{-# LANGUAGE FlexibleContexts #-}
6{-# LANGUAGE ScopedTypeVariables #-}
7{-# LANGUAGE ScopedTypeVariables #-}
8+import Streamly.SVar (MonadAsync)
7−import qualified Streamly.Streams.StreamD as S
9+import qualified Streamly.Streams.StreamK as S
8import Gauge
10import Gauge
11+import System.Random
9
12
10maxValue :: Int
13maxValue :: Int
11maxValue = 100000
14maxValue = 100000
12
15
13{-# INLINE sourceUnfoldrM #-}
16{-# INLINE sourceUnfoldrM #-}
14−sourceUnfoldrM :: Monad m => S.Stream m Int
17+sourceUnfoldrM :: MonadAsync m => S.Stream m Int
15sourceUnfoldrM = S.unfoldrM step 0
18sourceUnfoldrM = S.unfoldrM step 0
16 where
19 where
17 step cnt =
20 step cnt =
@@ -20,7 +23,7 @@ sourceUnfoldrM = S.unfoldrM step 0
20 else return (Just (cnt, cnt + 1))
23 else return (Just (cnt, cnt + 1))
21
24
22{-# INLINE sourceUnfoldrMN #-}
25{-# INLINE sourceUnfoldrMN #-}
23−sourceUnfoldrMN :: Monad m => Int -> S.Stream m Int
26+sourceUnfoldrMN :: MonadAsync m => Int -> S.Stream m Int
24sourceUnfoldrMN n = S.unfoldrM step n
27sourceUnfoldrMN n = S.unfoldrM step n
25 where
28 where
26 step cnt =
29 step cnt =
@@ -28,6 +31,15 @@ sourceUnfoldrMN n = S.unfoldrM step n
28 then return Nothing
31 then return Nothing
29 else return (Just (cnt, cnt + 1))
32 else return (Just (cnt, cnt + 1))
30
33
34+{-# INLINE sourceUnfoldr #-}
35+sourceUnfoldr :: Monad m => Int -> S.Stream m Int
36+sourceUnfoldr n = S.unfoldr step n
37+ where
38+ step cnt =
39+ if cnt > n + maxValue
40+ then Nothing
41+ else Just (cnt, cnt + 1)
42+
31-------------------------------------------------------------------------------
43-------------------------------------------------------------------------------
32-- take-drop composition
44-- take-drop composition
33-------------------------------------------------------------------------------
45-------------------------------------------------------------------------------
@@ -64,7 +76,7 @@ dropWhileFalseX4 = S.runStream
64
76
65{-# INLINE iterateSource #-}
77{-# INLINE iterateSource #-}
66iterateSource
78iterateSource
67− :: Monad m
79+ :: MonadAsync m
68 => (S.Stream m Int -> S.Stream m Int) -> Int -> Int -> S.Stream m Int
80 => (S.Stream m Int -> S.Stream m Int) -> Int -> Int -> S.Stream m Int
69iterateSource g i n = f i (sourceUnfoldrMN n)
81iterateSource g i n = f i (sourceUnfoldrMN n)
70 where
82 where
@@ -75,6 +87,8 @@ iterateSource g i n = f i (sourceUnfoldrMN n)
75-- We keep all of them enabled by default for testing the build.
87-- We keep all of them enabled by default for testing the build.
76main :: IO ()
88main :: IO ()
77main = do
89main = do
90+ defaultMain [bench "unfoldr" $ nfIO $
91+ randomRIO (1,1) >>= \n -> S.runStream (sourceUnfoldr n)]
78 defaultMain [bench "take-drop" $ nfIO $ takeDrop sourceUnfoldrM]
92 defaultMain [bench "take-drop" $ nfIO $ takeDrop sourceUnfoldrM]
79 defaultMain [bench "dropWhileFalseX4" $
93 defaultMain [bench "dropWhileFalseX4" $
80 nfIO $ dropWhileFalseX4 sourceUnfoldrM]
94 nfIO $ dropWhileFalseX4 sourceUnfoldrM]
benchmark/Nested.hs+12−6
@@ -23,7 +23,8 @@ main =
23 -- TBD Study scaling with 10, 100, 1000 loop iterations
23 -- TBD Study scaling with 10, 100, 1000 loop iterations
24 defaultMain
24 defaultMain
25 [ bgroup "serially"
25 [ bgroup "serially"
26+ [ benchIO "toNullAp" $ Ops.toNullAp serially
26− [ benchIO "toNull" $ Ops.toNull serially
27+ , benchIO "toNull" $ Ops.toNull serially
27 , benchIO "toList" $ Ops.toList serially
28 , benchIO "toList" $ Ops.toList serially
28 -- , benchIO "toListSome" $ Ops.toListSome serially
29 -- , benchIO "toListSome" $ Ops.toListSome serially
29 , benchIO "filterAllOut" $ Ops.filterAllOut serially
30 , benchIO "filterAllOut" $ Ops.filterAllOut serially
@@ -33,7 +34,8 @@ main =
33 ]
34 ]
34
35
35 , bgroup "wSerially"
36 , bgroup "wSerially"
37+ [ benchIO "toNullAp" $ Ops.toNullAp wSerially
36− [ benchIO "toNull" $ Ops.toNull wSerially
38+ , benchIO "toNull" $ Ops.toNull wSerially
37 , benchIO "toList" $ Ops.toList wSerially
39 , benchIO "toList" $ Ops.toList wSerially
38 -- , benchIO "toListSome" $ Ops.toListSome wSerially
40 -- , benchIO "toListSome" $ Ops.toListSome wSerially
39 , benchIO "filterAllOut" $ Ops.filterAllOut wSerially
41 , benchIO "filterAllOut" $ Ops.filterAllOut wSerially
@@ -43,7 +45,8 @@ main =
43 ]
45 ]
44
46
45 , bgroup "aheadly"
47 , bgroup "aheadly"
48+ [ benchIO "toNullAp" $ Ops.toNullAp aheadly
46− [ benchIO "toNull" $ Ops.toNull aheadly
49+ , benchIO "toNull" $ Ops.toNull aheadly
47 , benchIO "toList" $ Ops.toList aheadly
50 , benchIO "toList" $ Ops.toList aheadly
48 -- , benchIO "toListSome" $ Ops.toListSome aheadly
51 -- , benchIO "toListSome" $ Ops.toListSome aheadly
49 , benchIO "filterAllOut" $ Ops.filterAllOut aheadly
52 , benchIO "filterAllOut" $ Ops.filterAllOut aheadly
@@ -53,7 +56,8 @@ main =
53 ]
56 ]
54
57
55 , bgroup "asyncly"
58 , bgroup "asyncly"
59+ [ benchIO "toNullAp" $ Ops.toNullAp asyncly
56− [ benchIO "toNull" $ Ops.toNull asyncly
60+ , benchIO "toNull" $ Ops.toNull asyncly
57 , benchIO "toList" $ Ops.toList asyncly
61 , benchIO "toList" $ Ops.toList asyncly
58 -- , benchIO "toListSome" $ Ops.toListSome asyncly
62 -- , benchIO "toListSome" $ Ops.toListSome asyncly
59 , benchIO "filterAllOut" $ Ops.filterAllOut asyncly
63 , benchIO "filterAllOut" $ Ops.filterAllOut asyncly
@@ -63,7 +67,8 @@ main =
63 ]
67 ]
64
68
65 , bgroup "wAsyncly"
69 , bgroup "wAsyncly"
70+ [ benchIO "toNullAp" $ Ops.toNullAp wAsyncly
66− [ benchIO "toNull" $ Ops.toNull wAsyncly
71+ , benchIO "toNull" $ Ops.toNull wAsyncly
67 , benchIO "toList" $ Ops.toList wAsyncly
72 , benchIO "toList" $ Ops.toList wAsyncly
68 -- , benchIO "toListSome" $ Ops.toListSome wAsyncly
73 -- , benchIO "toListSome" $ Ops.toListSome wAsyncly
69 , benchIO "filterAllOut" $ Ops.filterAllOut wAsyncly
74 , benchIO "filterAllOut" $ Ops.filterAllOut wAsyncly
@@ -73,7 +78,8 @@ main =
73 ]
78 ]
74
79
75 , bgroup "parallely"
80 , bgroup "parallely"
81+ [ benchIO "toNullAp" $ Ops.toNullAp parallely
76− [ benchIO "toNull" $ Ops.toNull parallely
82+ , benchIO "toNull" $ Ops.toNull parallely
77 , benchIO "toList" $ Ops.toList parallely
83 , benchIO "toList" $ Ops.toList parallely
78 --, benchIO "toListSome" $ Ops.toListSome parallely
84 --, benchIO "toListSome" $ Ops.toListSome parallely
79 , benchIO "filterAllOut" $ Ops.filterAllOut parallely
85 , benchIO "filterAllOut" $ Ops.filterAllOut parallely
benchmark/NestedOps.hs+7
@@ -62,6 +62,13 @@ runToList = S.toList
62-- Benchmark ops
62-- Benchmark ops
63-------------------------------------------------------------------------------
63-------------------------------------------------------------------------------
64
64
65+{-# INLINE toNullAp #-}
66+toNullAp
67+ :: (S.IsStream t, S.MonadAsync m, Monad (t m))
68+ => (t m Int -> S.SerialT m Int) -> Int -> m ()
69+toNullAp t start = runStream . t $
70+ (+) <$> source start prodCount <*> source start prodCount
71+
65{-# INLINE toNull #-}
72{-# INLINE toNull #-}
66toNull
73toNull
67 :: (S.IsStream t, S.MonadAsync m, Monad (t m))
74 :: (S.IsStream t, S.MonadAsync m, Monad (t m))
benchmark/StreamDOps.hs+1−1
@@ -59,7 +59,7 @@ sourceUnfoldrM n = S.unfoldrM step n
59
59
60{-# INLINE sourceFromEnum #-}
60{-# INLINE sourceFromEnum #-}
61sourceFromEnum :: Monad m => Int -> Stream m Int
61sourceFromEnum :: Monad m => Int -> Stream m Int
62−sourceFromEnum n = S.enumFromStepN n 1 value
62+sourceFromEnum n = S.intFromTo n (n + value)
63
63
64{-# INLINE sourceFromList #-}
64{-# INLINE sourceFromList #-}
65sourceFromList :: Monad m => Int -> Stream m Int
65sourceFromList :: Monad m => Int -> Stream m Int
benchmark/StreamKOps.hs+9−5
@@ -14,7 +14,7 @@ import Control.Monad (when)
14import Data.Maybe (isJust)
14import Data.Maybe (isJust)
15import Prelude
15import Prelude
16 (Monad, Int, (+), ($), (.), return, even, (>), (<=), div,
16 (Monad, Int, (+), ($), (.), return, even, (>), (<=), div,
17− subtract, undefined, Maybe(..), not, mapM_, (>>=),
17+ subtract, undefined, Maybe(..), not, (>>=),
18 maxBound)
18 maxBound)
19import qualified Prelude as P
19import qualified Prelude as P
20
20
@@ -116,6 +116,10 @@ source = sourceUnfoldrM
116runStream :: Monad m => Stream m a -> m ()
116runStream :: Monad m => Stream m a -> m ()
117runStream = S.runStream
117runStream = S.runStream
118
118
119+{-# INLINE mapM_ #-}
120+mapM_ :: Monad m => Stream m a -> m ()
121+mapM_ = S.mapM_ (\_ -> return ())
122+
119toNull = runStream
123toNull = runStream
120uncons s = do
124uncons s = do
121 r <- S.uncons s
125 r <- S.uncons s
@@ -127,19 +131,19 @@ uncons s = do
127init :: (Monad m, S.IsStream t) => t m a -> m ()
131init :: (Monad m, S.IsStream t) => t m a -> m ()
128init s = do
132init s = do
129 t <- S.init s
133 t <- S.init s
130− mapM_ S.runStream t
134+ P.mapM_ S.runStream t
131
135
132{-# INLINE tail #-}
136{-# INLINE tail #-}
133tail :: (Monad m, S.IsStream t) => t m a -> m ()
137tail :: (Monad m, S.IsStream t) => t m a -> m ()
134−tail s = S.tail s >>= mapM_ tail
138+tail s = S.tail s >>= P.mapM_ tail
135
139
136nullTail s = do
140nullTail s = do
137 r <- S.null s
141 r <- S.null s
138− when (not r) $ S.tail s >>= mapM_ nullTail
142+ when (not r) $ S.tail s >>= P.mapM_ nullTail
139
143
140headTail s = do
144headTail s = do
141 h <- S.head s
145 h <- S.head s
142− when (isJust h) $ S.tail s >>= mapM_ headTail
146+ when (isJust h) $ S.tail s >>= P.mapM_ headTail
143
147
144toList = S.toList
148toList = S.toList
145foldl = S.foldl' (+) 0
149foldl = S.foldl' (+) 0
src/Streamly/Prelude.hs+92−91
@@ -363,7 +363,7 @@ import Prelude
363import qualified Prelude
363import qualified Prelude
364import qualified System.IO as IO
364import qualified System.IO as IO
365
365
366−import Streamly.SVar (MonadAsync, defState, rstState)
366+import Streamly.SVar (MonadAsync, defState)
367import Streamly.Streams.Async (mkAsync')
367import Streamly.Streams.Async (mkAsync')
368import Streamly.Streams.Combinators (maxYields)
368import Streamly.Streams.Combinators (maxYields)
369import Streamly.Streams.Prelude (fromStreamS, toStreamS)
369import Streamly.Streams.Prelude (fromStreamS, toStreamS)
@@ -394,6 +394,7 @@ import qualified Streamly.Streams.Serial as Serial
394-- the head of the stream and @ma@ its tail.
394-- the head of the stream and @ma@ its tail.
395--
395--
396-- @since 0.1.0
396-- @since 0.1.0
397+{-# INLINE uncons #-}
397uncons :: (IsStream t, Monad m) => SerialT m a -> m (Maybe (a, t m a))
398uncons :: (IsStream t, Monad m) => SerialT m a -> m (Maybe (a, t m a))
398uncons m = K.uncons (K.adapt m)
399uncons m = K.uncons (K.adapt m)
399
400
@@ -840,9 +841,9 @@ iterate step = fromStream . go
840iterateM :: (IsStream t, MonadAsync m) => (a -> m a) -> a -> t m a
841iterateM :: (IsStream t, MonadAsync m) => (a -> m a) -> a -> t m a
841iterateM step = go
842iterateM step = go
842 where
843 where
843− go s = fromStream $ K.Stream $ \svr stp sng yld -> do
844+ go s = K.mkStream $ \st stp sng yld -> do
844 next <- step s
845 next <- step s
845− K.unStream (toStream (return s |: go next)) svr stp sng yld
846+ K.foldStreamShared st stp sng yld (return s |: go next)
846
847
847------------------------------------------------------------------------------
848------------------------------------------------------------------------------
848-- Conversions
849-- Conversions
@@ -894,9 +895,9 @@ each = K.fromFoldable
894--
895--
895-- @since 0.1.0
896-- @since 0.1.0
896fromHandle :: (IsStream t, MonadIO m) => IO.Handle -> t m String
897fromHandle :: (IsStream t, MonadIO m) => IO.Handle -> t m String
897−fromHandle h = fromStream go
898+fromHandle h = go
898 where
899 where
899− go = K.Stream $ \_ stp _ yld -> do
900+ go = K.mkStream $ \_ yld _ stp -> do
900 eof <- liftIO $ IO.hIsEOF h
901 eof <- liftIO $ IO.hIsEOF h
901 if eof
902 if eof
902 then stp
903 then stp
@@ -923,60 +924,69 @@ foldrM = P.foldrM
923
924
924-- | Lazy right associative fold.
925-- | Lazy right associative fold.
925--
926--
926−-- @foldr f z xs@ deconstructs @xs@ one element @x@ at a time, applying the
927+-- For lists a @foldr@ looks like:
927−-- function @f@ to @x@ and the tail of the output. The tail recurses until the
928−-- input finishes and @z@ is used as the tail end.
929--
928--
930-- @
929-- @
931−-- foldr f z xs == x1 \`f` tail1
930+-- foldr f z [] = z
932−-- tail1 == x2 \`f` tail2
931+-- foldr f z (x:xs) = x \`f` foldr f z xs
933−-- tail2 == x3 \`f` tail3
934−-- ...
935−-- tailn == xn \`f` z
936-- @
932-- @
937--
933--
934+-- The recursive expression is the second argument of the fold step `f`.
935+-- Therefore, the evaluation of the recursive call depends on `f`. It can
936+-- terminate recursion by not inspecting the second argument based on a
937+-- condition. When expanded fully, it results in the following right associated
938−-- Resulting in a right associated expression:
938+-- expression:
939--
939--
940-- @
940-- @
941-- foldr f z xs == x1 \`f` (x2 \`f` ...(xn \`f` z))
941-- foldr f z xs == x1 \`f` (x2 \`f` ...(xn \`f` z))
942-- @
942-- @
943--
943--
944−-- When the outermost operation in the fold function is a constructor, foldr
944+-- When `f` is a constructor, we can see that the first deconstruction of this
945−-- generates a structure that can be consumed lazily. For example:
945+-- expression would be @x1@ on the left and the recursive expression on the
946+-- right. Therefore, we can deconstruct it to access the input elements in the
947+-- first-in-first-out (FIFO) order and consume the reconstructed structure
948+-- lazily. The recursive expression on the right gets evaluated incrementall
949+-- as demanded by the consumer. For example:
946--
950--
947-- @
951-- @
948-- > S.foldr (:) [] $ S.fromList [1,2,3,4]
952-- > S.foldr (:) [] $ S.fromList [1,2,3,4]
949-- [1,2,3,4]
953-- [1,2,3,4]
950-- @
954-- @
951--
955--
956+-- When `f` is a function strict in its second argument, the right side of the
957+-- expression gets evaluated as follows:
958+--
952-- @
959-- @
953−-- 1 : tail
960+-- foldr f z xs == x1 \`f` tail1
954−-- 1 : (2 : tail)
961+-- tail1 == x2 \`f` tail2
955−-- 1 : (2 : (3 : tail))
962+-- tail2 == x3 \`f` tail3
956−-- 1 : (2 : (3 : (4 : [])))
963+-- ...
964+-- tailn == xn \`f` z
957-- @
965-- @
958--
966--
959−-- When the outermost operation is a function @foldr@ results in a right
967+-- In @foldl'@ we have both the arguments of `f` available at each step,
960−-- associated expression which cannot be reduced until the whole expression has
968+-- therefore, each step can be reduced immediately. However, in @foldr@ the
961−-- been built. Therefore, it ends up consuming the whole input, buffering the
969+-- second argument to `f` is a recursive call, therefore, it ends up building
962−-- whole expression in memory before reduction can start. For example:
970+-- the whole expression in memory before it can be reduced, consuming the whole
971+-- input. This makes @foldr@ much less efficient for reduction compared to
972+-- @foldl'@. For example:
963--
973--
964-- @
974-- @
965-- > S.foldr (+) 0 $ S.fromList [1,2,3,4]
975-- > S.foldr (+) 0 $ S.fromList [1,2,3,4]
966-- 10
976-- 10
967-- @
977-- @
968--
978--
969−-- @
979+-- When the underlying monad @m@ is strict (e.g. IO), then @foldr@ ends up
970−-- 1 + tail
980+-- evaluating all of its input because of strict evaluation of the recursive
971−-- 1 + (2 + tail)
981+-- call:
972−-- 1 + (2 + (3 + tail))
982+--
973−-- 1 + (2 + (3 + (4 + 0)))
983+-- >> S.foldr (\_ _ -> []) [] $ S.fromList (1:undefined)
974−-- @
984+-- >*** Exception: Prelude.undefined
975--
985--
976−-- In @foldr@, the output tail is the source of recursion, we can stop
986+-- In a lazy monad, we can consume the input lazily, and terminate the fold
977−-- recursion and terminate the fold by yielding a terminal value as tail:
987+-- by conditionally not inspecting the recursive expression.
978--
988--
979−-- >> S.foldr (\x rest -> if x == 3 then [] else x : rest) [] $ S.fromList [4,1,3,undefined]
989+-- >> runIdentity $ S.foldr (\x rest -> if x == 3 then [] else x : rest) [] $ S.fromList (4:1:3:undefined)
980-- >[4,1]
990-- >[4,1]
981--
991--
982-- The arguments to the folding function (@a -> b -> b@) are in the head and
992-- The arguments to the folding function (@a -> b -> b@) are in the head and
@@ -1014,37 +1024,38 @@ foldl = foldx
1014
1024
1015-- | Strict left associative fold.
1025-- | Strict left associative fold.
1016--
1026--
1017−-- @foldl' f z xs@ deconstructs @xs@ one element @x@ at a time, applying the
1027+-- For lists a @foldl@ looks like:
1018−-- function @f@ to the output accumulated till now (the head of the expression)
1019−-- and @x@. The accumulator starts with the initial value @z@ and keeps
1020−-- accumulating elements until the input finishes.
1021--
1028--
1022-- @
1029-- @
1023−-- head1 == z \`f` x1
1030+-- foldl f z [] = z
1024−-- head2 == head1 \`f` x2
1031+-- foldl f z (x:xs) = foldl f (z \`f` x) xs
1025−-- head3 == head2 \`f` x3
1026−-- ...
1027−-- foldl' f z xs == head(n-1) \`f` xn
1028-- @
1032-- @
1029--
1033--
1034+-- The recursive call at the head of the output expression is bound to be
1035+-- evaluated until recursion terminates,
1036+-- /deconstructing the whole input container/ and building the following left
1030−-- Recursively building a left associated expression:
1037+-- associated expression:
1031--
1038--
1032-- @
1039-- @
1033−-- foldl' f z xs == (((z \`f` x1) \`f` x2) ...) \`f` xn
1040+-- foldl f z xs == (((z \`f` x1) \`f` x2) ...) \`f` xn
1034-- @
1041-- @
1035--
1042--
1036−-- When the outermost operation in the fold function is a (left associated)
1043+-- When `f` is a constructor, we can see that the first deconstruction of this
1037−-- constructor, foldl' consumes the whole input to construct the new structure
1044+-- expression would be the recursive expression on the left and `xn` on the
1045+-- right. Therefore, it can access the input elements only in the reverse
1038−-- buffered in memory in the reverse order of the input. For example:
1046+-- (LIFO) order. For example:
1039--
1047--
1040-- @
1048-- @
1041-- > S.foldl' (flip (:)) [] $ S.fromList [1,2,3,4]
1049-- > S.foldl' (flip (:)) [] $ S.fromList [1,2,3,4]
1042-- [4,3,2,1]
1050-- [4,3,2,1]
1043-- @
1051-- @
1044--
1052--
1045−-- When the outermost operation is a function, @foldl'@ results in a left
1053+-- The strict left fold @foldl'@ forces the reduction of its argument @z \`f`
1046−-- associated expression which is incrementally reduced at each step of the
1047−-- fold, thus never building the whole expression in memory. For example:
1054+-- x@ before using it, therefore it never builds the whole expression in
1055+-- memory. Thus, @z \`f` x1@ would get reduced to @z1@ and then @z1 \`f` x2@
1056+-- would get reduced to @z2@ and so on, incrementally reducing the expression
1057+-- as it recurses. However, it evaluates the accumulator only to WHNF, it may
1058+-- further help to use a strict data structure as accumulator. For example:
1048--
1059--
1049-- @
1060-- @
1050-- > S.foldl' (+) 0 $ S.fromList [1,2,3,4]
1061-- > S.foldl' (+) 0 $ S.fromList [1,2,3,4]
@@ -1057,42 +1068,32 @@ foldl = foldx
1057-- ((0 + 1) + 2) + 3
1068-- ((0 + 1) + 2) + 3
1058-- (((0 + 1) + 2) + 3) + 4
1069-- (((0 + 1) + 2) + 3) + 4
1059-- @
1070-- @
1060−-- @
1061−-- 0 + 1 => reduce to 1
1062−-- 1 + 2 => reduce to 3
1063−-- 3 + 3 => reduce to 6
1064−-- 6 + 4 => reduce to 10
1065−-- @
1066--
1071--
1067−-- We can stop recursion and terminate the fold by yielding an expression that
1072+-- @foldl@ strictly deconstructs the whole input container irrespective of
1068−-- is independent of the input element:
1073+-- whether it needs it or not:
1069--
1074--
1070−-- >> S.foldl' (\acc x -> if acc >= 8 then acc else x + acc) 0 $ S.fromList [4,1,3,undefined]
1075+-- >> S.foldl' (\acc x -> if x == 3 then acc else x : acc) [] $ S.fromList (4:1:3:undefined)
1071−-- >8
1076+-- >*** Exception: Prelude.undefined
1072--
1077--
1073−-- To stop on encountering the number 3 we will have to store the previous
1078+-- However, evaluation of the items contained in the input container is lazy as
1074−-- number in the accumulator so that we do not depend on the current input:
1079+-- demanded by the fold step function:
1075--
1080--
1076−-- @
1077−-- > S.foldl' (\(acc, prev) x -> if prev == 3 then (acc,prev) else (x + acc,x))
1081+-- >> S.foldl' (\acc x -> if x == 3 then acc else x : acc) [] $ S.fromList [4,1,3,undefined]
1078−-- (0,0) $ S.fromList \[4,1,3,undefined]
1082+-- >[4,1]
1079−-- (8,3)
1080−-- @
1081--
1083--
1084+-- To perform a left fold without consuming all the input one can use @scanl@
1085+-- to stream the intermediate results of the fold and use them lazily.
1086+--
1082−-- To map the fold operation to stateful or event-driven programming, we can
1087+-- In stateful or event-driven programming, we can consider @z@ as the initial
1083−-- consider @z@ as the initial state and the stream being folded as a stream of
1088+-- state and the stream being folded as a stream of events, thus @foldl'@
1084−-- events, thus @foldl'@ processes all the events in the stream updating the
1089+-- processes all the events in the stream updating the state on each event and
1085−-- state on each event and then ultimately returning the final state.
1090+-- then ultimately returning the final state.
1086--
1091--
1087-- The arguments to the folding function (@b -> a -> b@) are in the head and
1092-- The arguments to the folding function (@b -> a -> b@) are in the head and
1088-- tail order of the output expression, @b@ is the head and @a@ is the tail.
1093-- tail order of the output expression, @b@ is the head and @a@ is the tail.
1089-- Remember, in a left fold the zero is on the left, at the head of the
1094-- Remember, in a left fold the zero is on the left, at the head of the
1090-- expression.
1095-- expression.
1091--
1096--
1092−-- IMPORTANT: 'foldl'' evaluates the accumulator to WHNF. To avoid building
1093−-- lazy expressions inside the accumulator, and to help GHC optimize better, it
1094−-- is recommended that a strict data structure is used for accumulator.
1095−--
1096-- @since 0.2.0
1097-- @since 0.2.0
1097{-# INLINE foldl' #-}
1098{-# INLINE foldl' #-}
1098foldl' :: Monad m => (b -> a -> b) -> b -> SerialT m a -> m b
1099foldl' :: Monad m => (b -> a -> b) -> b -> SerialT m a -> m b
@@ -1443,13 +1444,13 @@ toList = P.toList
1443--
1444--
1444-- @since 0.1.0
1445-- @since 0.1.0
1445toHandle :: MonadIO m => IO.Handle -> SerialT m String -> m ()
1446toHandle :: MonadIO m => IO.Handle -> SerialT m String -> m ()
1446−toHandle h m = go (toStream m)
1447+toHandle h m = go m
1447 where
1448 where
1448 go m1 =
1449 go m1 =
1449 let stop = return ()
1450 let stop = return ()
1450 single a = liftIO (IO.hPutStrLn h a)
1451 single a = liftIO (IO.hPutStrLn h a)
1451 yieldk a r = liftIO (IO.hPutStrLn h a) >> go r
1452 yieldk a r = liftIO (IO.hPutStrLn h a) >> go r
1452− in K.unStream m1 defState stop single yieldk
1453+ in K.foldStream defState yieldk single stop m1
1453
1454
1454------------------------------------------------------------------------------
1455------------------------------------------------------------------------------
1455-- Transformation by Folding (Scans)
1456-- Transformation by Folding (Scans)
@@ -1519,8 +1520,8 @@ scanlM' step begin m = fromStreamD $ D.scanlM' step begin $ toStreamD m
1519-- @
1520-- @
1520--
1521--
1521-- IMPORTANT: 'scanl'' evaluates the accumulator to WHNF. To avoid building
1522-- IMPORTANT: 'scanl'' evaluates the accumulator to WHNF. To avoid building
1522−-- lazy expressions inside the accumulator, and to help GHC optimize better, it
1523+-- lazy expressions inside the accumulator, it is recommended that a strict
1523−-- is recommended that a strict data structure is used for accumulator.
1524+-- data structure is used for accumulator.
1524--
1525--
1525-- @since 0.2.0
1526-- @since 0.2.0
1526{-# INLINE scanl' #-}
1527{-# INLINE scanl' #-}
@@ -1768,14 +1769,14 @@ mapMaybeMSerial f m = fromStreamD $ D.mapMaybeM f $ toStreamD m
1768--
1769--
1769-- @since 0.1.1
1770-- @since 0.1.1
1770reverse :: (IsStream t) => t m a -> t m a
1771reverse :: (IsStream t) => t m a -> t m a
1771−reverse m = fromStream $ go K.nil (toStream m)
1772+reverse m = go K.nil m
1772 where
1773 where
1773− go rev rest = K.Stream $ \st stp sng yld ->
1774+ go rev rest = K.mkStream $ \st yld sng stp ->
1774− let runIt x = K.unStream x (rstState st) stp sng yld
1775+ let runIt x = K.foldStream st yld sng stp x
1775 stop = runIt rev
1776 stop = runIt rev
1776 single a = runIt $ a `K.cons` rev
1777 single a = runIt $ a `K.cons` rev
1777 yieldk a r = runIt $ go (a `K.cons` rev) r
1778 yieldk a r = runIt $ go (a `K.cons` rev) r
1778− in K.unStream rest (rstState st) stop single yieldk
1779+ in K.foldStream st yieldk single stop rest
1779
1780
1780------------------------------------------------------------------------------
1781------------------------------------------------------------------------------
1781-- Transformation by Inserting
1782-- Transformation by Inserting
@@ -1986,10 +1987,10 @@ merge = mergeBy compare
1986-- @since 0.6.0
1987-- @since 0.6.0
1987mergeAsyncBy :: (IsStream t, MonadAsync m)
1988mergeAsyncBy :: (IsStream t, MonadAsync m)
1988 => (a -> a -> Ordering) -> t m a -> t m a -> t m a
1989 => (a -> a -> Ordering) -> t m a -> t m a -> t m a
1989−mergeAsyncBy f m1 m2 = K.fromStream $ K.Stream $ \st stp sng yld -> do
1990+mergeAsyncBy f m1 m2 = K.mkStream $ \st stp sng yld -> do
1990− ma <- mkAsync' (rstState st) m1
1991+ ma <- mkAsync' st m1
1991− mb <- mkAsync' (rstState st) m2
1992+ mb <- mkAsync' st m2
1992− K.unStream (K.toStream (K.mergeBy f ma mb)) (rstState st) stp sng yld
1993+ K.foldStream st stp sng yld (K.mergeBy f ma mb)
1993
1994
1994-- | Like 'mergeByM' but merges concurrently (i.e. both the elements being
1995-- | Like 'mergeByM' but merges concurrently (i.e. both the elements being
1995-- merged are generated concurrently).
1996-- merged are generated concurrently).
@@ -1997,7 +1998,7 @@ mergeAsyncBy f m1 m2 = K.fromStream $ K.Stream $ \st stp sng yld -> do
1997-- @since 0.6.0
1998-- @since 0.6.0
1998mergeAsyncByM :: (IsStream t, MonadAsync m)
1999mergeAsyncByM :: (IsStream t, MonadAsync m)
1999 => (a -> a -> m Ordering) -> t m a -> t m a -> t m a
2000 => (a -> a -> m Ordering) -> t m a -> t m a -> t m a
2000−mergeAsyncByM f m1 m2 = K.fromStream $ K.Stream $ \st stp sng yld -> do
2001+mergeAsyncByM f m1 m2 = K.mkStream $ \st stp sng yld -> do
2001− ma <- mkAsync' (rstState st) m1
2002+ ma <- mkAsync' st m1
2002− mb <- mkAsync' (rstState st) m2
2003+ mb <- mkAsync' st m2
2003− K.unStream (K.toStream (K.mergeByM f ma mb)) (rstState st) stp sng yld
2004+ K.foldStream st stp sng yld (K.mergeByM f ma mb)
src/Streamly/SVar.hs+11−3
@@ -31,7 +31,7 @@ module Streamly.SVar
31 , Limit (..)
31 , Limit (..)
32 , State (streamVar)
32 , State (streamVar)
33 , defState
33 , defState
34− , rstState
34+ , adaptState
35 , getMaxThreads
35 , getMaxThreads
36 , setMaxThreads
36 , setMaxThreads
37 , getMaxBuffer
37 , getMaxBuffer
@@ -433,8 +433,15 @@ defState = State
433-- We can optimize this so that we clear it only if it is a Just value, it
433-- We can optimize this so that we clear it only if it is a Just value, it
434-- results in slightly better perf for zip/zipM but the performance of scan
434-- results in slightly better perf for zip/zipM but the performance of scan
435-- worsens a lot, it does not fuse.
435-- worsens a lot, it does not fuse.
436+--
437+-- XXX This has a side effect of clearing the SVar and yieldLimit, therefore it
438+-- should not be used to convert from the same type to the same type, unless
439+-- you want to clear the SVar. For clearing the SVar you should be using the
440+-- appropriate unStream functions instead.
441+--
442+-- | Adapt the stream state from one type to another.
436−rstState :: State t m a -> State t m b
443+adaptState :: State t m a -> State t m b
437−rstState st = st
444+adaptState st = st
438 { streamVar = Nothing
445 { streamVar = Nothing
439 , _yieldLimit = Nothing
446 , _yieldLimit = Nothing
440 }
447 }
@@ -2009,6 +2016,7 @@ newSVarStats = do
2009 , svarStopTime = stpTime
2016 , svarStopTime = stpTime
2010 }
2017 }
2011
2018
2019+-- XXX remove polymorphism in t, inline f
2012getAheadSVar :: MonadAsync m
2020getAheadSVar :: MonadAsync m
2013 => State t m a
2021 => State t m a
2014 -> ( IORef ([t m a], Int)
2022 -> ( IORef ([t m a], Int)
src/Streamly/Streams/Ahead.hs+60−61
@@ -48,8 +48,8 @@ import Streamly.Streams.SVar (fromSVar)
48import Streamly.Streams.Serial (map)
48import Streamly.Streams.Serial (map)
49import Streamly.SVar
49import Streamly.SVar
50import Streamly.Streams.StreamK
50import Streamly.Streams.StreamK
51− (IsStream(..), Stream(..), unstreamShared, unStreamIsolated,
51+ (IsStream(..), Stream, mkStream, foldStream, foldStreamShared,
52− runStreamSVar)
52+ foldStreamSVar)
53import qualified Streamly.Streams.StreamK as K
53import qualified Streamly.Streams.StreamK as K
54
54
55import Prelude hiding (map)
55import Prelude hiding (map)
@@ -298,9 +298,11 @@ processHeap q heap st sv winfo entry sno stopping = loopHeap sno entry
298 let stop = do
298 let stop = do
299 liftIO (incrementYieldLimit sv)
299 liftIO (incrementYieldLimit sv)
300 nextHeap seqNo
300 nextHeap seqNo
301− runStreamSVar sv r st stop
301+ foldStreamSVar sv st
302− (singleStreamFromHeap seqNo)
303 (yieldStreamFromHeap seqNo)
302 (yieldStreamFromHeap seqNo)
303+ (singleStreamFromHeap seqNo)
304+ stop
305+ r
304 else liftIO $ do
306 else liftIO $ do
305 let ent = Entry seqNo (AheadEntryStream r)
307 let ent = Entry seqNo (AheadEntryStream r)
306 liftIO $ requeueOnHeapTop heap ent seqNo
308 liftIO $ requeueOnHeapTop heap ent seqNo
@@ -348,9 +350,11 @@ processWithoutToken q heap st sv winfo m seqNo = do
348 -- we stop.
350 -- we stop.
349 toHeap AheadEntryNull
351 toHeap AheadEntryNull
350
352
351− runStreamSVar sv m st stop
353+ foldStreamSVar sv st
352− (toHeap . AheadEntryPure)
353 (\a r -> toHeap $ AheadEntryStream $ K.cons a r)
354 (\a r -> toHeap $ AheadEntryStream $ K.cons a r)
355+ (toHeap . AheadEntryPure)
356+ stop
357+ m
354
358
355 where
359 where
356
360
@@ -408,7 +412,7 @@ processWithToken q heap st sv winfo action sno = do
408 liftIO (incrementYieldLimit sv)
412 liftIO (incrementYieldLimit sv)
409 loopWithToken (sno + 1)
413 loopWithToken (sno + 1)
410
414
411− runStreamSVar sv action st stop (singleOutput sno) (yieldOutput sno)
415+ foldStreamSVar sv st (yieldOutput sno) (singleOutput sno) stop action
412
416
413 where
417 where
414
418
@@ -431,9 +435,11 @@ processWithToken q heap st sv winfo action sno = do
431 let stop = do
435 let stop = do
432 liftIO (incrementYieldLimit sv)
436 liftIO (incrementYieldLimit sv)
433 loopWithToken (seqNo + 1)
437 loopWithToken (seqNo + 1)
434− runStreamSVar sv r st stop
438+ foldStreamSVar sv st
435− (singleOutput seqNo)
436 (yieldOutput seqNo)
439 (yieldOutput seqNo)
440+ (singleOutput seqNo)
441+ stop
442+ r
437 else do
443 else do
438 let ent = Entry seqNo (AheadEntryStream r)
444 let ent = Entry seqNo (AheadEntryStream r)
439 liftIO $ requeueOnHeapTop heap ent seqNo
445 liftIO $ requeueOnHeapTop heap ent seqNo
@@ -460,9 +466,11 @@ processWithToken q heap st sv winfo action sno = do
460 let stop = do
466 let stop = do
461 liftIO (incrementYieldLimit sv)
467 liftIO (incrementYieldLimit sv)
462 loopWithToken (seqNo + 1)
468 loopWithToken (seqNo + 1)
463− runStreamSVar sv m st stop
469+ foldStreamSVar sv st
464− (singleOutput seqNo)
465 (yieldOutput seqNo)
470 (yieldOutput seqNo)
471+ (singleOutput seqNo)
472+ stop
473+ m
466 else
474 else
467 -- To avoid a race when another thread puts something
475 -- To avoid a race when another thread puts something
468 -- on the heap and goes away, the consumer will not get
476 -- on the heap and goes away, the consumer will not get
@@ -543,32 +551,38 @@ workLoopAhead q heap st sv winfo = do
543
551
544-- The only difference between forkSVarAsync and this is that we run the left
552-- The only difference between forkSVarAsync and this is that we run the left
545-- computation without a shared SVar.
553-- computation without a shared SVar.
546−forkSVarAhead :: MonadAsync m => Stream m a -> Stream m a -> Stream m a
554+forkSVarAhead :: (IsStream t, MonadAsync m) => t m a -> t m a -> t m a
547−forkSVarAhead m1 m2 = Stream $ \st stp sng yld -> do
555+forkSVarAhead m1 m2 = mkStream $ \st stp sng yld -> do
548− sv <- newAheadVar st (concurrently m1 m2) workLoopAhead
556+ sv <- newAheadVar st (concurrently (toStream m1) (toStream m2))
549− unStream (fromSVar sv) (rstState st) stp sng yld
557+ workLoopAhead
558+ foldStream st stp sng yld (fromSVar sv)
550 where
559 where
551− concurrently ma mb = Stream $ \st stp sng yld -> do
560+ concurrently ma mb = mkStream $ \st stp sng yld -> do
552 liftIO $ enqueue (fromJust $ streamVar st) mb
561 liftIO $ enqueue (fromJust $ streamVar st) mb
553− unStream ma (rstState st) stp sng yld
562+ foldStream st stp sng yld ma
554
563
564+-- | Polymorphic version of the 'Semigroup' operation '<>' of 'AheadT'.
565+-- Merges two streams sequentially but with concurrent lookahead.
566+--
567+-- @since 0.3.0
555−{-# INLINE aheadS #-}
568+{-# INLINE ahead #-}
556−aheadS :: MonadAsync m => Stream m a -> Stream m a -> Stream m a
569+ahead :: (IsStream t, MonadAsync m) => t m a -> t m a -> t m a
557−aheadS m1 m2 = Stream $ \st stp sng yld ->
570+ahead m1 m2 = mkStream $ \st stp sng yld ->
558 case streamVar st of
571 case streamVar st of
559 Just sv | svarStyle sv == AheadVar -> do
572 Just sv | svarStyle sv == AheadVar -> do
560− liftIO $ enqueue sv m2
573+ liftIO $ enqueue sv (toStream m2)
561 -- Always run the left side on a new SVar to avoid complexity in
574 -- Always run the left side on a new SVar to avoid complexity in
562 -- sequencing results. This means the left side cannot further
575 -- sequencing results. This means the left side cannot further
563 -- split into more ahead computations on the same SVar.
576 -- split into more ahead computations on the same SVar.
564− unStream m1 (rstState st) stp sng yld
577+ foldStream st stp sng yld m1
565− _ -> unStream (forkSVarAhead m1 m2) st stp sng yld
578+ _ -> foldStreamShared st stp sng yld (forkSVarAhead m1 m2)
566
579
567-- | XXX we can implement it more efficienty by directly implementing instead
580-- | XXX we can implement it more efficienty by directly implementing instead
568-- of combining streams using ahead.
581-- of combining streams using ahead.
569{-# INLINE consMAhead #-}
582{-# INLINE consMAhead #-}
583+{-# SPECIALIZE consMAhead :: IO a -> AheadT IO a -> AheadT IO a #-}
570−consMAhead :: MonadAsync m => m a -> Stream m a -> Stream m a
584+consMAhead :: MonadAsync m => m a -> AheadT m a -> AheadT m a
571−consMAhead m r = K.yieldM m `aheadS` r
585+consMAhead m r = fromStream $ K.yieldM m `ahead` (toStream r)
572
586
573------------------------------------------------------------------------------
587------------------------------------------------------------------------------
574-- AheadT
588-- AheadT
@@ -636,30 +650,20 @@ aheadly = K.adapt
636instance IsStream AheadT where
650instance IsStream AheadT where
637 toStream = getAheadT
651 toStream = getAheadT
638 fromStream = AheadT
652 fromStream = AheadT
639−
640− {-# INLINE consM #-}
641− {-# SPECIALIZE consM :: IO a -> AheadT IO a -> AheadT IO a #-}
642− consM m r = fromStream $ consMAhead m (toStream r)
653+ consM = consMAhead
643−
654+ (|:) = consMAhead
644− {-# INLINE (|:) #-}
645− {-# SPECIALIZE (|:) :: IO a -> AheadT IO a -> AheadT IO a #-}
646− (|:) = consM
647
655
648------------------------------------------------------------------------------
656------------------------------------------------------------------------------
649-- Semigroup
657-- Semigroup
650------------------------------------------------------------------------------
658------------------------------------------------------------------------------
651
659
652−-- | Polymorphic version of the 'Semigroup' operation '<>' of 'AheadT'.
653−-- Merges two streams sequentially but with concurrent lookahead.
654−--
655−-- @since 0.3.0
656−{-# INLINE ahead #-}
660+{-# INLINE mappendAhead #-}
661+{-# SPECIALIZE mappendAhead :: AheadT IO a -> AheadT IO a -> AheadT IO a #-}
657−ahead :: (IsStream t, MonadAsync m) => t m a -> t m a -> t m a
662+mappendAhead :: MonadAsync m => AheadT m a -> AheadT m a -> AheadT m a
658−ahead m1 m2 = fromStream $ Stream $ \st stp sng yld ->
659− unStream (aheadS (toStream m1) (toStream m2)) st stp sng yld
663+mappendAhead m1 m2 = fromStream $ ahead (toStream m1) (toStream m2)
660
664
661instance MonadAsync m => Semigroup (AheadT m a) where
665instance MonadAsync m => Semigroup (AheadT m a) where
662− (<>) = ahead
666+ (<>) = mappendAhead
663
667
664------------------------------------------------------------------------------
668------------------------------------------------------------------------------
665-- Monoid
669-- Monoid
@@ -673,31 +677,26 @@ instance MonadAsync m => Monoid (AheadT m a) where
673-- Monad
677-- Monad
674------------------------------------------------------------------------------
678------------------------------------------------------------------------------
675
679
676−{-# INLINE aheadbind #-}
680+{-# INLINE bindAhead #-}
677−aheadbind
681+{-# SPECIALIZE bindAhead :: AheadT IO a -> (a -> AheadT IO b) -> AheadT IO b #-}
678− :: MonadAsync m
682+bindAhead :: MonadAsync m => AheadT m a -> (a -> AheadT m b) -> AheadT m b
679− => Stream m a
683+bindAhead m f = fromStream $ K.bindWith ahead (K.adapt m) (\a -> K.adapt $ f a)
680− -> (a -> Stream m b)
681− -> Stream m b
682−aheadbind m f = go m
683− where
684− go (Stream g) =
685− Stream $ \st stp sng yld ->
686− let runShared x = unstreamShared x st stp sng yld
687− runIsolated x = unStreamIsolated x st stp sng yld
688−
689− single a = runIsolated $ f a
690− yieldk a r = runShared $
691− K.isolateStream (f a) `aheadS` go r
692− in g (rstState st) stp single yieldk
693
684
694instance MonadAsync m => Monad (AheadT m) where
685instance MonadAsync m => Monad (AheadT m) where
695 return = pure
686 return = pure
696− (AheadT m) >>= f = AheadT $ aheadbind m (getAheadT . f)
687+ (>>=) = bindAhead
688+
689+{-# INLINE apAhead #-}
690+{-# SPECIALIZE apAhead :: AheadT IO (a -> b) -> AheadT IO a -> AheadT IO b #-}
691+apAhead :: MonadAsync m => AheadT m (a -> b) -> AheadT m a -> AheadT m b
692+apAhead mf m = ap (K.adapt mf) (K.adapt m)
693+
694+instance (Monad m, MonadAsync m) => Applicative (AheadT m) where
695+ pure = AheadT . K.yield
696+ (<*>) = apAhead
697
697
698------------------------------------------------------------------------------
698------------------------------------------------------------------------------
699-- Other instances
699-- Other instances
700------------------------------------------------------------------------------
700------------------------------------------------------------------------------
701
701
702−MONAD_APPLICATIVE_INSTANCE(AheadT,MONADPARALLEL)
703MONAD_COMMON_INSTANCES(AheadT, MONADPARALLEL)
702MONAD_COMMON_INSTANCES(AheadT, MONADPARALLEL)
src/Streamly/Streams/Async.hs+86−63
@@ -57,7 +57,9 @@ import qualified Data.Set as S
57import Streamly.Streams.SVar (fromSVar)
57import Streamly.Streams.SVar (fromSVar)
58import Streamly.Streams.Serial (map)
58import Streamly.Streams.Serial (map)
59import Streamly.SVar
59import Streamly.SVar
60−import Streamly.Streams.StreamK (IsStream(..), Stream(..), adapt, runStreamSVar)
60+import Streamly.Streams.StreamK
61+ (IsStream(..), Stream, mkStream, foldStream, adapt, foldStreamShared,
62+ foldStreamSVar)
61import qualified Streamly.Streams.StreamK as K
63import qualified Streamly.Streams.StreamK as K
62
64
63#include "Instances.hs"
65#include "Instances.hs"
@@ -82,7 +84,7 @@ workLoopLIFO q st sv winfo = run
82 work <- dequeue
84 work <- dequeue
83 case work of
85 case work of
84 Nothing -> liftIO $ sendStop sv winfo
86 Nothing -> liftIO $ sendStop sv winfo
85− Just m -> runStreamSVar sv m st run single yieldk
87+ Just m -> foldStreamSVar sv st yieldk single run m
86
88
87 single a = do
89 single a = do
88 res <- liftIO $ sendYield sv winfo (ChildYield a)
90 res <- liftIO $ sendYield sv winfo (ChildYield a)
@@ -91,7 +93,7 @@ workLoopLIFO q st sv winfo = run
91 yieldk a r = do
93 yieldk a r = do
92 res <- liftIO $ sendYield sv winfo (ChildYield a)
94 res <- liftIO $ sendYield sv winfo (ChildYield a)
93 if res
95 if res
94− then runStreamSVar sv r st run single yieldk
96+ then foldStreamSVar sv st yieldk single run r
95 else liftIO $ do
97 else liftIO $ do
96 enqueueLIFO sv q r
98 enqueueLIFO sv q r
97 sendStop sv winfo
99 sendStop sv winfo
@@ -132,7 +134,7 @@ workLoopLIFOLimited q st sv winfo = run
132 if yieldLimitOk
134 if yieldLimitOk
133 then do
135 then do
134 let stop = liftIO (incrementYieldLimit sv) >> run
136 let stop = liftIO (incrementYieldLimit sv) >> run
135− runStreamSVar sv m st stop single yieldk
137+ foldStreamSVar sv st yieldk single stop m
136 -- Avoid any side effects, undo the yield limit decrement if we
138 -- Avoid any side effects, undo the yield limit decrement if we
137 -- never yielded anything.
139 -- never yielded anything.
138 else liftIO $ do
140 else liftIO $ do
@@ -151,7 +153,7 @@ workLoopLIFOLimited q st sv winfo = run
151 yieldLimitOk <- liftIO $ decrementYieldLimit sv
153 yieldLimitOk <- liftIO $ decrementYieldLimit sv
152 let stop = liftIO (incrementYieldLimit sv) >> run
154 let stop = liftIO (incrementYieldLimit sv) >> run
153 if res && yieldLimitOk
155 if res && yieldLimitOk
154− then runStreamSVar sv r st stop single yieldk
156+ then foldStreamSVar sv st yieldk single stop r
155 else liftIO $ do
157 else liftIO $ do
156 incrementYieldLimit sv
158 incrementYieldLimit sv
157 enqueueLIFO sv q r
159 enqueueLIFO sv q r
@@ -183,7 +185,7 @@ workLoopFIFO q st sv winfo = run
183 work <- liftIO $ tryPopR q
185 work <- liftIO $ tryPopR q
184 case work of
186 case work of
185 Nothing -> liftIO $ sendStop sv winfo
187 Nothing -> liftIO $ sendStop sv winfo
186− Just m -> runStreamSVar sv m st run single yieldk
188+ Just m -> foldStreamSVar sv st yieldk single run m
187
189
188 single a = do
190 single a = do
189 res <- liftIO $ sendYield sv winfo (ChildYield a)
191 res <- liftIO $ sendYield sv winfo (ChildYield a)
@@ -192,7 +194,7 @@ workLoopFIFO q st sv winfo = run
192 yieldk a r = do
194 yieldk a r = do
193 res <- liftIO $ sendYield sv winfo (ChildYield a)
195 res <- liftIO $ sendYield sv winfo (ChildYield a)
194 if res
196 if res
195− then runStreamSVar sv r st run single yieldk
197+ then foldStreamSVar sv st yieldk single run r
196 else liftIO $ do
198 else liftIO $ do
197 enqueueFIFO sv q r
199 enqueueFIFO sv q r
198 sendStop sv winfo
200 sendStop sv winfo
@@ -218,7 +220,7 @@ workLoopFIFOLimited q st sv winfo = run
218 if yieldLimitOk
220 if yieldLimitOk
219 then do
221 then do
220 let stop = liftIO (incrementYieldLimit sv) >> run
222 let stop = liftIO (incrementYieldLimit sv) >> run
221− runStreamSVar sv m st stop single yieldk
223+ foldStreamSVar sv st yieldk single stop m
222 else liftIO $ do
224 else liftIO $ do
223 enqueueFIFO sv q m
225 enqueueFIFO sv q m
224 incrementYieldLimit sv
226 incrementYieldLimit sv
@@ -233,7 +235,7 @@ workLoopFIFOLimited q st sv winfo = run
233 yieldLimitOk <- liftIO $ decrementYieldLimit sv
235 yieldLimitOk <- liftIO $ decrementYieldLimit sv
234 let stop = liftIO (incrementYieldLimit sv) >> run
236 let stop = liftIO (incrementYieldLimit sv) >> run
235 if res && yieldLimitOk
237 if res && yieldLimitOk
236− then runStreamSVar sv r st stop single yieldk
238+ then foldStreamSVar sv st yieldk single stop r
237 else liftIO $ do
239 else liftIO $ do
238 incrementYieldLimit sv
240 incrementYieldLimit sv
239 enqueueFIFO sv q r
241 enqueueFIFO sv q r
@@ -526,36 +528,33 @@ newWAsyncVar st m = do
526-- composition and vice-versa we create a new SVar to isolate the scheduling
528-- composition and vice-versa we create a new SVar to isolate the scheduling
527-- of the two.
529-- of the two.
528
530
529−forkSVarAsync :: MonadAsync m
531+forkSVarAsync :: (IsStream t, MonadAsync m)
530− => SVarStyle -> Stream m a -> Stream m a -> Stream m a
532+ => SVarStyle -> t m a -> t m a -> t m a
531−forkSVarAsync style m1 m2 = Stream $ \st stp sng yld -> do
533+forkSVarAsync style m1 m2 = mkStream $ \st stp sng yld -> do
532 sv <- case style of
534 sv <- case style of
533− AsyncVar -> newAsyncVar st (concurrently m1 m2)
535+ AsyncVar -> newAsyncVar st (concurrently (toStream m1) (toStream m2))
534− WAsyncVar -> newWAsyncVar st (concurrently m1 m2)
536+ WAsyncVar -> newWAsyncVar st (concurrently (toStream m1) (toStream m2))
535 _ -> error "illegal svar type"
537 _ -> error "illegal svar type"
536− unStream (fromSVar sv) (rstState st) stp sng yld
538+ foldStream st stp sng yld $ fromSVar sv
537 where
539 where
538− concurrently ma mb = Stream $ \st stp sng yld -> do
540+ concurrently ma mb = mkStream $ \st stp sng yld -> do
539 liftIO $ enqueue (fromJust $ streamVar st) mb
541 liftIO $ enqueue (fromJust $ streamVar st) mb
540− unStream ma st stp sng yld
542+ foldStreamShared st stp sng yld ma
541
543
542{-# INLINE joinStreamVarAsync #-}
544{-# INLINE joinStreamVarAsync #-}
543−joinStreamVarAsync :: MonadAsync m
545+joinStreamVarAsync :: (IsStream t, MonadAsync m)
544− => SVarStyle -> Stream m a -> Stream m a -> Stream m a
546+ => SVarStyle -> t m a -> t m a -> t m a
545−joinStreamVarAsync style m1 m2 = Stream $ \st stp sng yld ->
547+joinStreamVarAsync style m1 m2 = mkStream $ \st stp sng yld ->
546 case streamVar st of
548 case streamVar st of
547− Just sv | svarStyle sv == style ->
549+ Just sv | svarStyle sv == style -> do
548− liftIO (enqueue sv m2) >> unStream m1 st stp sng yld
550+ liftIO $ enqueue sv (toStream m2)
551+ foldStreamShared st stp sng yld m1
549− _ -> unStream (forkSVarAsync style m1 m2) st stp sng yld
552+ _ -> foldStreamShared st stp sng yld (forkSVarAsync style m1 m2)
550
553
551------------------------------------------------------------------------------
554------------------------------------------------------------------------------
552-- Semigroup and Monoid style compositions for parallel actions
555-- Semigroup and Monoid style compositions for parallel actions
553------------------------------------------------------------------------------
556------------------------------------------------------------------------------
554
557
555−{-# INLINE asyncS #-}
556−asyncS :: MonadAsync m => Stream m a -> Stream m a -> Stream m a
557−asyncS = joinStreamVarAsync AsyncVar
558−
559-- | Polymorphic version of the 'Semigroup' operation '<>' of 'AsyncT'.
558-- | Polymorphic version of the 'Semigroup' operation '<>' of 'AsyncT'.
560-- Merges two streams possibly concurrently, preferring the
559-- Merges two streams possibly concurrently, preferring the
561-- elements from the left one when available.
560-- elements from the left one when available.
@@ -563,9 +562,7 @@ asyncS = joinStreamVarAsync AsyncVar
563-- @since 0.2.0
562-- @since 0.2.0
564{-# INLINE async #-}
563{-# INLINE async #-}
565async :: (IsStream t, MonadAsync m) => t m a -> t m a -> t m a
564async :: (IsStream t, MonadAsync m) => t m a -> t m a -> t m a
566−async m1 m2 = fromStream $ Stream $ \st stp sng yld ->
567− unStream (joinStreamVarAsync AsyncVar (toStream m1) (toStream m2))
565+async = joinStreamVarAsync AsyncVar
568− st stp sng yld
569
566
570-- | Same as 'async'.
567-- | Same as 'async'.
571--
568--
@@ -575,11 +572,16 @@ async m1 m2 = fromStream $ Stream $ \st stp sng yld ->
575(<|) :: (IsStream t, MonadAsync m) => t m a -> t m a -> t m a
572(<|) :: (IsStream t, MonadAsync m) => t m a -> t m a -> t m a
576(<|) = async
573(<|) = async
577
574
575+-- IMPORTANT: using a monomorphically typed and SPECIALIZED consMAsync makes a
576+-- huge difference in the performance of consM in IsStream instance even we
577+-- have a SPECIALIZE in the instance.
578+--
578-- | XXX we can implement it more efficienty by directly implementing instead
579-- | XXX we can implement it more efficienty by directly implementing instead
579-- of combining streams using async.
580-- of combining streams using async.
580{-# INLINE consMAsync #-}
581{-# INLINE consMAsync #-}
582+{-# SPECIALIZE consMAsync :: IO a -> AsyncT IO a -> AsyncT IO a #-}
581−consMAsync :: MonadAsync m => m a -> Stream m a -> Stream m a
583+consMAsync :: MonadAsync m => m a -> AsyncT m a -> AsyncT m a
582−consMAsync m r = K.yieldM m `asyncS` r
584+consMAsync m r = fromStream $ K.yieldM m `async` (toStream r)
583
585
584------------------------------------------------------------------------------
586------------------------------------------------------------------------------
585-- AsyncT
587-- AsyncT
@@ -652,21 +654,22 @@ asyncly = adapt
652instance IsStream AsyncT where
654instance IsStream AsyncT where
653 toStream = getAsyncT
655 toStream = getAsyncT
654 fromStream = AsyncT
656 fromStream = AsyncT
655−
656− {-# INLINE consM #-}
657− {-# SPECIALIZE consM :: IO a -> AsyncT IO a -> AsyncT IO a #-}
658− consM m r = fromStream $ consMAsync m (toStream r)
657+ consM = consMAsync
659−
658+ (|:) = consMAsync
660− {-# INLINE (|:) #-}
661− {-# SPECIALIZE (|:) :: IO a -> AsyncT IO a -> AsyncT IO a #-}
662− (|:) = consM
663
659
664------------------------------------------------------------------------------
660------------------------------------------------------------------------------
665-- Semigroup
661-- Semigroup
666------------------------------------------------------------------------------
662------------------------------------------------------------------------------
667
663
664+-- Monomorphically typed version of "async" for better performance of Semigroup
665+-- instance.
666+{-# INLINE mappendAsync #-}
667+{-# SPECIALIZE mappendAsync :: AsyncT IO a -> AsyncT IO a -> AsyncT IO a #-}
668+mappendAsync :: MonadAsync m => AsyncT m a -> AsyncT m a -> AsyncT m a
669+mappendAsync m1 m2 = fromStream $ async (toStream m1) (toStream m2)
670+
668instance MonadAsync m => Semigroup (AsyncT m a) where
671instance MonadAsync m => Semigroup (AsyncT m a) where
669− (<>) = async
672+ (<>) = mappendAsync
670
673
671------------------------------------------------------------------------------
674------------------------------------------------------------------------------
672-- Monoid
675-- Monoid
@@ -680,30 +683,40 @@ instance MonadAsync m => Monoid (AsyncT m a) where
680-- Monad
683-- Monad
681------------------------------------------------------------------------------
684------------------------------------------------------------------------------
682
685
686+{-# INLINE bindAsync #-}
687+{-# SPECIALIZE bindAsync :: AsyncT IO a -> (a -> AsyncT IO b) -> AsyncT IO b #-}
688+bindAsync :: MonadAsync m => AsyncT m a -> (a -> AsyncT m b) -> AsyncT m b
689+bindAsync m f = fromStream $ K.bindWith async (adapt m) (\a -> adapt $ f a)
690+
683instance MonadAsync m => Monad (AsyncT m) where
691instance MonadAsync m => Monad (AsyncT m) where
684 return = pure
692 return = pure
685− (AsyncT m) >>= f = AsyncT $ K.bindWith asyncS m (getAsyncT . f)
693+ (>>=) = bindAsync
694+
695+{-# INLINE apAsync #-}
696+{-# SPECIALIZE apAsync :: AsyncT IO (a -> b) -> AsyncT IO a -> AsyncT IO b #-}
697+apAsync :: MonadAsync m => AsyncT m (a -> b) -> AsyncT m a -> AsyncT m b
698+apAsync mf m = ap (adapt mf) (adapt m)
699+
700+instance (Monad m, MonadAsync m) => Applicative (AsyncT m) where
701+ pure = AsyncT . K.yield
702+ (<*>) = apAsync
686
703
687------------------------------------------------------------------------------
704------------------------------------------------------------------------------
688-- Other instances
705-- Other instances
689------------------------------------------------------------------------------
706------------------------------------------------------------------------------
690
707
691−MONAD_APPLICATIVE_INSTANCE(AsyncT,MONADPARALLEL)
692MONAD_COMMON_INSTANCES(AsyncT, MONADPARALLEL)
708MONAD_COMMON_INSTANCES(AsyncT, MONADPARALLEL)
693
709
694------------------------------------------------------------------------------
710------------------------------------------------------------------------------
695-- WAsyncT
711-- WAsyncT
696------------------------------------------------------------------------------
712------------------------------------------------------------------------------
697
713
698−{-# INLINE wAsyncS #-}
699−wAsyncS :: MonadAsync m => Stream m a -> Stream m a -> Stream m a
700−wAsyncS = joinStreamVarAsync WAsyncVar
701−
702-- | XXX we can implement it more efficienty by directly implementing instead
714-- | XXX we can implement it more efficienty by directly implementing instead
703-- of combining streams using wAsync.
715-- of combining streams using wAsync.
704{-# INLINE consMWAsync #-}
716{-# INLINE consMWAsync #-}
717+{-# SPECIALIZE consMWAsync :: IO a -> WAsyncT IO a -> WAsyncT IO a #-}
705−consMWAsync :: MonadAsync m => m a -> Stream m a -> Stream m a
718+consMWAsync :: MonadAsync m => m a -> WAsyncT m a -> WAsyncT m a
706−consMWAsync m r = K.yieldM m `wAsyncS` r
719+consMWAsync m r = fromStream $ K.yieldM m `wAsync` (toStream r)
707
720
708-- | Polymorphic version of the 'Semigroup' operation '<>' of 'WAsyncT'.
721-- | Polymorphic version of the 'Semigroup' operation '<>' of 'WAsyncT'.
709-- Merges two streams concurrently choosing elements from both fairly.
722-- Merges two streams concurrently choosing elements from both fairly.
@@ -711,8 +724,7 @@ consMWAsync m r = K.yieldM m `wAsyncS` r
711-- @since 0.2.0
724-- @since 0.2.0
712{-# INLINE wAsync #-}
725{-# INLINE wAsync #-}
713wAsync :: (IsStream t, MonadAsync m) => t m a -> t m a -> t m a
726wAsync :: (IsStream t, MonadAsync m) => t m a -> t m a -> t m a
714−wAsync m1 m2 = fromStream $ Stream $ \st stp sng yld ->
727+wAsync = joinStreamVarAsync WAsyncVar
715− unStream (wAsyncS (toStream m1) (toStream m2)) st stp sng yld
716
728
717-- | Wide async composition or async composition with breadth first traversal.
729-- | Wide async composition or async composition with breadth first traversal.
718-- The Semigroup instance of 'WAsyncT' concurrently /traverses/ the composed
730-- The Semigroup instance of 'WAsyncT' concurrently /traverses/ the composed
@@ -779,21 +791,20 @@ wAsyncly = adapt
779instance IsStream WAsyncT where
791instance IsStream WAsyncT where
780 toStream = getWAsyncT
792 toStream = getWAsyncT
781 fromStream = WAsyncT
793 fromStream = WAsyncT
782−
783− {-# INLINE consM #-}
784− {-# SPECIALIZE consM :: IO a -> WAsyncT IO a -> WAsyncT IO a #-}
785− consM m r = fromStream $ consMWAsync m (toStream r)
794+ consM = consMWAsync
786−
795+ (|:) = consMWAsync
787− {-# INLINE (|:) #-}
788− {-# SPECIALIZE (|:) :: IO a -> WAsyncT IO a -> WAsyncT IO a #-}
789− (|:) = consM
790
796
791------------------------------------------------------------------------------
797------------------------------------------------------------------------------
792-- Semigroup
798-- Semigroup
793------------------------------------------------------------------------------
799------------------------------------------------------------------------------
794
800
801+{-# INLINE mappendWAsync #-}
802+{-# SPECIALIZE mappendWAsync :: WAsyncT IO a -> WAsyncT IO a -> WAsyncT IO a #-}
803+mappendWAsync :: MonadAsync m => WAsyncT m a -> WAsyncT m a -> WAsyncT m a
804+mappendWAsync m1 m2 = fromStream $ wAsync (toStream m1) (toStream m2)
805+
795instance MonadAsync m => Semigroup (WAsyncT m a) where
806instance MonadAsync m => Semigroup (WAsyncT m a) where
796− (<>) = wAsync
807+ (<>) = mappendWAsync
797
808
798------------------------------------------------------------------------------
809------------------------------------------------------------------------------
799-- Monoid
810-- Monoid
@@ -807,14 +818,26 @@ instance MonadAsync m => Monoid (WAsyncT m a) where
807-- Monad
818-- Monad
808------------------------------------------------------------------------------
819------------------------------------------------------------------------------
809
820
821+{-# INLINE bindWAsync #-}
822+{-# SPECIALIZE bindWAsync :: WAsyncT IO a -> (a -> WAsyncT IO b) -> WAsyncT IO b #-}
823+bindWAsync :: MonadAsync m => WAsyncT m a -> (a -> WAsyncT m b) -> WAsyncT m b
824+bindWAsync m f = fromStream $ K.bindWith wAsync (adapt m) (\a -> adapt $ f a)
825+
810instance MonadAsync m => Monad (WAsyncT m) where
826instance MonadAsync m => Monad (WAsyncT m) where
811 return = pure
827 return = pure
812− (WAsyncT m) >>= f =
828+ (>>=) = bindWAsync
813− WAsyncT $ K.bindWith wAsyncS m (getWAsyncT . f)
829+
830+{-# INLINE apWAsync #-}
831+{-# SPECIALIZE apWAsync :: WAsyncT IO (a -> b) -> WAsyncT IO a -> WAsyncT IO b #-}
832+apWAsync :: MonadAsync m => WAsyncT m (a -> b) -> WAsyncT m a -> WAsyncT m b
833+apWAsync mf m = ap (adapt mf) (adapt m)
834+
835+instance (Monad m, MonadAsync m) => Applicative (WAsyncT m) where
836+ pure = WAsyncT . K.yield
837+ (<*>) = apWAsync
814
838
815------------------------------------------------------------------------------
839------------------------------------------------------------------------------
816-- Other instances
840-- Other instances
817------------------------------------------------------------------------------
841------------------------------------------------------------------------------
818
842
819−MONAD_APPLICATIVE_INSTANCE(WAsyncT,MONADPARALLEL)
820MONAD_COMMON_INSTANCES(WAsyncT, MONADPARALLEL)
843MONAD_COMMON_INSTANCES(WAsyncT, MONADPARALLEL)
src/Streamly/Streams/Combinators.hs+12−12
@@ -52,8 +52,8 @@ import Streamly.Streams.Serial (SerialT)
52-- @since 0.4.0
52-- @since 0.4.0
53{-# INLINE_NORMAL maxThreads #-}
53{-# INLINE_NORMAL maxThreads #-}
54maxThreads :: IsStream t => Int -> t m a -> t m a
54maxThreads :: IsStream t => Int -> t m a -> t m a
55−maxThreads n m = fromStream $ Stream $ \st stp sng yld ->
55+maxThreads n m = mkStream $ \st stp sng yld ->
56− unStream (toStream m) (setMaxThreads n st) stp sng yld
56+ foldStreamShared (setMaxThreads n st) stp sng yld m
57
57
58{-
58{-
59{-# RULES "maxThreadsSerial serial" maxThreads = maxThreadsSerial #-}
59{-# RULES "maxThreadsSerial serial" maxThreads = maxThreadsSerial #-}
@@ -77,8 +77,8 @@ maxThreadsSerial _ = id
77-- @since 0.4.0
77-- @since 0.4.0
78{-# INLINE_NORMAL maxBuffer #-}
78{-# INLINE_NORMAL maxBuffer #-}
79maxBuffer :: IsStream t => Int -> t m a -> t m a
79maxBuffer :: IsStream t => Int -> t m a -> t m a
80−maxBuffer n m = fromStream $ Stream $ \st stp sng yld ->
80+maxBuffer n m = mkStream $ \st stp sng yld ->
81− unStream (toStream m) (setMaxBuffer n st) stp sng yld
81+ foldStreamShared (setMaxBuffer n st) stp sng yld m
82
82
83{-
83{-
84{-# RULES "maxBuffer serial" maxBuffer = maxBufferSerial #-}
84{-# RULES "maxBuffer serial" maxBuffer = maxBufferSerial #-}
@@ -101,7 +101,7 @@ maxBufferSerial _ = id
101-- @since 0.5.0
101-- @since 0.5.0
102{-# INLINE_NORMAL rate #-}
102{-# INLINE_NORMAL rate #-}
103rate :: IsStream t => Maybe Rate -> t m a -> t m a
103rate :: IsStream t => Maybe Rate -> t m a -> t m a
104−rate r m = fromStream $ Stream $ \st stp sng yld ->
104+rate r m = mkStream $ \st stp sng yld ->
105 case r of
105 case r of
106 Just (Rate low goal _ _) | goal < low ->
106 Just (Rate low goal _ _) | goal < low ->
107 error "rate: Target rate cannot be lower than minimum rate."
107 error "rate: Target rate cannot be lower than minimum rate."
@@ -109,7 +109,7 @@ rate r m = fromStream $ Stream $ \st stp sng yld ->
109 error "rate: Target rate cannot be greater than maximum rate."
109 error "rate: Target rate cannot be greater than maximum rate."
110 Just (Rate low _ high _) | low > high ->
110 Just (Rate low _ high _) | low > high ->
111 error "rate: Minimum rate cannot be greater than maximum rate."
111 error "rate: Minimum rate cannot be greater than maximum rate."
112− _ -> unStream (toStream m) (setStreamRate r st) stp sng yld
112+ _ -> foldStreamShared (setStreamRate r st) stp sng yld m
113
113
114-- XXX implement for serial streams as well, as a simple delay
114-- XXX implement for serial streams as well, as a simple delay
115
115
@@ -181,8 +181,8 @@ constRate r = rate (Just $ Rate r r r 0)
181--
181--
182{-# INLINE_NORMAL _serialLatency #-}
182{-# INLINE_NORMAL _serialLatency #-}
183_serialLatency :: IsStream t => Int -> t m a -> t m a
183_serialLatency :: IsStream t => Int -> t m a -> t m a
184−_serialLatency n m = fromStream $ Stream $ \st stp sng yld ->
184+_serialLatency n m = mkStream $ \st stp sng yld ->
185− unStream (toStream m) (setStreamLatency n st) stp sng yld
185+ foldStreamShared (setStreamLatency n st) stp sng yld m
186
186
187{-
187{-
188{-# RULES "serialLatency serial" _serialLatency = serialLatencySerial #-}
188{-# RULES "serialLatency serial" _serialLatency = serialLatencySerial #-}
@@ -196,8 +196,8 @@ serialLatencySerial _ = id
196-- inherited by everything in enclosed scope.
196-- inherited by everything in enclosed scope.
197{-# INLINE_NORMAL maxYields #-}
197{-# INLINE_NORMAL maxYields #-}
198maxYields :: IsStream t => Maybe Int64 -> t m a -> t m a
198maxYields :: IsStream t => Maybe Int64 -> t m a -> t m a
199−maxYields n m = fromStream $ Stream $ \st stp sng yld ->
199+maxYields n m = mkStream $ \st stp sng yld ->
200− unStream (toStream m) (setYieldLimit n st) stp sng yld
200+ foldStreamShared (setYieldLimit n st) stp sng yld m
201
201
202{-# RULES "maxYields serial" maxYields = maxYieldsSerial #-}
202{-# RULES "maxYields serial" maxYields = maxYieldsSerial #-}
203maxYieldsSerial :: Maybe Int64 -> SerialT m a -> SerialT m a
203maxYieldsSerial :: Maybe Int64 -> SerialT m a -> SerialT m a
@@ -212,5 +212,5 @@ printState st = liftIO $ do
212
212
213-- | Print debug information about an SVar when the stream ends
213-- | Print debug information about an SVar when the stream ends
214inspectMode :: IsStream t => t m a -> t m a
214inspectMode :: IsStream t => t m a -> t m a
215−inspectMode m = fromStream $ Stream $ \st stp sng yld ->
215+inspectMode m = mkStream $ \st stp sng yld ->
216− unStream (toStream m) (setInspectMode st) stp sng yld
216+ foldStreamShared (setInspectMode st) stp sng yld m
src/Streamly/Streams/Parallel.hs+36−29
@@ -49,7 +49,8 @@ import Prelude hiding (map)
49import Streamly.Streams.SVar (fromSVar)
49import Streamly.Streams.SVar (fromSVar)
50import Streamly.Streams.Serial (map)
50import Streamly.Streams.Serial (map)
51import Streamly.SVar
51import Streamly.SVar
52−import Streamly.Streams.StreamK (IsStream(..), Stream(..), adapt)
52+import Streamly.Streams.StreamK (IsStream(..), Stream, mkStream, foldStream,
53+ foldStreamShared, adapt)
53import qualified Streamly.Streams.StreamK as K
54import qualified Streamly.Streams.StreamK as K
54
55
55#include "Instances.hs"
56#include "Instances.hs"
@@ -62,7 +63,7 @@ import qualified Streamly.Streams.StreamK as K
62runOne
63runOne
63 :: MonadIO m
64 :: MonadIO m
64 => State Stream m a -> Stream m a -> Maybe WorkerInfo -> m ()
65 => State Stream m a -> Stream m a -> Maybe WorkerInfo -> m ()
65−runOne st m winfo = unStream m st stop single yieldk
66+runOne st m winfo = foldStreamShared st yieldk single stop m
66
67
67 where
68 where
68
69
@@ -87,32 +88,29 @@ runOne st m winfo = unStream m st stop single yieldk
87 >> withLimitCheck (void $ liftIO $ mrun $ runOne st r winfo)
88 >> withLimitCheck (void $ liftIO $ mrun $ runOne st r winfo)
88
89
89{-# NOINLINE forkSVarPar #-}
90{-# NOINLINE forkSVarPar #-}
90−forkSVarPar :: MonadAsync m => Stream m a -> Stream m a -> Stream m a
91+forkSVarPar :: (IsStream t, MonadAsync m) => t m a -> t m a -> t m a
91−forkSVarPar m r = Stream $ \st stp sng yld -> do
92+forkSVarPar m r = mkStream $ \st yld sng stp -> do
92 sv <- newParallelVar st
93 sv <- newParallelVar st
93− pushWorkerPar sv (runOne st{streamVar = Just sv} m)
94+ pushWorkerPar sv (runOne st{streamVar = Just sv} $ toStream m)
94− pushWorkerPar sv (runOne st{streamVar = Just sv} r)
95+ pushWorkerPar sv (runOne st{streamVar = Just sv} $ toStream r)
95− unStream (fromSVar sv) (rstState st) stp sng yld
96+ foldStream st yld sng stp (fromSVar sv)
96
97
97{-# INLINE joinStreamVarPar #-}
98{-# INLINE joinStreamVarPar #-}
98−joinStreamVarPar :: MonadAsync m
99+joinStreamVarPar :: (IsStream t, MonadAsync m)
99− => SVarStyle -> Stream m a -> Stream m a -> Stream m a
100+ => SVarStyle -> t m a -> t m a -> t m a
100−joinStreamVarPar style m1 m2 = Stream $ \st stp sng yld ->
101+joinStreamVarPar style m1 m2 = mkStream $ \st yld sng stp ->
101 case streamVar st of
102 case streamVar st of
102 Just sv | svarStyle sv == style -> do
103 Just sv | svarStyle sv == style -> do
103− pushWorkerPar sv (runOne st m1)
104+ pushWorkerPar sv (runOne st $ toStream m1)
104− unStream m2 st stp sng yld
105+ foldStreamShared st yld sng stp m2
105− _ -> unStream (forkSVarPar m1 m2) st stp sng yld
106+ _ -> foldStreamShared st yld sng stp (forkSVarPar m1 m2)
106−
107−{-# INLINE parallelStream #-}
108−parallelStream :: MonadAsync m => Stream m a -> Stream m a -> Stream m a
109−parallelStream = joinStreamVarPar ParallelVar
110
107
111-- | XXX we can implement it more efficienty by directly implementing instead
108-- | XXX we can implement it more efficienty by directly implementing instead
112-- of combining streams using parallel.
109-- of combining streams using parallel.
113{-# INLINE consMParallel #-}
110{-# INLINE consMParallel #-}
111+{-# SPECIALIZE consMParallel :: IO a -> ParallelT IO a -> ParallelT IO a #-}
114−consMParallel :: MonadAsync m => m a -> Stream m a -> Stream m a
112+consMParallel :: MonadAsync m => m a -> ParallelT m a -> ParallelT m a
115−consMParallel m r = K.yieldM m `parallelStream` r
113+consMParallel m r = fromStream $ K.yieldM m `parallel` (toStream r)
116
114
117-- | Polymorphic version of the 'Semigroup' operation '<>' of 'ParallelT'
115-- | Polymorphic version of the 'Semigroup' operation '<>' of 'ParallelT'
118-- Merges two streams concurrently.
116-- Merges two streams concurrently.
@@ -120,9 +118,7 @@ consMParallel m r = K.yieldM m `parallelStream` r
120-- @since 0.2.0
118-- @since 0.2.0
121{-# INLINE parallel #-}
119{-# INLINE parallel #-}
122parallel :: (IsStream t, MonadAsync m) => t m a -> t m a -> t m a
120parallel :: (IsStream t, MonadAsync m) => t m a -> t m a -> t m a
123−parallel m1 m2 = fromStream $ Stream $ \st stp sng yld ->
121+parallel = joinStreamVarPar ParallelVar
124− unStream (parallelStream (toStream m1) (toStream m2))
125− st stp sng yld
126
122
127------------------------------------------------------------------------------
123------------------------------------------------------------------------------
128-- Convert a stream to parallel
124-- Convert a stream to parallel
@@ -140,10 +136,10 @@ mkParallel m = do
140
136
141{-# INLINE applyWith #-}
137{-# INLINE applyWith #-}
142applyWith :: (IsStream t, MonadAsync m) => (t m a -> t m b) -> t m a -> t m b
138applyWith :: (IsStream t, MonadAsync m) => (t m a -> t m b) -> t m a -> t m b
143−applyWith f m = fromStream $ Stream $ \st stp sng yld -> do
139+applyWith f m = mkStream $ \st yld sng stp -> do
144− sv <- newParallelVar (rstState st)
140+ sv <- newParallelVar (adaptState st)
145 pushWorkerPar sv (runOne st{streamVar = Just sv} (toStream m))
141 pushWorkerPar sv (runOne st{streamVar = Just sv} (toStream m))
146− unStream (toStream $ f $ fromSVar sv) (rstState st) stp sng yld
142+ foldStream st yld sng stp $ f $ fromSVar sv
147
143
148------------------------------------------------------------------------------
144------------------------------------------------------------------------------
149-- Stream runner concurrent function application
145-- Stream runner concurrent function application
@@ -345,7 +341,7 @@ instance IsStream ParallelT where
345
341
346 {-# INLINE consM #-}
342 {-# INLINE consM #-}
347 {-# SPECIALIZE consM :: IO a -> ParallelT IO a -> ParallelT IO a #-}
343 {-# SPECIALIZE consM :: IO a -> ParallelT IO a -> ParallelT IO a #-}
348− consM m r = fromStream $ consMParallel m (toStream r)
344+ consM = consMParallel
349
345
350 {-# INLINE (|:) #-}
346 {-# INLINE (|:) #-}
351 {-# SPECIALIZE (|:) :: IO a -> ParallelT IO a -> ParallelT IO a #-}
347 {-# SPECIALIZE (|:) :: IO a -> ParallelT IO a -> ParallelT IO a #-}
@@ -355,8 +351,13 @@ instance IsStream ParallelT where
355-- Semigroup
351-- Semigroup
356------------------------------------------------------------------------------
352------------------------------------------------------------------------------
357
353
354+{-# INLINE mappendParallel #-}
355+{-# SPECIALIZE mappendParallel :: ParallelT IO a -> ParallelT IO a -> ParallelT IO a #-}
356+mappendParallel :: MonadAsync m => ParallelT m a -> ParallelT m a -> ParallelT m a
357+mappendParallel m1 m2 = fromStream $ parallel (toStream m1) (toStream m2)
358+
358instance MonadAsync m => Semigroup (ParallelT m a) where
359instance MonadAsync m => Semigroup (ParallelT m a) where
359− (<>) = parallel
360+ (<>) = mappendParallel
360
361
361------------------------------------------------------------------------------
362------------------------------------------------------------------------------
362-- Monoid
363-- Monoid
@@ -370,10 +371,16 @@ instance MonadAsync m => Monoid (ParallelT m a) where
370-- Monad
371-- Monad
371------------------------------------------------------------------------------
372------------------------------------------------------------------------------
372
373
374+{-# INLINE bindParallel #-}
375+{-# SPECIALIZE bindParallel :: ParallelT IO a -> (a -> ParallelT IO b) -> ParallelT IO b #-}
376+bindParallel :: MonadAsync m => ParallelT m a -> (a -> ParallelT m b) -> ParallelT m b
377+bindParallel m f = fromStream $ K.bindWith parallel (K.adapt m) (\a -> K.adapt $ f a)
378+
373instance MonadAsync m => Monad (ParallelT m) where
379instance MonadAsync m => Monad (ParallelT m) where
374 return = pure
380 return = pure
375− (ParallelT m) >>= f
381+ (>>=) = bindParallel
376− = ParallelT $ K.bindWith parallelStream m (getParallelT . f)
382+
383+-- XXX Specialize the applicative instance
377
384
378------------------------------------------------------------------------------
385------------------------------------------------------------------------------
379-- Other instances
386-- Other instances
src/Streamly/Streams/SVar.hs+10−9
@@ -38,12 +38,12 @@ printSVar sv how = do
38-- | Pull a stream from an SVar.
38-- | Pull a stream from an SVar.
39{-# NOINLINE fromStreamVar #-}
39{-# NOINLINE fromStreamVar #-}
40fromStreamVar :: MonadAsync m => SVar Stream m a -> Stream m a
40fromStreamVar :: MonadAsync m => SVar Stream m a -> Stream m a
41−fromStreamVar sv = Stream $ \st stp sng yld -> do
41+fromStreamVar sv = mkStream $ \st yld sng stp -> do
42 list <- readOutputQ sv
42 list <- readOutputQ sv
43 -- Reversing the output is important to guarantee that we process the
43 -- Reversing the output is important to guarantee that we process the
44 -- outputs in the same order as they were generated by the constituent
44 -- outputs in the same order as they were generated by the constituent
45 -- streams.
45 -- streams.
46− unStream (processEvents $ reverse list) (rstState st) stp sng yld
46+ foldStream st yld sng stp $ processEvents $ reverse list
47
47
48 where
48 where
49
49
@@ -55,36 +55,37 @@ fromStreamVar sv = Stream $ \st stp sng yld -> do
55 stp
55 stp
56
56
57 {-# INLINE processEvents #-}
57 {-# INLINE processEvents #-}
58− processEvents [] = Stream $ \st stp sng yld -> do
58+ processEvents [] = mkStream $ \st yld sng stp -> do
59 done <- postProcess sv
59 done <- postProcess sv
60 if done
60 if done
61 then allDone stp
61 then allDone stp
62− else unStream (fromStreamVar sv) (rstState st) stp sng yld
62+ else foldStream st yld sng stp $ fromStreamVar sv
63
63
64− processEvents (ev : es) = Stream $ \st stp sng yld -> do
64+ processEvents (ev : es) = mkStream $ \st yld sng stp -> do
65 let rest = processEvents es
65 let rest = processEvents es
66 case ev of
66 case ev of
67 ChildYield a -> yld a rest
67 ChildYield a -> yld a rest
68 ChildStop tid e -> do
68 ChildStop tid e -> do
69 accountThread sv tid
69 accountThread sv tid
70 case e of
70 case e of
71− Nothing -> unStream rest (rstState st) stp sng yld
71+ Nothing -> foldStream st yld sng stp rest
72 Just ex ->
72 Just ex ->
73 case fromException ex of
73 case fromException ex of
74 Just ThreadAbort ->
74 Just ThreadAbort ->
75− unStream rest (rstState st) stp sng yld
75+ foldStream st yld sng stp rest
76 Nothing -> liftIO (cleanupSVar sv) >> throwM ex
76 Nothing -> liftIO (cleanupSVar sv) >> throwM ex
77
77
78{-# INLINE fromSVar #-}
78{-# INLINE fromSVar #-}
79fromSVar :: (MonadAsync m, IsStream t) => SVar Stream m a -> t m a
79fromSVar :: (MonadAsync m, IsStream t) => SVar Stream m a -> t m a
80fromSVar sv =
80fromSVar sv =
81− fromStream $ Stream $ \st stp sng yld -> do
81+ mkStream $ \st yld sng stp -> do
82 ref <- liftIO $ newIORef ()
82 ref <- liftIO $ newIORef ()
83 _ <- liftIO $ mkWeakIORef ref hook
83 _ <- liftIO $ mkWeakIORef ref hook
84 -- We pass a copy of sv to fromStreamVar, so that we know that it has
84 -- We pass a copy of sv to fromStreamVar, so that we know that it has
85 -- no other references, when that copy gets garbage collected "ref"
85 -- no other references, when that copy gets garbage collected "ref"
86 -- will get garbage collected and our hook will be called.
86 -- will get garbage collected and our hook will be called.
87+ foldStreamShared st yld sng stp $
87− unStream (fromStreamVar sv{svarRef = Just ref}) st stp sng yld
88+ fromStream $ fromStreamVar sv{svarRef = Just ref}
88 where
89 where
89
90
90 hook = do
91 hook = do
src/Streamly/Streams/Serial.hs+22−51
@@ -24,7 +24,7 @@ module Streamly.Streams.Serial
24 SerialT
24 SerialT
25 , StreamT -- deprecated
25 , StreamT -- deprecated
26 , Serial
26 , Serial
27− , serial
27+ , K.serial
28 , serially
28 , serially
29
29
30 -- * Serial interleaving stream
30 -- * Serial interleaving stream
@@ -60,8 +60,8 @@ import Text.Read (Lexeme(Ident), lexP, parens, prec, readPrec, readListPrec,
60 readListPrecDefault)
60 readListPrecDefault)
61import Prelude hiding (map, mapM)
61import Prelude hiding (map, mapM)
62
62
63−import Streamly.SVar (rstState)
64−import Streamly.Streams.StreamK (IsStream(..), adapt, Stream(..))
63+import Streamly.Streams.StreamK (IsStream(..), adapt, Stream, mkStream,
64+ foldStream)
65import qualified Streamly.Streams.Prelude as P
65import qualified Streamly.Streams.Prelude as P
66import qualified Streamly.Streams.StreamK as K
66import qualified Streamly.Streams.StreamK as K
67import qualified Streamly.Streams.StreamD as D
67import qualified Streamly.Streams.StreamD as D
@@ -149,34 +149,16 @@ type StreamT = SerialT
149serially :: IsStream t => SerialT m a -> t m a
149serially :: IsStream t => SerialT m a -> t m a
150serially = adapt
150serially = adapt
151
151
152+{-# INLINE consMSerial #-}
153+{-# SPECIALIZE consMSerial :: IO a -> SerialT IO a -> SerialT IO a #-}
154+consMSerial :: Monad m => m a -> SerialT m a -> SerialT m a
155+consMSerial m ms = fromStream $ K.consMStream m (toStream ms)
156+
152instance IsStream SerialT where
157instance IsStream SerialT where
153 toStream = getSerialT
158 toStream = getSerialT
154 fromStream = SerialT
159 fromStream = SerialT
155−
156− {-# INLINE consM #-}
157− {-# SPECIALIZE consM :: IO a -> SerialT IO a -> SerialT IO a #-}
158− consM :: Monad m => m a -> SerialT m a -> SerialT m a
159− consM m r = fromStream $ K.consMSerial m (toStream r)
160+ consM = consMSerial
160−
161− {-# INLINE (|:) #-}
162− {-# SPECIALIZE (|:) :: IO a -> SerialT IO a -> SerialT IO a #-}
163− (|:) :: Monad m => m a -> SerialT m a -> SerialT m a
164− m |: r = fromStream $ K.consMSerial m (toStream r)
161+ (|:) = consMSerial
165−
166−------------------------------------------------------------------------------
167−-- Semigroup
168−------------------------------------------------------------------------------
169−
170−-- | Polymorphic version of the 'Semigroup' operation '<>' of 'SerialT'.
171−-- Appends two streams sequentially, yielding all elements from the first
172−-- stream, and then all elements from the second stream.
173−--
174−-- @since 0.2.0
175−{-# INLINE serial #-}
176−serial :: IsStream t => t m a -> t m a -> t m a
177−serial m1 m2 = fromStream $ Stream $ \st stp sng yld ->
178− unStream (K.serial (toStream m1) (toStream m2))
179− (rstState st) stp sng yld
180
162
181------------------------------------------------------------------------------
163------------------------------------------------------------------------------
182-- Monad
164-- Monad
@@ -184,11 +166,7 @@ serial m1 m2 = fromStream $ Stream $ \st stp sng yld ->
184
166
185instance Monad m => Monad (SerialT m) where
167instance Monad m => Monad (SerialT m) where
186 return = pure
168 return = pure
187− (SerialT (Stream m)) >>= f = SerialT $ Stream $ \st stp sng yld ->
169+ (>>=) = K.bindWith K.serial
188− let run x = unStream x (rstState st) stp sng yld
189− single a = run $ toStream (f a)
190− yieldk a r = run $ toStream $ f a <> (fromStream r >>= f)
191− in m (rstState st) stp single yieldk
192
170
193------------------------------------------------------------------------------
171------------------------------------------------------------------------------
194-- Other instances
172-- Other instances
@@ -286,6 +264,9 @@ wSerially = adapt
286interleaving :: IsStream t => WSerialT m a -> t m a
264interleaving :: IsStream t => WSerialT m a -> t m a
287interleaving = wSerially
265interleaving = wSerially
288
266
267+consMWSerial :: Monad m => m a -> WSerialT m a -> WSerialT m a
268+consMWSerial m ms = fromStream $ K.consMStream m (toStream ms)
269+
289instance IsStream WSerialT where
270instance IsStream WSerialT where
290 toStream = getWSerialT
271 toStream = getWSerialT
291 fromStream = WSerialT
272 fromStream = WSerialT
@@ -293,34 +274,28 @@ instance IsStream WSerialT where
293 {-# INLINE consM #-}
274 {-# INLINE consM #-}
294 {-# SPECIALIZE consM :: IO a -> WSerialT IO a -> WSerialT IO a #-}
275 {-# SPECIALIZE consM :: IO a -> WSerialT IO a -> WSerialT IO a #-}
295 consM :: Monad m => m a -> WSerialT m a -> WSerialT m a
276 consM :: Monad m => m a -> WSerialT m a -> WSerialT m a
296− consM m r = fromStream $ K.consMSerial m (toStream r)
277+ consM = consMWSerial
297
278
298 {-# INLINE (|:) #-}
279 {-# INLINE (|:) #-}
299 {-# SPECIALIZE (|:) :: IO a -> WSerialT IO a -> WSerialT IO a #-}
280 {-# SPECIALIZE (|:) :: IO a -> WSerialT IO a -> WSerialT IO a #-}
300 (|:) :: Monad m => m a -> WSerialT m a -> WSerialT m a
281 (|:) :: Monad m => m a -> WSerialT m a -> WSerialT m a
301− m |: r = fromStream $ K.consMSerial m (toStream r)
282+ (|:) = consMWSerial
302
283
303------------------------------------------------------------------------------
284------------------------------------------------------------------------------
304-- Semigroup
285-- Semigroup
305------------------------------------------------------------------------------
286------------------------------------------------------------------------------
306
287
307−{-# INLINE interleave #-}
308−interleave :: Stream m a -> Stream m a -> Stream m a
309−interleave m1 m2 = Stream $ \st stp sng yld -> do
310− let stop = unStream m2 (rstState st) stp sng yld
311− single a = yld a m2
312− yieldk a r = yld a (interleave m2 r)
313− unStream m1 (rstState st) stop single yieldk
314−
315-- | Polymorphic version of the 'Semigroup' operation '<>' of 'WSerialT'.
288-- | Polymorphic version of the 'Semigroup' operation '<>' of 'WSerialT'.
316-- Interleaves two streams, yielding one element from each stream alternately.
289-- Interleaves two streams, yielding one element from each stream alternately.
317--
290--
318-- @since 0.2.0
291-- @since 0.2.0
319{-# INLINE wSerial #-}
292{-# INLINE wSerial #-}
320wSerial :: IsStream t => t m a -> t m a -> t m a
293wSerial :: IsStream t => t m a -> t m a -> t m a
321−wSerial m1 m2 = fromStream $ Stream $ \st stp sng yld ->
294+wSerial m1 m2 = mkStream $ \st yld sng stp -> do
322− unStream (interleave (toStream m1) (toStream m2))
295+ let stop = foldStream st yld sng stp m2
323− (rstState st) stp sng yld
296+ single a = yld a m2
297+ yieldk a r = yld a (wSerial m2 r)
298+ foldStream st yieldk single stop m1
324
299
325instance Semigroup (WSerialT m a) where
300instance Semigroup (WSerialT m a) where
326 (<>) = wSerial
301 (<>) = wSerial
@@ -349,11 +324,7 @@ instance Monoid (WSerialT m a) where
349
324
350instance Monad m => Monad (WSerialT m) where
325instance Monad m => Monad (WSerialT m) where
351 return = pure
326 return = pure
352− (WSerialT (Stream m)) >>= f = WSerialT $ Stream $ \st stp sng yld ->
327+ (>>=) = K.bindWith wSerial
353− let run x = unStream x (rstState st) stp sng yld
354− single a = run $ toStream (f a)
355− yieldk a r = run $ toStream $ f a <> (fromStream r >>= f)
356− in m (rstState st) stp single yieldk
357
328
358------------------------------------------------------------------------------
329------------------------------------------------------------------------------
359-- Other instances
330-- Other instances
src/Streamly/Streams/StreamD.hs+43−83
@@ -5,6 +5,8 @@
5{-# LANGUAGE FlexibleContexts #-}
5{-# LANGUAGE FlexibleContexts #-}
6{-# LANGUAGE FlexibleInstances #-}
6{-# LANGUAGE FlexibleInstances #-}
7{-# LANGUAGE MultiParamTypeClasses #-}
7{-# LANGUAGE MultiParamTypeClasses #-}
8+{-# LANGUAGE PatternSynonyms #-}
9+{-# LANGUAGE ViewPatterns #-}
8{-# LANGUAGE RankNTypes #-}
10{-# LANGUAGE RankNTypes #-}
9
11
10#include "inline.hs"
12#include "inline.hs"
@@ -197,30 +199,11 @@ import Prelude
197 notElem, null, head, tail, zipWith, lookup, foldr1, sequence,
199 notElem, null, head, tail, zipWith, lookup, foldr1, sequence,
198 (!!), scanl, scanl1, concatMap, replicate, enumFromTo)
200 (!!), scanl, scanl1, concatMap, replicate, enumFromTo)
199
201
200−import Streamly.SVar (MonadAsync, State(..), defState, rstState)
202+import Streamly.SVar (MonadAsync, defState, adaptState)
201
203
204+import Streamly.Streams.StreamD.Type
202import qualified Streamly.Streams.StreamK as K
205import qualified Streamly.Streams.StreamK as K
203
206
204−------------------------------------------------------------------------------
205−-- The direct style stream type
206−------------------------------------------------------------------------------
207−
208−-- | A stream is a succession of 'Step's. A 'Yield' produces a single value and
209−-- the next state of the stream. 'Stop' indicates there are no more values in
210−-- the stream.
211−data Step s a = Yield a s | Skip s | Stop
212−
213−instance Functor (Step s) where
214− {-# INLINE fmap #-}
215− fmap f (Yield x s) = Yield (f x) s
216− fmap _ (Skip s) = Skip s
217− fmap _ Stop = Stop
218−
219−-- gst = global state
220−-- | A stream consists of a step function that generates the next step given a
221−-- current state, and the current state.
222−data Stream m a = forall s. Stream (State K.Stream m a -> s -> m (Step s a)) s
223−
224------------------------------------------------------------------------------
207------------------------------------------------------------------------------
225-- Construction
208-- Construction
226------------------------------------------------------------------------------
209------------------------------------------------------------------------------
@@ -238,7 +221,7 @@ cons x (Stream step state) = Stream step1 Nothing
238 {-# INLINE_LATE step1 #-}
221 {-# INLINE_LATE step1 #-}
239 step1 _ Nothing = return $ Yield x (Just state)
222 step1 _ Nothing = return $ Yield x (Just state)
240 step1 gst (Just st) = do
223 step1 gst (Just st) = do
241− r <- step (rstState gst) st
224+ r <- step gst st
242 return $
225 return $
243 case r of
226 case r of
244 Yield a s -> Yield a (Just s)
227 Yield a s -> Yield a (Just s)
@@ -252,7 +235,7 @@ cons x (Stream step state) = Stream step1 Nothing
252-- Does not fuse, has the same performance as the StreamK version.
235-- Does not fuse, has the same performance as the StreamK version.
253{-# INLINE_NORMAL uncons #-}
236{-# INLINE_NORMAL uncons #-}
254uncons :: Monad m => Stream m a -> m (Maybe (a, Stream m a))
237uncons :: Monad m => Stream m a -> m (Maybe (a, Stream m a))
255−uncons (Stream step state) = go state
238+uncons (UnStream step state) = go state
256 where
239 where
257 go st = do
240 go st = do
258 r <- step defState st
241 r <- step defState st
@@ -492,7 +475,6 @@ fromList = Stream step
492 step _ (x:xs) = return $ Yield x xs
475 step _ (x:xs) = return $ Yield x xs
493 step _ [] = return Stop
476 step _ [] = return Stop
494
477
495−-- XXX pass the state to streamD
496{-# INLINE_LATE fromStreamK #-}
478{-# INLINE_LATE fromStreamK #-}
497fromStreamK :: Monad m => K.Stream m a -> Stream m a
479fromStreamK :: Monad m => K.Stream m a -> Stream m a
498fromStreamK = Stream step
480fromStreamK = Stream step
@@ -501,7 +483,7 @@ fromStreamK = Stream step
501 let stop = return Stop
483 let stop = return Stop
502 single a = return $ Yield a K.nil
484 single a = return $ Yield a K.nil
503 yieldk a r = return $ Yield a r
485 yieldk a r = return $ Yield a r
504− in K.unStream m1 gst stop single yieldk
486+ in K.foldStreamShared gst yieldk single stop m1
505
487
506{-# INLINE toStreamD #-}
488{-# INLINE toStreamD #-}
507toStreamD :: (K.IsStream t, Monad m) => t m a -> Stream m a
489toStreamD :: (K.IsStream t, Monad m) => t m a -> Stream m a
@@ -593,7 +575,7 @@ head (Stream step state) = go state
593-- Does not fuse, has the same performance as the StreamK version.
575-- Does not fuse, has the same performance as the StreamK version.
594{-# INLINE_NORMAL tail #-}
576{-# INLINE_NORMAL tail #-}
595tail :: Monad m => Stream m a -> m (Maybe (Stream m a))
577tail :: Monad m => Stream m a -> m (Maybe (Stream m a))
596−tail (Stream step state) = go state
578+tail (UnStream step state) = go state
597 where
579 where
598 go st = do
580 go st = do
599 r <- step defState st
581 r <- step defState st
@@ -773,7 +755,7 @@ findIndices p (Stream step state) = Stream step' (state, 0)
773 where
755 where
774 {-# INLINE_LATE step' #-}
756 {-# INLINE_LATE step' #-}
775 step' gst (st, i) = do
757 step' gst (st, i) = do
776− r <- step (rstState gst) st
758+ r <- step (adaptState gst) st
777 return $ case r of
759 return $ case r of
778 Yield x s -> if p x then Yield i (s, i+1) else Skip (s, i+1)
760 Yield x s -> if p x then Yield i (s, i+1) else Skip (s, i+1)
779 Skip s -> Skip (s, i+1)
761 Skip s -> Skip (s, i+1)
@@ -785,7 +767,7 @@ concatMapM f (Stream step state) = Stream step' (Left state)
785 where
767 where
786 {-# INLINE_LATE step' #-}
768 {-# INLINE_LATE step' #-}
787 step' gst (Left st) = do
769 step' gst (Left st) = do
788− r <- step (rstState gst) st
770+ r <- step (adaptState gst) st
789 case r of
771 case r of
790 Yield a s -> do
772 Yield a s -> do
791 b_stream <- f a
773 b_stream <- f a
@@ -793,7 +775,10 @@ concatMapM f (Stream step state) = Stream step' (Left state)
793 Skip s -> return $ Skip (Left s)
775 Skip s -> return $ Skip (Left s)
794 Stop -> return Stop
776 Stop -> return Stop
795
777
778+ -- XXX using the pattern synonym Stream causes a major performance issue
779+ -- here even if the synonym does not include a adaptState call. Need to
780+ -- find out why. Is that something to be fixed in GHC?
796− step' _ (Right (Stream inner_step inner_st, st)) = do
781+ step' _ (Right (UnStream inner_step inner_st, st)) = do
797 r <- inner_step defState inner_st
782 r <- inner_step defState inner_st
798 case r of
783 case r of
799 Yield b inner_s ->
784 Yield b inner_s ->
@@ -897,11 +882,11 @@ toList = foldr (:) []
897toStreamK :: Monad m => Stream m a -> K.Stream m a
882toStreamK :: Monad m => Stream m a -> K.Stream m a
898toStreamK (Stream step state) = go state
883toStreamK (Stream step state) = go state
899 where
884 where
900− go st = K.Stream $ \gst stp sng yld -> do
885+ go st = K.mkStream $ \gst yld sng stp -> do
901 r <- step gst st
886 r <- step gst st
902 case r of
887 case r of
903 Yield x s -> yld x (go s)
888 Yield x s -> yld x (go s)
904− Skip s -> K.unStream (go s) gst stp sng yld
889+ Skip s -> K.foldStreamShared gst yld sng stp $ go s
905 Stop -> stp
890 Stop -> stp
906
891
907#ifndef DISABLE_FUSION
892#ifndef DISABLE_FUSION
@@ -935,7 +920,7 @@ prescanlM' f mz (Stream step state) = Stream step' (state, mz)
935 where
920 where
936 {-# INLINE_LATE step' #-}
921 {-# INLINE_LATE step' #-}
937 step' gst (st, prev) = do
922 step' gst (st, prev) = do
938− r <- step (rstState gst) st
923+ r <- step (adaptState gst) st
939 case r of
924 case r of
940 Yield x s -> do
925 Yield x s -> do
941 acc <- prev
926 acc <- prev
@@ -963,7 +948,7 @@ postscanlM' fstep begin (Stream step state) =
963 where
948 where
964 {-# INLINE_LATE step' #-}
949 {-# INLINE_LATE step' #-}
965 step' gst (st, acc) = acc `seq` do
950 step' gst (st, acc) = acc `seq` do
966− r <- step (rstState gst) st
951+ r <- step (adaptState gst) st
967 case r of
952 case r of
968 Yield x s -> do
953 Yield x s -> do
969 y <- fstep acc x
954 y <- fstep acc x
@@ -981,7 +966,7 @@ postscanlM fstep begin (Stream step state) = Stream step' (state, begin)
981 where
966 where
982 {-# INLINE_LATE step' #-}
967 {-# INLINE_LATE step' #-}
983 step' gst (st, acc) = do
968 step' gst (st, acc) = do
984− r <- step (rstState gst) st
969+ r <- step (adaptState gst) st
985 case r of
970 case r of
986 Yield x s -> do
971 Yield x s -> do
987 y <- fstep acc x
972 y <- fstep acc x
@@ -1015,14 +1000,14 @@ scanl1M fstep (Stream step state) = Stream step' (state, Nothing)
1015 where
1000 where
1016 {-# INLINE_LATE step' #-}
1001 {-# INLINE_LATE step' #-}
1017 step' gst (st, Nothing) = do
1002 step' gst (st, Nothing) = do
1018− r <- step (rstState gst) st
1003+ r <- step gst st
1019 case r of
1004 case r of
1020 Yield x s -> return $ Yield x (s, Just x)
1005 Yield x s -> return $ Yield x (s, Just x)
1021 Skip s -> return $ Skip (s, Nothing)
1006 Skip s -> return $ Skip (s, Nothing)
1022 Stop -> return Stop
1007 Stop -> return Stop
1023
1008
1024 step' gst (st, Just acc) = do
1009 step' gst (st, Just acc) = do
1025− r <- step (rstState gst) st
1010+ r <- step gst st
1026 case r of
1011 case r of
1027 Yield y s -> do
1012 Yield y s -> do
1028 z <- fstep acc y
1013 z <- fstep acc y
@@ -1040,14 +1025,14 @@ scanl1M' fstep (Stream step state) = Stream step' (state, Nothing)
1040 where
1025 where
1041 {-# INLINE_LATE step' #-}
1026 {-# INLINE_LATE step' #-}
1042 step' gst (st, Nothing) = do
1027 step' gst (st, Nothing) = do
1043− r <- step (rstState gst) st
1028+ r <- step gst st
1044 case r of
1029 case r of
1045 Yield x s -> x `seq` return $ Yield x (s, Just x)
1030 Yield x s -> x `seq` return $ Yield x (s, Just x)
1046 Skip s -> return $ Skip (s, Nothing)
1031 Skip s -> return $ Skip (s, Nothing)
1047 Stop -> return Stop
1032 Stop -> return Stop
1048
1033
1049 step' gst (st, Just acc) = acc `seq` do
1034 step' gst (st, Just acc) = acc `seq` do
1050− r <- step (rstState gst) st
1035+ r <- step gst st
1051 case r of
1036 case r of
1052 Yield y s -> do
1037 Yield y s -> do
1053 z <- fstep acc y
1038 z <- fstep acc y
@@ -1069,7 +1054,7 @@ take n (Stream step state) = n `seq` Stream step' (state, 0)
1069 where
1054 where
1070 {-# INLINE_LATE step' #-}
1055 {-# INLINE_LATE step' #-}
1071 step' gst (st, i) | i < n = do
1056 step' gst (st, i) | i < n = do
1072− r <- step (rstState gst) st
1057+ r <- step gst st
1073 return $ case r of
1058 return $ case r of
1074 Yield x s -> Yield x (s, i + 1)
1059 Yield x s -> Yield x (s, i + 1)
1075 Skip s -> Skip (s, i)
1060 Skip s -> Skip (s, i)
@@ -1082,7 +1067,7 @@ takeWhileM f (Stream step state) = Stream step' state
1082 where
1067 where
1083 {-# INLINE_LATE step' #-}
1068 {-# INLINE_LATE step' #-}
1084 step' gst st = do
1069 step' gst st = do
1085− r <- step (rstState gst) st
1070+ r <- step gst st
1086 case r of
1071 case r of
1087 Yield x s -> do
1072 Yield x s -> do
1088 b <- f x
1073 b <- f x
@@ -1101,7 +1086,7 @@ drop n (Stream step state) = Stream step' (state, Just n)
1101 {-# INLINE_LATE step' #-}
1086 {-# INLINE_LATE step' #-}
1102 step' gst (st, Just i)
1087 step' gst (st, Just i)
1103 | i > 0 = do
1088 | i > 0 = do
1104− r <- step (rstState gst) st
1089+ r <- step gst st
1105 return $
1090 return $
1106 case r of
1091 case r of
1107 Yield _ s -> Skip (s, Just (i - 1))
1092 Yield _ s -> Skip (s, Just (i - 1))
@@ -1110,7 +1095,7 @@ drop n (Stream step state) = Stream step' (state, Just n)
1110 | otherwise = return $ Skip (st, Nothing)
1095 | otherwise = return $ Skip (st, Nothing)
1111
1096
1112 step' gst (st, Nothing) = do
1097 step' gst (st, Nothing) = do
1113− r <- step (rstState gst) st
1098+ r <- step gst st
1114 return $
1099 return $
1115 case r of
1100 case r of
1116 Yield x s -> Yield x (s, Nothing)
1101 Yield x s -> Yield x (s, Nothing)
@@ -1128,7 +1113,7 @@ dropWhileM f (Stream step state) = Stream step' (DropWhileDrop state)
1128 where
1113 where
1129 {-# INLINE_LATE step' #-}
1114 {-# INLINE_LATE step' #-}
1130 step' gst (DropWhileDrop st) = do
1115 step' gst (DropWhileDrop st) = do
1131− r <- step (rstState gst) st
1116+ r <- step gst st
1132 case r of
1117 case r of
1133 Yield x s -> do
1118 Yield x s -> do
1134 b <- f x
1119 b <- f x
@@ -1139,7 +1124,7 @@ dropWhileM f (Stream step state) = Stream step' (DropWhileDrop state)
1139 Stop -> return Stop
1124 Stop -> return Stop
1140
1125
1141 step' gst (DropWhileNext st) = do
1126 step' gst (DropWhileNext st) = do
1142− r <- step (rstState gst) st
1127+ r <- step gst st
1143 case r of
1128 case r of
1144 Yield x s -> return $ Skip (DropWhileYield x s)
1129 Yield x s -> return $ Skip (DropWhileYield x s)
1145 Skip s -> return $ Skip (DropWhileNext s)
1130 Skip s -> return $ Skip (DropWhileNext s)
@@ -1157,7 +1142,7 @@ filterM f (Stream step state) = Stream step' state
1157 where
1142 where
1158 {-# INLINE_LATE step' #-}
1143 {-# INLINE_LATE step' #-}
1159 step' gst st = do
1144 step' gst st = do
1160− r <- step (rstState gst) st
1145+ r <- step gst st
1161 case r of
1146 case r of
1162 Yield x s -> do
1147 Yield x s -> do
1163 b <- f x
1148 b <- f x
@@ -1177,13 +1162,13 @@ uniq (Stream step state) = Stream step' (Nothing, state)
1177 where
1162 where
1178 {-# INLINE_LATE step' #-}
1163 {-# INLINE_LATE step' #-}
1179 step' gst (Nothing, st) = do
1164 step' gst (Nothing, st) = do
1180− r <- step (rstState gst) st
1165+ r <- step gst st
1181 case r of
1166 case r of
1182 Yield x s -> return $ Yield x (Just x, s)
1167 Yield x s -> return $ Yield x (Just x, s)
1183 Skip s -> return $ Skip (Nothing, s)
1168 Skip s -> return $ Skip (Nothing, s)
1184 Stop -> return Stop
1169 Stop -> return Stop
1185 step' gst (Just x, st) = do
1170 step' gst (Just x, st) = do
1186− r <- step (rstState gst) st
1171+ r <- step gst st
1187 case r of
1172 case r of
1188 Yield y s | x == y -> return $ Skip (Just x, s)
1173 Yield y s | x == y -> return $ Skip (Just x, s)
1189 | otherwise -> return $ Yield x (Just y, s)
1174 | otherwise -> return $ Yield x (Just y, s)
@@ -1194,30 +1179,13 @@ uniq (Stream step state) = Stream step' (Nothing, state)
1194-- Transformation by Mapping
1179-- Transformation by Mapping
1195------------------------------------------------------------------------------
1180------------------------------------------------------------------------------
1196
1181
1197−-- | Map a monadic function over a 'Stream'
1198−{-# INLINE_NORMAL mapM #-}
1199−mapM :: Monad m => (a -> m b) -> Stream m a -> Stream m b
1200−mapM f (Stream step state) = Stream step' state
1201− where
1202− {-# INLINE_LATE step' #-}
1203− step' gst st = do
1204− r <- step (rstState gst) st
1205− case r of
1206− Yield x s -> f x >>= \a -> return $ Yield a s
1207− Skip s -> return $ Skip s
1208− Stop -> return Stop
1209−
1210−{-# INLINE map #-}
1211−map :: Monad m => (a -> b) -> Stream m a -> Stream m b
1212−map f = mapM (return . f)
1213−
1214{-# INLINE_NORMAL sequence #-}
1182{-# INLINE_NORMAL sequence #-}
1215sequence :: Monad m => Stream m (m a) -> Stream m a
1183sequence :: Monad m => Stream m (m a) -> Stream m a
1216sequence (Stream step state) = Stream step' state
1184sequence (Stream step state) = Stream step' state
1217 where
1185 where
1218 {-# INLINE_LATE step' #-}
1186 {-# INLINE_LATE step' #-}
1219 step' gst st = do
1187 step' gst st = do
1220− r <- step (rstState gst) st
1188+ r <- step (adaptState gst) st
1221 case r of
1189 case r of
1222 Yield x s -> x >>= \a -> return (Yield a s)
1190 Yield x s -> x >>= \a -> return (Yield a s)
1223 Skip s -> return $ Skip s
1191 Skip s -> return $ Skip s
@@ -1233,7 +1201,7 @@ insertBy cmp a (Stream step state) = Stream step' (state, False, Nothing)
1233 where
1201 where
1234 {-# INLINE_LATE step' #-}
1202 {-# INLINE_LATE step' #-}
1235 step' gst (st, False, _) = do
1203 step' gst (st, False, _) = do
1236− r <- step (rstState gst) st
1204+ r <- step gst st
1237 case r of
1205 case r of
1238 Yield x s -> case cmp a x of
1206 Yield x s -> case cmp a x of
1239 GT -> return $ Yield x (s, False, Nothing)
1207 GT -> return $ Yield x (s, False, Nothing)
@@ -1244,7 +1212,7 @@ insertBy cmp a (Stream step state) = Stream step' (state, False, Nothing)
1244 step' _ (_, True, Nothing) = return Stop
1212 step' _ (_, True, Nothing) = return Stop
1245
1213
1246 step' gst (st, True, Just prev) = do
1214 step' gst (st, True, Just prev) = do
1247− r <- step (rstState gst) st
1215+ r <- step gst st
1248 case r of
1216 case r of
1249 Yield x s -> return $ Yield prev (s, True, Just x)
1217 Yield x s -> return $ Yield prev (s, True, Just x)
1250 Skip s -> return $ Skip (s, True, Just prev)
1218 Skip s -> return $ Skip (s, True, Just prev)
@@ -1260,7 +1228,7 @@ deleteBy eq x (Stream step state) = Stream step' (state, False)
1260 where
1228 where
1261 {-# INLINE_LATE step' #-}
1229 {-# INLINE_LATE step' #-}
1262 step' gst (st, False) = do
1230 step' gst (st, False) = do
1263− r <- step (rstState gst) st
1231+ r <- step gst st
1264 case r of
1232 case r of
1265 Yield y s -> return $
1233 Yield y s -> return $
1266 if eq x y then Skip (s, True) else Yield y (s, False)
1234 if eq x y then Skip (s, True) else Yield y (s, False)
@@ -1268,7 +1236,7 @@ deleteBy eq x (Stream step state) = Stream step' (state, False)
1268 Stop -> return Stop
1236 Stop -> return Stop
1269
1237
1270 step' gst (st, True) = do
1238 step' gst (st, True) = do
1271− r <- step (rstState gst) st
1239+ r <- step gst st
1272 case r of
1240 case r of
1273 Yield y s -> return $ Yield y (s, True)
1241 Yield y s -> return $ Yield y (s, True)
1274 Skip s -> return $ Skip (s, True)
1242 Skip s -> return $ Skip (s, True)
@@ -1297,7 +1265,7 @@ indexed (Stream step state) = Stream step' (state, 0)
1297 where
1265 where
1298 {-# INLINE_LATE step' #-}
1266 {-# INLINE_LATE step' #-}
1299 step' gst (st, i) = i `seq` do
1267 step' gst (st, i) = i `seq` do
1300− r <- step (rstState gst) st
1268+ r <- step (adaptState gst) st
1301 case r of
1269 case r of
1302 Yield x s -> return $ Yield (i, x) (s, i+1)
1270 Yield x s -> return $ Yield (i, x) (s, i+1)
1303 Skip s -> return $ Skip (s, i)
1271 Skip s -> return $ Skip (s, i)
@@ -1309,7 +1277,7 @@ indexedR m (Stream step state) = Stream step' (state, m)
1309 where
1277 where
1310 {-# INLINE_LATE step' #-}
1278 {-# INLINE_LATE step' #-}
1311 step' gst (st, i) = i `seq` do
1279 step' gst (st, i) = i `seq` do
1312− r <- step (rstState gst) st
1280+ r <- step (adaptState gst) st
1313 case r of
1281 case r of
1314 Yield x s -> let i' = i - 1
1282 Yield x s -> let i' = i - 1
1315 in
1283 in
@@ -1324,7 +1292,7 @@ zipWithM f (Stream stepa ta) (Stream stepb tb) = Stream step (ta, tb, Nothing)
1324 where
1292 where
1325 {-# INLINE_LATE step #-}
1293 {-# INLINE_LATE step #-}
1326 step gst (sa, sb, Nothing) = do
1294 step gst (sa, sb, Nothing) = do
1327− r <- stepa (rstState gst) sa
1295+ r <- stepa (adaptState gst) sa
1328 return $
1296 return $
1329 case r of
1297 case r of
1330 Yield x sa' -> Skip (sa', sb, Just x)
1298 Yield x sa' -> Skip (sa', sb, Just x)
@@ -1332,7 +1300,7 @@ zipWithM f (Stream stepa ta) (Stream stepb tb) = Stream step (ta, tb, Nothing)
1332 Stop -> Stop
1300 Stop -> Stop
1333
1301
1334 step gst (sa, sb, Just x) = do
1302 step gst (sa, sb, Just x) = do
1335− r <- stepb (rstState gst) sb
1303+ r <- stepb (adaptState gst) sb
1336 case r of
1304 case r of
1337 Yield y sb' -> do
1305 Yield y sb' -> do
1338 z <- f x y
1306 z <- f x y
@@ -1423,14 +1391,14 @@ mergeByM cmp (Stream stepa ta) (Stream stepb tb) =
1423
1391
1424 -- one of the values is missing, and the corresponding stream is running
1392 -- one of the values is missing, and the corresponding stream is running
1425 step gst (Just sa, sb, Nothing, b) = do
1393 step gst (Just sa, sb, Nothing, b) = do
1426− r <- stepa (rstState gst) sa
1394+ r <- stepa gst sa
1427 return $ case r of
1395 return $ case r of
1428 Yield a sa' -> Skip (Just sa', sb, Just a, b)
1396 Yield a sa' -> Skip (Just sa', sb, Just a, b)
1429 Skip sa' -> Skip (Just sa', sb, Nothing, b)
1397 Skip sa' -> Skip (Just sa', sb, Nothing, b)
1430 Stop -> Skip (Nothing, sb, Nothing, b)
1398 Stop -> Skip (Nothing, sb, Nothing, b)
1431
1399
1432 step gst (sa, Just sb, a, Nothing) = do
1400 step gst (sa, Just sb, a, Nothing) = do
1433− r <- stepb (rstState gst) sb
1401+ r <- stepb gst sb
1434 return $ case r of
1402 return $ case r of
1435 Yield b sb' -> Skip (sa, Just sb', a, Just b)
1403 Yield b sb' -> Skip (sa, Just sb', a, Just b)
1436 Skip sb' -> Skip (sa, Just sb', a, Nothing)
1404 Skip sb' -> Skip (sa, Just sb', a, Nothing)
@@ -1479,11 +1447,3 @@ the (Stream step state) = go state
1479 | otherwise -> return Nothing
1447 | otherwise -> return Nothing
1480 Skip s -> go' n s
1448 Skip s -> go' n s
1481 Stop -> return (Just n)
1449 Stop -> return (Just n)
1482−
1483−------------------------------------------------------------------------------
1484−-- Instances
1485−------------------------------------------------------------------------------
1486−
1487−instance Monad m => Functor (Stream m) where
1488− {-# INLINE fmap #-}
1489− fmap = map
src/Streamly/Streams/StreamD/Type.hsnew file+100
@@ -0,0 +1,100 @@
1+{-# LANGUAGE BangPatterns #-}
2+{-# LANGUAGE CPP #-}
3+{-# LANGUAGE ConstraintKinds #-}
4+{-# LANGUAGE ExistentialQuantification #-}
5+{-# LANGUAGE FlexibleContexts #-}
6+{-# LANGUAGE FlexibleInstances #-}
7+{-# LANGUAGE MultiParamTypeClasses #-}
8+{-# LANGUAGE PatternSynonyms #-}
9+{-# LANGUAGE ViewPatterns #-}
10+{-# LANGUAGE RankNTypes #-}
11+
12+#include "../inline.hs"
13+
14+-- |
15+-- Module : Streamly.Streams.StreamD.Type
16+-- Copyright : (c) 2018 Harendra Kumar
17+--
18+-- License : BSD3
19+-- Maintainer : harendra.kumar@gmail.com
20+-- Stability : experimental
21+-- Portability : GHC
22+
23+module Streamly.Streams.StreamD.Type
24+ (
25+ -- * The stream type
26+ Step (..)
27+ -- XXX UnStream is exported to avoid a performance issue in concatMap if we
28+ -- use the pattern synonym "Stream".
29+#if __GLASGOW_HASKELL__ >= 800
30+ , Stream (Stream, UnStream)
31+#else
32+ , Stream (UnStream)
33+ , pattern Stream
34+#endif
35+ , map
36+ , mapM
37+ )
38+where
39+
40+import Streamly.SVar (State(..), adaptState)
41+import qualified Streamly.Streams.StreamK as K
42+import Prelude hiding (map, mapM)
43+
44+------------------------------------------------------------------------------
45+-- The direct style stream type
46+------------------------------------------------------------------------------
47+
48+-- | A stream is a succession of 'Step's. A 'Yield' produces a single value and
49+-- the next state of the stream. 'Stop' indicates there are no more values in
50+-- the stream.
51+data Step s a = Yield a s | Skip s | Stop
52+
53+instance Functor (Step s) where
54+ {-# INLINE fmap #-}
55+ fmap f (Yield x s) = Yield (f x) s
56+ fmap _ (Skip s) = Skip s
57+ fmap _ Stop = Stop
58+
59+-- gst = global state
60+-- | A stream consists of a step function that generates the next step given a
61+-- current state, and the current state.
62+data Stream m a =
63+ forall s. UnStream (State K.Stream m a -> s -> m (Step s a)) s
64+
65+unShare :: Stream m a -> Stream m a
66+unShare (UnStream step state) = UnStream step' state
67+ where step' gst = step (adaptState gst)
68+
69+pattern Stream :: (State K.Stream m a -> s -> m (Step s a)) -> s -> Stream m a
70+pattern Stream step state <- (unShare -> UnStream step state)
71+ where Stream = UnStream
72+
73+#if __GLASGOW_HASKELL__ >= 802
74+{-# COMPLETE Stream #-}
75+#endif
76+
77+------------------------------------------------------------------------------
78+-- Instances
79+------------------------------------------------------------------------------
80+
81+-- | Map a monadic function over a 'Stream'
82+{-# INLINE_NORMAL mapM #-}
83+mapM :: Monad m => (a -> m b) -> Stream m a -> Stream m b
84+mapM f (Stream step state) = Stream step' state
85+ where
86+ {-# INLINE_LATE step' #-}
87+ step' gst st = do
88+ r <- step (adaptState gst) st
89+ case r of
90+ Yield x s -> f x >>= \a -> return $ Yield a s
91+ Skip s -> return $ Skip s
92+ Stop -> return Stop
93+
94+{-# INLINE map #-}
95+map :: Monad m => (a -> b) -> Stream m a -> Stream m b
96+map f = mapM (return . f)
97+
98+instance Monad m => Functor (Stream m) where
99+ {-# INLINE fmap #-}
100+ fmap = map
src/Streamly/Streams/StreamK.hs+224−471
@@ -6,8 +6,11 @@
6{-# LANGUAGE InstanceSigs #-}
6{-# LANGUAGE InstanceSigs #-}
7{-# LANGUAGE MultiParamTypeClasses #-}
7{-# LANGUAGE MultiParamTypeClasses #-}
8{-# LANGUAGE RankNTypes #-}
8{-# LANGUAGE RankNTypes #-}
9+{-# LANGUAGE ScopedTypeVariables #-}
9{-# LANGUAGE UndecidableInstances #-} -- XXX
10{-# LANGUAGE UndecidableInstances #-} -- XXX
10
11
12+#include "inline.hs"
13+
11-- |
14-- |
12-- Module : Streamly.Streams.StreamK
15-- Module : Streamly.Streams.StreamK
13-- Copyright : (c) 2017 Harendra Kumar
16-- Copyright : (c) 2017 Harendra Kumar
@@ -32,22 +35,21 @@ module Streamly.Streams.StreamK
32 , adapt
35 , adapt
33
36
34 -- * The stream type
37 -- * The stream type
35− , Stream (..)
38+ , Stream
36− , unStreamIsolated
37− , isolateStream
38− , unstreamShared
39− , runStreamSVar
40
39
41− -- * Construction
40+ -- * Construction Primitives
42 , mkStream
41 , mkStream
43 , nil
42 , nil
44 , cons
43 , cons
45 , (.:)
44 , (.:)
46
45
47− -- * Asynchronous construction
46+ -- * Elimination Primitives
48− , nilK
47+ , foldStream
49− , yieldK
48+ , foldStreamShared
50− , consK
49+ , foldStreamSVar
50+
51+ -- * Transformation Primitives
52+ , unShare
51
53
52 -- * Deconstruction
54 -- * Deconstruction
53 , uncons
55 , uncons
@@ -71,7 +73,6 @@ module Streamly.Streams.StreamK
71
73
72 -- * Elimination
74 -- * Elimination
73 -- ** General Folds
75 -- ** General Folds
74− , foldStream
75 , foldr
76 , foldr
76 , foldrM
77 , foldrM
77 , foldr1
78 , foldr1
@@ -150,7 +151,7 @@ module Streamly.Streams.StreamK
150 , serial
151 , serial
151
152
152 -- * Utilities
153 -- * Utilities
153− , consMSerial
154+ , consMStream
154 , bindWith
155 , bindWith
155 , withLocal
156 , withLocal
156
157
@@ -161,10 +162,7 @@ module Streamly.Streams.StreamK
161where
162where
162
163
163import Control.Monad (void)
164import Control.Monad (void)
164−import Control.Monad.IO.Class (MonadIO(liftIO))
165import Control.Monad.Reader.Class (MonadReader(..))
165import Control.Monad.Reader.Class (MonadReader(..))
166−import Control.Monad.Trans.Class (MonadTrans(lift))
167−import Data.Semigroup (Semigroup(..))
168import Prelude
166import Prelude
169 hiding (foldl, foldr, last, map, mapM, mapM_, repeat, sequence,
167 hiding (foldl, foldr, last, map, mapM, mapM_, repeat, sequence,
170 take, filter, all, any, takeWhile, drop, dropWhile, minimum,
168 take, filter, all, any, takeWhile, drop, dropWhile, minimum,
@@ -173,182 +171,18 @@ import Prelude
173import qualified Prelude
171import qualified Prelude
174
172
175import Streamly.SVar
173import Streamly.SVar
174+import Streamly.Streams.StreamK.Type
176
175
177−------------------------------------------------------------------------------
178−-- The basic stream type
179−------------------------------------------------------------------------------
180−
181−-- | The type @Stream m a@ represents a monadic stream of values of type 'a'
182−-- constructed using actions in monad 'm'. It uses stop, singleton and yield
183−-- continuations equivalent to the following direct style type:
184−--
185−-- @
186−-- data Stream m a = Stop | Singleton a | Yield a (Stream m a)
187−-- @
188−--
189−-- To facilitate parallel composition we maintain a local state in an 'SVar'
190−-- that is shared across and is used for synchronization of the streams being
191−-- composed.
192−--
193−-- The singleton case can be expressed in terms of stop and yield but we have
194−-- it as a separate case to optimize composition operations for streams with
195−-- single element. We build singleton streams in the implementation of 'pure'
196−-- for Applicative and Monad, and in 'lift' for MonadTrans.
197−--
198−newtype Stream m a =
199− Stream {
200− unStream :: forall r.
201− State Stream m a -- state
202− -> m r -- stop
203− -> (a -> m r) -- singleton
204− -> (a -> Stream m a -> m r) -- yield
205− -> m r
206− }
207−
208−-- XXX make this the default "unStream"
209−-- | unwraps the Stream type producing the stream function that can be run with
210−-- continuations.
211−{-# INLINE unStreamIsolated #-}
212−unStreamIsolated ::
213− Stream m a
214− -> State Stream m a -- state
215− -> m r -- stop
216− -> (a -> m r) -- singleton
217− -> (a -> Stream m a -> m r) -- yield
218− -> m r
219−unStreamIsolated x st = unStream x (rstState st)
220−
221−{-# INLINE isolateStream #-}
222−isolateStream :: Stream m a -> Stream m a
223−isolateStream x = Stream $ \st stp sng yld ->
224− unStreamIsolated x st stp sng yld
225−
226−-- | Like unstream, but passes a shared SVar across continuations.
227−{-# INLINE unstreamShared #-}
228−unstreamShared ::
229− Stream m a
230− -> State Stream m a -- state
231− -> m r -- stop
232− -> (a -> m r) -- singleton
233− -> (a -> Stream m a -> m r) -- yield
234− -> m r
235−unstreamShared = unStream
236−
237−-- Run the stream using a run function associated with the SVar that runs the
238−-- streams with a captured snapshot of the monadic state.
239−{-# INLINE runStreamSVar #-}
240−runStreamSVar
241− :: MonadIO m
242− => SVar Stream m a
243− -> Stream m a
244− -> State Stream m a -- state
245− -> m r -- stop
246− -> (a -> m r) -- singleton
247− -> (a -> Stream m a -> m r) -- yield
248− -> m ()
249−runStreamSVar sv m st stp sng yld =
250− let mrun = runInIO $ svarMrun sv
251− in void $ liftIO $ mrun $ unStream m st stp sng yld
252−
253−------------------------------------------------------------------------------
254−-- Types that can behave as a Stream
255−------------------------------------------------------------------------------
256−
257−infixr 5 `consM`
258−infixr 5 |:
259−
260−-- | Class of types that can represent a stream of elements of some type 'a' in
261−-- some monad 'm'.
262−--
263−-- @since 0.2.0
264−class IsStream t where
265− toStream :: t m a -> Stream m a
266− fromStream :: Stream m a -> t m a
267− -- | Constructs a stream by adding a monadic action at the head of an
268− -- existing stream. For example:
269− --
270− -- @
271− -- > toList $ getLine \`consM` getLine \`consM` nil
272− -- hello
273− -- world
274− -- ["hello","world"]
275− -- @
276− --
277− -- /Concurrent (do not use 'parallely' to construct infinite streams)/
278− --
279− -- @since 0.2.0
280− consM :: MonadAsync m => m a -> t m a -> t m a
281− -- | Operator equivalent of 'consM'. We can read it as "@parallel colon@"
282− -- to remember that @|@ comes before ':'.
283− --
284− -- @
285− -- > toList $ getLine |: getLine |: nil
286− -- hello
287− -- world
288− -- ["hello","world"]
289− -- @
290− --
291− -- @
292− -- let delay = threadDelay 1000000 >> print 1
293− -- runStream $ serially $ delay |: delay |: delay |: nil
294− -- runStream $ parallely $ delay |: delay |: delay |: nil
295− -- @
296− --
297− -- /Concurrent (do not use 'parallely' to construct infinite streams)/
298− --
299− -- @since 0.2.0
300− (|:) :: MonadAsync m => m a -> t m a -> t m a
301− -- We can define (|:) just as 'consM' but it is defined explicitly for each
302− -- type because we want to use SPECIALIZE pragma on the definition.
303−
304−-- | Same as 'IsStream'.
305−--
306−-- @since 0.1.0
307−{-# DEPRECATED Streaming "Please use IsStream instead." #-}
308−type Streaming = IsStream
309−
310−-------------------------------------------------------------------------------
311−-- Type adapting combinators
312−-------------------------------------------------------------------------------
313−
314−-- | Adapt any specific stream type to any other specific stream type.
315−--
316−-- @since 0.1.0
317−adapt :: (IsStream t1, IsStream t2) => t1 m a -> t2 m a
318−adapt = fromStream . toStream
319−
320−------------------------------------------------------------------------------
321−-- Building a stream
322−------------------------------------------------------------------------------
323−
324−-- | Build a stream from an 'SVar', a stop continuation, a singleton stream
176+-- | Detach a stream from an SVar
325−-- continuation and a yield continuation.
177+{-# INLINE unShare #-}
326−mkStream:: IsStream t
178+unShare :: IsStream t => t m a -> t m a
327− => (forall r. State Stream m a
179+unShare x = mkStream $ \st yld sng stp ->
328− -> m r
180+ foldStream st yld sng stp x
329− -> (a -> m r)
330− -> (a -> t m a -> m r)
331− -> m r)
332− -> t m a
333−mkStream k = fromStream $ Stream $ \st stp sng yld ->
334− let yieldk a r = yld a (toStream r)
335− in k (rstState st) stp sng yieldk
336
181
337------------------------------------------------------------------------------
182------------------------------------------------------------------------------
338-- Construction
183-- Construction
339------------------------------------------------------------------------------
184------------------------------------------------------------------------------
340
185
341−-- | An empty stream.
342−--
343−-- @
344−-- > toList nil
345−-- []
346−-- @
347−--
348−-- @since 0.1.0
349−nil :: IsStream t => t m a
350−nil = fromStream $ Stream $ \_ stp _ _ -> stp
351−
352infixr 5 `cons`
186infixr 5 `cons`
353
187
354-- faster than consM because there is no bind.
188-- faster than consM because there is no bind.
@@ -363,8 +197,9 @@ infixr 5 `cons`
363-- @
197-- @
364--
198--
365-- @since 0.1.0
199-- @since 0.1.0
200+{-# INLINE cons #-}
366cons :: IsStream t => a -> t m a -> t m a
201cons :: IsStream t => a -> t m a -> t m a
367−cons a r = fromStream $ Stream $ \_ _ _ yld -> yld a (toStream r)
202+cons a r = mkStream $ \_ yld _ _ -> yld a r
368
203
369infixr 5 .:
204infixr 5 .:
370
205
@@ -376,50 +211,10 @@ infixr 5 .:
376-- @
211-- @
377--
212--
378-- @since 0.1.1
213-- @since 0.1.1
214+{-# INLINE (.:) #-}
379(.:) :: IsStream t => a -> t m a -> t m a
215(.:) :: IsStream t => a -> t m a -> t m a
380(.:) = cons
216(.:) = cons
381
217
382−{-# INLINE consMSerial #-}
383−consMSerial :: (Monad m) => m a -> Stream m a -> Stream m a
384−consMSerial m r = Stream $ \_ _ _ yld -> m >>= \a -> yld a r
385−
386−------------------------------------------------------------------------------
387−-- Asynchronous construction
388−------------------------------------------------------------------------------
389−
390−-- | Make an empty stream from a callback function.
391−nilK :: IsStream t => (forall r. m r -> m r) -> t m a
392−nilK k = fromStream $ Stream $ \_ stp _ _ -> k stp
393−
394−-- | Make a singleton stream from a one shot callback function.
395−yieldK :: IsStream t => (forall r. (a -> m r) -> m r) -> t m a
396−yieldK k = fromStream $ Stream $ \_ _ sng _ -> k sng
397−
398−-- | Construct a stream from a callback function.
399−consK :: IsStream t => (forall r. (a -> m r) -> m r) -> t m a -> t m a
400−consK k r = fromStream $ Stream $ \_ _ _ yld -> k (\x -> yld x (toStream r))
401−
402−-- XXX consK with concurrent callbacks
403−-- XXX Build a stream from a repeating callback function.
404−
405−-------------------------------------------------------------------------------
406−-- IsStream Stream
407−-------------------------------------------------------------------------------
408−
409−instance IsStream Stream where
410− toStream = id
411− fromStream = id
412−
413− {-# INLINE consM #-}
414− {-# SPECIALIZE consM :: IO a -> Stream IO a -> Stream IO a #-}
415− consM :: Monad m => m a -> Stream m a -> Stream m a
416− consM = consMSerial
417−
418− {-# INLINE (|:) #-}
419− {-# SPECIALIZE (|:) :: IO a -> Stream IO a -> Stream IO a #-}
420− (|:) :: Monad m => m a -> Stream m a -> Stream m a
421− (|:) = consMSerial
422−
423-------------------------------------------------------------------------------
218-------------------------------------------------------------------------------
424-- Deconstruction
219-- Deconstruction
425-------------------------------------------------------------------------------
220-------------------------------------------------------------------------------
@@ -429,43 +224,56 @@ uncons :: (IsStream t, Monad m) => t m a -> m (Maybe (a, t m a))
429uncons m =
224uncons m =
430 let stop = return Nothing
225 let stop = return Nothing
431 single a = return (Just (a, nil))
226 single a = return (Just (a, nil))
432− yieldk a r = return (Just (a, fromStream r))
227+ yieldk a r = return (Just (a, r))
433− in unStream (toStream m) defState stop single yieldk
228+ in foldStream defState yieldk single stop m
434
229
435-------------------------------------------------------------------------------
230-------------------------------------------------------------------------------
436-- Generation
231-- Generation
437-------------------------------------------------------------------------------
232-------------------------------------------------------------------------------
438
233
234+{-# INLINE_NORMAL build #-}
235+build :: IsStream t => forall a. (forall b. (a -> b -> b) -> b -> b) -> t m a
236+build g = g cons nil
237+
238+{-# INLINE_NORMAL _augment #-}
239+_augment
240+ :: IsStream t
241+ => forall a. (forall b. (a -> b -> b) -> b -> b) -> t m a -> t m a
242+_augment g xs = g cons xs
243+
244+{-# INLINE_NORMAL _buildM #-}
245+_buildM
246+ :: (IsStream t, MonadAsync m)
247+ => forall a. ((m a -> t m a -> t m a) -> t m a -> t m a) -> t m a
248+_buildM g = g consM nil
249+
439{-# INLINE unfoldr #-}
250{-# INLINE unfoldr #-}
440unfoldr :: IsStream t => (b -> Maybe (a, b)) -> b -> t m a
251unfoldr :: IsStream t => (b -> Maybe (a, b)) -> b -> t m a
441−unfoldr step = fromStream . go
252+unfoldr step b0 = build $ \cns nl ->
442− where
253+ let go s =
443− go s = Stream $ \_ stp _ yld ->
444− case step s of
254+ case step s of
445− Nothing -> stp
446− Just (a, b) -> yld a (go b)
255+ Just (a, b) -> a `cns` go b
256+ Nothing -> nl
257+ in go b0
447
258
448{-# INLINE unfoldrM #-}
259{-# INLINE unfoldrM #-}
449unfoldrM :: (IsStream t, MonadAsync m) => (b -> m (Maybe (a, b))) -> b -> t m a
260unfoldrM :: (IsStream t, MonadAsync m) => (b -> m (Maybe (a, b))) -> b -> t m a
450unfoldrM step = go
261unfoldrM step = go
451 where
262 where
452− go s = fromStream $ Stream $ \svr stp sng yld -> do
263+ go s = mkStream $ \st yld sng stp -> do
453 mayb <- step s
264 mayb <- step s
454 case mayb of
265 case mayb of
455 Nothing -> stp
266 Nothing -> stp
456 Just (a, b) ->
267 Just (a, b) ->
457− unStream (toStream (return a |: go b)) svr stp sng yld
268+ foldStreamShared st yld sng stp $ return a |: go b
458
269
459-------------------------------------------------------------------------------
270-------------------------------------------------------------------------------
460-- Special generation
271-- Special generation
461-------------------------------------------------------------------------------
272-------------------------------------------------------------------------------
462
273
274+{-# INLINE yield #-}
463yield :: IsStream t => a -> t m a
275yield :: IsStream t => a -> t m a
464−yield a = fromStream $ Stream $ \_ _ single _ -> single a
276+yield a = mkStream $ \_ _ single _ -> single a
465−
466−{-# INLINE yieldM #-}
467−yieldM :: (Monad m, IsStream t) => m a -> t m a
468−yieldM m = fromStream $ Stream $ \_ _ single _ -> m >>= single
469
277
470-- | Same as yieldM
278-- | Same as yieldM
471--
279--
@@ -484,14 +292,17 @@ once = yieldM
484-- Generate an infinite stream by repeating a pure value.
292-- Generate an infinite stream by repeating a pure value.
485--
293--
486-- @since 0.4.0
294-- @since 0.4.0
295+{-# INLINE repeat #-}
487repeat :: IsStream t => a -> t m a
296repeat :: IsStream t => a -> t m a
488repeat a = let x = cons a x in x
297repeat a = let x = cons a x in x
489
298
299+{-# INLINE replicateM #-}
490replicateM :: (IsStream t, MonadAsync m) => Int -> m a -> t m a
300replicateM :: (IsStream t, MonadAsync m) => Int -> m a -> t m a
491replicateM n m = go n
301replicateM n m = go n
492 where
302 where
493 go cnt = if cnt <= 0 then nil else m |: go (cnt - 1)
303 go cnt = if cnt <= 0 then nil else m |: go (cnt - 1)
494
304
305+{-# INLINE replicate #-}
495replicate :: IsStream t => Int -> a -> t m a
306replicate :: IsStream t => Int -> a -> t m a
496replicate n a = go n
307replicate n a = go n
497 where
308 where
@@ -518,47 +329,34 @@ fromList :: IsStream t => [a] -> t m a
518fromList = fromFoldable
329fromList = fromFoldable
519
330
520{-# INLINE fromStreamK #-}
331{-# INLINE fromStreamK #-}
521−fromStreamK :: Stream m a -> Stream m a
332+fromStreamK :: IsStream t => Stream m a -> t m a
522−fromStreamK = id
333+fromStreamK = fromStream
523
334
524-------------------------------------------------------------------------------
335-------------------------------------------------------------------------------
525-- Elimination by Folding
336-- Elimination by Folding
526-------------------------------------------------------------------------------
337-------------------------------------------------------------------------------
527
338
528−-- | Fold a stream by providing an SVar, a stop continuation, a singleton
529−-- continuation and a yield continuation.
530−foldStream
531− :: IsStream t
532− => State Stream m a
533− -> m r
534− -> (a -> m r)
535− -> (a -> t m a -> m r)
536− -> t m a
537− -> m r
538−foldStream st blank single step m =
539− let yieldk a x = step a (fromStream x)
540− in unStream (toStream m) st blank single yieldk
541−
542-- | Lazy right associative fold.
339-- | Lazy right associative fold.
340+{-# INLINE foldr #-}
543foldr :: (IsStream t, Monad m) => (a -> b -> b) -> b -> t m a -> m b
341foldr :: (IsStream t, Monad m) => (a -> b -> b) -> b -> t m a -> m b
544−foldr step acc m = go (toStream m)
342+foldr step acc m = go m
545 where
343 where
546 go m1 =
344 go m1 =
547 let stop = return acc
345 let stop = return acc
548 single a = return (step a acc)
346 single a = return (step a acc)
549 yieldk a r = go r >>= \b -> return (step a b)
347 yieldk a r = go r >>= \b -> return (step a b)
550− in unStream m1 defState stop single yieldk
348+ in foldStream defState yieldk single stop m1
551
349
552-- | Lazy right fold with a monadic step function.
350-- | Lazy right fold with a monadic step function.
553{-# INLINE foldrM #-}
351{-# INLINE foldrM #-}
554foldrM :: (IsStream t, Monad m) => (a -> b -> m b) -> b -> t m a -> m b
352foldrM :: (IsStream t, Monad m) => (a -> b -> m b) -> b -> t m a -> m b
555−foldrM step acc m = go (toStream m)
353+foldrM step acc m = go m
556 where
354 where
557 go m1 =
355 go m1 =
558 let stop = return acc
356 let stop = return acc
559 single a = step a acc
357 single a = step a acc
560 yieldk a r = go r >>= step a
358 yieldk a r = go r >>= step a
561− in unStream m1 defState stop single yieldk
359+ in foldStream defState yieldk single stop m1
562
360
563{-# INLINE foldr1 #-}
361{-# INLINE foldr1 #-}
564foldr1 :: (IsStream t, Monad m) => (a -> a -> a) -> t m a -> m (Maybe a)
362foldr1 :: (IsStream t, Monad m) => (a -> a -> a) -> t m a -> m (Maybe a)
@@ -566,13 +364,13 @@ foldr1 step m = do
566 r <- uncons m
364 r <- uncons m
567 case r of
365 case r of
568 Nothing -> return Nothing
366 Nothing -> return Nothing
569− Just (h, t) -> fmap Just (go h (toStream t))
367+ Just (h, t) -> fmap Just (go h t)
570 where
368 where
571 go p m1 =
369 go p m1 =
572 let stp = return p
370 let stp = return p
573 single a = return $ step a p
371 single a = return $ step a p
574 yieldk a r = fmap (step p) (go a r)
372 yieldk a r = fmap (step p) (go a r)
575− in unStream m1 defState stp single yieldk
373+ in foldStream defState yieldk single stp m1
576
374
577-- | Strict left fold with an extraction function. Like the standard strict
375-- | Strict left fold with an extraction function. Like the standard strict
578-- left fold, but applies a user supplied extraction function (the third
376-- left fold, but applies a user supplied extraction function (the third
@@ -581,28 +379,31 @@ foldr1 step m = do
581--
379--
582-- Note that the accumulator is always evaluated including the initial value.
380-- Note that the accumulator is always evaluated including the initial value.
583{-# INLINE foldx #-}
381{-# INLINE foldx #-}
584−foldx :: (IsStream t, Monad m)
382+foldx :: forall t m a b x. (IsStream t, Monad m)
585 => (x -> a -> x) -> x -> (x -> b) -> t m a -> m b
383 => (x -> a -> x) -> x -> (x -> b) -> t m a -> m b
586−foldx step begin done m = get $ go (toStream m) begin
384+foldx step begin done m = get $ go m begin
587 where
385 where
588 {-# NOINLINE get #-}
386 {-# NOINLINE get #-}
387+ get :: t m x -> m b
589 get m1 =
388 get m1 =
590 -- XXX we are not strictly evaluating the accumulator here. Is this
389 -- XXX we are not strictly evaluating the accumulator here. Is this
591 -- okay?
390 -- okay?
592 let single = return . done
391 let single = return . done
392+ -- XXX this is foldSingleton. why foldStreamShared?
593− in unStream m1 undefined undefined single undefined
393+ in foldStreamShared undefined undefined single undefined m1
594
394
595 -- Note, this can be implemented by making a recursive call to "go",
395 -- Note, this can be implemented by making a recursive call to "go",
596 -- however that is more expensive because of unnecessary recursion
396 -- however that is more expensive because of unnecessary recursion
597 -- that cannot be tail call optimized. Unfolding recursion explicitly via
397 -- that cannot be tail call optimized. Unfolding recursion explicitly via
598 -- continuations is much more efficient.
398 -- continuations is much more efficient.
399+ go :: t m a -> x -> t m x
599− go m1 !acc = Stream $ \_ _ sng yld ->
400+ go m1 !acc = mkStream $ \_ yld sng _ ->
600 let stop = sng acc
401 let stop = sng acc
601 single a = sng $ step acc a
402 single a = sng $ step acc a
602− yieldk a r =
403+ -- XXX this is foldNonEmptyStream
404+ yieldk a r = foldStream defState yld sng undefined $
603− let stream = go r (step acc a)
405+ go r (step acc a)
604− in unStream stream defState undefined sng yld
605− in unStream m1 defState stop single yieldk
406+ in foldStream defState yieldk single stop m1
606
407
607-- | Strict left associative fold.
408-- | Strict left associative fold.
608{-# INLINE foldl' #-}
409{-# INLINE foldl' #-}
@@ -611,17 +412,19 @@ foldl' step begin = foldx step begin id
611
412
612-- XXX replace the recursive "go" with explicit continuations.
413-- XXX replace the recursive "go" with explicit continuations.
613-- | Like 'foldx', but with a monadic step function.
414-- | Like 'foldx', but with a monadic step function.
415+{-# INLINABLE foldxM #-}
614foldxM :: (IsStream t, Monad m)
416foldxM :: (IsStream t, Monad m)
615 => (x -> a -> m x) -> m x -> (x -> m b) -> t m a -> m b
417 => (x -> a -> m x) -> m x -> (x -> m b) -> t m a -> m b
616−foldxM step begin done m = go begin (toStream m)
418+foldxM step begin done m = go begin m
617 where
419 where
618 go !acc m1 =
420 go !acc m1 =
619 let stop = acc >>= done
421 let stop = acc >>= done
620 single a = acc >>= \b -> step b a >>= done
422 single a = acc >>= \b -> step b a >>= done
621 yieldk a r = acc >>= \b -> step b a >>= \x -> go (return x) r
423 yieldk a r = acc >>= \b -> step b a >>= \x -> go (return x) r
622− in unStream m1 defState stop single yieldk
424+ in foldStream defState yieldk single stop m1
623
425
624-- | Like 'foldl'' but with a monadic step function.
426-- | Like 'foldl'' but with a monadic step function.
427+{-# INLINE foldlM' #-}
625foldlM' :: (IsStream t, Monad m) => (b -> a -> m b) -> b -> t m a -> m b
428foldlM' :: (IsStream t, Monad m) => (b -> a -> m b) -> b -> t m a -> m b
626foldlM' step begin = foldxM step (return begin) return
429foldlM' step begin = foldxM step (return begin) return
627
430
@@ -629,15 +432,18 @@ foldlM' step begin = foldxM step (return begin) return
629-- Specialized folds
432-- Specialized folds
630------------------------------------------------------------------------------
433------------------------------------------------------------------------------
631
434
435+-- |
436+-- > runStream = foldl' (\_ _ -> ()) ()
437+-- > runStream = mapM_ (\_ -> return ())
632{-# INLINE runStream #-}
438{-# INLINE runStream #-}
633runStream :: (Monad m, IsStream t) => t m a -> m ()
439runStream :: (Monad m, IsStream t) => t m a -> m ()
634−runStream m = go (toStream m)
440+runStream = go
635 where
441 where
636 go m1 =
442 go m1 =
637 let stop = return ()
443 let stop = return ()
638 single _ = return ()
444 single _ = return ()
639− yieldk _ r = go (toStream r)
445+ yieldk _ r = go r
640− in unStream m1 defState stop single yieldk
446+ in foldStream defState yieldk single stop m1
641
447
642{-# INLINE null #-}
448{-# INLINE null #-}
643null :: (IsStream t, Monad m) => t m a -> m Bool
449null :: (IsStream t, Monad m) => t m a -> m Bool
@@ -645,7 +451,7 @@ null m =
645 let stop = return True
451 let stop = return True
646 single _ = return False
452 single _ = return False
647 yieldk _ _ = return False
453 yieldk _ _ = return False
648− in unStream (toStream m) defState stop single yieldk
454+ in foldStream defState yieldk single stop m
649
455
650{-# INLINE head #-}
456{-# INLINE head #-}
651head :: (IsStream t, Monad m) => t m a -> m (Maybe a)
457head :: (IsStream t, Monad m) => t m a -> m (Maybe a)
@@ -653,69 +459,71 @@ head m =
653 let stop = return Nothing
459 let stop = return Nothing
654 single a = return (Just a)
460 single a = return (Just a)
655 yieldk a _ = return (Just a)
461 yieldk a _ = return (Just a)
656− in unStream (toStream m) defState stop single yieldk
462+ in foldStream defState yieldk single stop m
657
463
658{-# INLINE tail #-}
464{-# INLINE tail #-}
659tail :: (IsStream t, Monad m) => t m a -> m (Maybe (t m a))
465tail :: (IsStream t, Monad m) => t m a -> m (Maybe (t m a))
660tail m =
466tail m =
661 let stop = return Nothing
467 let stop = return Nothing
662 single _ = return $ Just nil
468 single _ = return $ Just nil
663− yieldk _ r = return $ Just $ fromStream r
469+ yieldk _ r = return $ Just r
664− in unStream (toStream m) defState stop single yieldk
470+ in foldStream defState yieldk single stop m
665
471
666{-# INLINE init #-}
472{-# INLINE init #-}
667init :: (IsStream t, Monad m) => t m a -> m (Maybe (t m a))
473init :: (IsStream t, Monad m) => t m a -> m (Maybe (t m a))
668−init m = go1 (toStream m)
474+init m = go1 m
669 where
475 where
670 go1 m1 = do
476 go1 m1 = do
671 r <- uncons m1
477 r <- uncons m1
672 case r of
478 case r of
673 Nothing -> return Nothing
479 Nothing -> return Nothing
674− Just (h, t) -> return . Just . fromStream $ go h t
480+ Just (h, t) -> return . Just $ go h t
675− go p m1 = Stream $ \_ stp sng yld ->
481+ go p m1 = mkStream $ \_ yld sng stp ->
676 let single _ = sng p
482 let single _ = sng p
677 yieldk a x = yld p $ go a x
483 yieldk a x = yld p $ go a x
678− in unStream m1 defState stp single yieldk
484+ in foldStream defState yieldk single stp m1
679
485
680{-# INLINE elem #-}
486{-# INLINE elem #-}
681elem :: (IsStream t, Monad m, Eq a) => a -> t m a -> m Bool
487elem :: (IsStream t, Monad m, Eq a) => a -> t m a -> m Bool
682−elem e m = go (toStream m)
488+elem e m = go m
683 where
489 where
684 go m1 =
490 go m1 =
685 let stop = return False
491 let stop = return False
686 single a = return (a == e)
492 single a = return (a == e)
687 yieldk a r = if a == e then return True else go r
493 yieldk a r = if a == e then return True else go r
688− in unStream m1 defState stop single yieldk
494+ in foldStream defState yieldk single stop m1
689
495
690{-# INLINE notElem #-}
496{-# INLINE notElem #-}
691notElem :: (IsStream t, Monad m, Eq a) => a -> t m a -> m Bool
497notElem :: (IsStream t, Monad m, Eq a) => a -> t m a -> m Bool
692−notElem e m = go (toStream m)
498+notElem e m = go m
693 where
499 where
694 go m1 =
500 go m1 =
695 let stop = return True
501 let stop = return True
696 single a = return (a /= e)
502 single a = return (a /= e)
697 yieldk a r = if a == e then return False else go r
503 yieldk a r = if a == e then return False else go r
698− in unStream m1 defState stop single yieldk
504+ in foldStream defState yieldk single stop m1
699
505
506+{-# INLINABLE all #-}
700all :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> m Bool
507all :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> m Bool
701−all p m = go (toStream m)
508+all p m = go m
702 where
509 where
703 go m1 =
510 go m1 =
704 let single a | p a = return True
511 let single a | p a = return True
705 | otherwise = return False
512 | otherwise = return False
706 yieldk a r | p a = go r
513 yieldk a r | p a = go r
707 | otherwise = return False
514 | otherwise = return False
708− in unStream m1 defState (return True) single yieldk
515+ in foldStream defState yieldk single (return True) m1
709
516
517+{-# INLINABLE any #-}
710any :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> m Bool
518any :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> m Bool
711−any p m = go (toStream m)
519+any p m = go m
712 where
520 where
713 go m1 =
521 go m1 =
714 let single a | p a = return True
522 let single a | p a = return True
715 | otherwise = return False
523 | otherwise = return False
716 yieldk a r | p a = return True
524 yieldk a r | p a = return True
717 | otherwise = go r
525 | otherwise = go r
718− in unStream m1 defState (return False) single yieldk
526+ in foldStream defState yieldk single (return False) m1
719
527
720-- | Extract the last element of the stream, if any.
528-- | Extract the last element of the stream, if any.
721{-# INLINE last #-}
529{-# INLINE last #-}
@@ -724,13 +532,13 @@ last = foldx (\_ y -> Just y) Nothing id
724
532
725{-# INLINE minimum #-}
533{-# INLINE minimum #-}
726minimum :: (IsStream t, Monad m, Ord a) => t m a -> m (Maybe a)
534minimum :: (IsStream t, Monad m, Ord a) => t m a -> m (Maybe a)
727−minimum m = go Nothing (toStream m)
535+minimum m = go Nothing m
728 where
536 where
729 go Nothing m1 =
537 go Nothing m1 =
730 let stop = return Nothing
538 let stop = return Nothing
731 single a = return (Just a)
539 single a = return (Just a)
732 yieldk a r = go (Just a) r
540 yieldk a r = go (Just a) r
733− in unStream m1 defState stop single yieldk
541+ in foldStream defState yieldk single stop m1
734
542
735 go (Just res) m1 =
543 go (Just res) m1 =
736 let stop = return (Just res)
544 let stop = return (Just res)
@@ -742,19 +550,19 @@ minimum m = go Nothing (toStream m)
742 if res <= a
550 if res <= a
743 then go (Just res) r
551 then go (Just res) r
744 else go (Just a) r
552 else go (Just a) r
745− in unStream m1 defState stop single yieldk
553+ in foldStream defState yieldk single stop m1
746
554
747{-# INLINE minimumBy #-}
555{-# INLINE minimumBy #-}
748minimumBy
556minimumBy
749 :: (IsStream t, Monad m)
557 :: (IsStream t, Monad m)
750 => (a -> a -> Ordering) -> t m a -> m (Maybe a)
558 => (a -> a -> Ordering) -> t m a -> m (Maybe a)
751−minimumBy cmp m = go Nothing (toStream m)
559+minimumBy cmp m = go Nothing m
752 where
560 where
753 go Nothing m1 =
561 go Nothing m1 =
754 let stop = return Nothing
562 let stop = return Nothing
755 single a = return (Just a)
563 single a = return (Just a)
756 yieldk a r = go (Just a) r
564 yieldk a r = go (Just a) r
757− in unStream m1 defState stop single yieldk
565+ in foldStream defState yieldk single stop m1
758
566
759 go (Just res) m1 =
567 go (Just res) m1 =
760 let stop = return (Just res)
568 let stop = return (Just res)
@@ -764,17 +572,17 @@ minimumBy cmp m = go Nothing (toStream m)
764 yieldk a r = case cmp res a of
572 yieldk a r = case cmp res a of
765 GT -> go (Just a) r
573 GT -> go (Just a) r
766 _ -> go (Just res) r
574 _ -> go (Just res) r
767− in unStream m1 defState stop single yieldk
575+ in foldStream defState yieldk single stop m1
768
576
769{-# INLINE maximum #-}
577{-# INLINE maximum #-}
770maximum :: (IsStream t, Monad m, Ord a) => t m a -> m (Maybe a)
578maximum :: (IsStream t, Monad m, Ord a) => t m a -> m (Maybe a)
771−maximum m = go Nothing (toStream m)
579+maximum m = go Nothing m
772 where
580 where
773 go Nothing m1 =
581 go Nothing m1 =
774 let stop = return Nothing
582 let stop = return Nothing
775 single a = return (Just a)
583 single a = return (Just a)
776 yieldk a r = go (Just a) r
584 yieldk a r = go (Just a) r
777− in unStream m1 defState stop single yieldk
585+ in foldStream defState yieldk single stop m1
778
586
779 go (Just res) m1 =
587 go (Just res) m1 =
780 let stop = return (Just res)
588 let stop = return (Just res)
@@ -786,17 +594,17 @@ maximum m = go Nothing (toStream m)
786 if res <= a
594 if res <= a
787 then go (Just a) r
595 then go (Just a) r
788 else go (Just res) r
596 else go (Just res) r
789− in unStream m1 defState stop single yieldk
597+ in foldStream defState yieldk single stop m1
790
598
791{-# INLINE maximumBy #-}
599{-# INLINE maximumBy #-}
792maximumBy :: (IsStream t, Monad m) => (a -> a -> Ordering) -> t m a -> m (Maybe a)
600maximumBy :: (IsStream t, Monad m) => (a -> a -> Ordering) -> t m a -> m (Maybe a)
793−maximumBy cmp m = go Nothing (toStream m)
601+maximumBy cmp m = go Nothing m
794 where
602 where
795 go Nothing m1 =
603 go Nothing m1 =
796 let stop = return Nothing
604 let stop = return Nothing
797 single a = return (Just a)
605 single a = return (Just a)
798 yieldk a r = go (Just a) r
606 yieldk a r = go (Just a) r
799− in unStream m1 defState stop single yieldk
607+ in foldStream defState yieldk single stop m1
800
608
801 go (Just res) m1 =
609 go (Just res) m1 =
802 let stop = return (Just res)
610 let stop = return (Just res)
@@ -806,11 +614,11 @@ maximumBy cmp m = go Nothing (toStream m)
806 yieldk a r = case cmp res a of
614 yieldk a r = case cmp res a of
807 GT -> go (Just res) r
615 GT -> go (Just res) r
808 _ -> go (Just a) r
616 _ -> go (Just a) r
809− in unStream m1 defState stop single yieldk
617+ in foldStream defState yieldk single stop m1
810
618
811{-# INLINE (!!) #-}
619{-# INLINE (!!) #-}
812(!!) :: (IsStream t, Monad m) => t m a -> Int -> m (Maybe a)
620(!!) :: (IsStream t, Monad m) => t m a -> Int -> m (Maybe a)
813−m !! i = go i (toStream m)
621+m !! i = go i m
814 where
622 where
815 go n m1 =
623 go n m1 =
816 let single a | n == 0 = return $ Just a
624 let single a | n == 0 = return $ Just a
@@ -818,22 +626,22 @@ m !! i = go i (toStream m)
818 yieldk a x | n < 0 = return Nothing
626 yieldk a x | n < 0 = return Nothing
819 | n == 0 = return $ Just a
627 | n == 0 = return $ Just a
820 | otherwise = go (n - 1) x
628 | otherwise = go (n - 1) x
821− in unStream m1 defState (return Nothing) single yieldk
629+ in foldStream defState yieldk single (return Nothing) m1
822
630
823{-# INLINE lookup #-}
631{-# INLINE lookup #-}
824lookup :: (IsStream t, Monad m, Eq a) => a -> t m (a, b) -> m (Maybe b)
632lookup :: (IsStream t, Monad m, Eq a) => a -> t m (a, b) -> m (Maybe b)
825−lookup e m = go (toStream m)
633+lookup e m = go m
826 where
634 where
827 go m1 =
635 go m1 =
828 let single (a, b) | a == e = return $ Just b
636 let single (a, b) | a == e = return $ Just b
829 | otherwise = return Nothing
637 | otherwise = return Nothing
830 yieldk (a, b) x | a == e = return $ Just b
638 yieldk (a, b) x | a == e = return $ Just b
831 | otherwise = go x
639 | otherwise = go x
832− in unStream m1 defState (return Nothing) single yieldk
640+ in foldStream defState yieldk single (return Nothing) m1
833
641
834{-# INLINE findM #-}
642{-# INLINE findM #-}
835findM :: (IsStream t, Monad m) => (a -> m Bool) -> t m a -> m (Maybe a)
643findM :: (IsStream t, Monad m) => (a -> m Bool) -> t m a -> m (Maybe a)
836−findM p m = go (toStream m)
644+findM p m = go m
837 where
645 where
838 go m1 =
646 go m1 =
839 let single a = do
647 let single a = do
@@ -842,7 +650,7 @@ findM p m = go (toStream m)
842 yieldk a x = do
650 yieldk a x = do
843 b <- p a
651 b <- p a
844 if b then return $ Just a else go x
652 if b then return $ Just a else go x
845− in unStream m1 defState (return Nothing) single yieldk
653+ in foldStream defState yieldk single (return Nothing) m1
846
654
847{-# INLINE find #-}
655{-# INLINE find #-}
848find :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> m (Maybe a)
656find :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> m (Maybe a)
@@ -850,14 +658,15 @@ find p = findM (return . p)
850
658
851{-# INLINE findIndices #-}
659{-# INLINE findIndices #-}
852findIndices :: IsStream t => (a -> Bool) -> t m a -> t m Int
660findIndices :: IsStream t => (a -> Bool) -> t m a -> t m Int
853−findIndices p = fromStream . go 0 . toStream
661+findIndices p = go 0
854 where
662 where
855− go offset m1 = Stream $ \st stp sng yld ->
663+ go offset m1 = mkStream $ \st yld sng stp ->
856 let single a | p a = sng offset
664 let single a | p a = sng offset
857 | otherwise = stp
665 | otherwise = stp
858 yieldk a x | p a = yld offset $ go (offset + 1) x
666 yieldk a x | p a = yld offset $ go (offset + 1) x
667+ | otherwise = foldStream (adaptState st) yld sng stp $
859− | otherwise = unStream (go (offset + 1) x) st stp sng yld
668+ go (offset + 1) x
860− in unStream m1 (rstState st) stp single yieldk
669+ in foldStream (adaptState st) yieldk single stp m1
861
670
862------------------------------------------------------------------------------
671------------------------------------------------------------------------------
863-- Map and Fold
672-- Map and Fold
@@ -865,14 +674,15 @@ findIndices p = fromStream . go 0 . toStream
865
674
866-- | Apply a monadic action to each element of the stream and discard the
675-- | Apply a monadic action to each element of the stream and discard the
867-- output of the action.
676-- output of the action.
677+{-# INLINE mapM_ #-}
868mapM_ :: (IsStream t, Monad m) => (a -> m b) -> t m a -> m ()
678mapM_ :: (IsStream t, Monad m) => (a -> m b) -> t m a -> m ()
869−mapM_ f m = go (toStream m)
679+mapM_ f m = go m
870 where
680 where
871 go m1 =
681 go m1 =
872 let stop = return ()
682 let stop = return ()
873 single a = void (f a)
683 single a = void (f a)
874 yieldk a r = f a >> go r
684 yieldk a r = f a >> go r
875− in unStream m1 defState stop single yieldk
685+ in foldStream defState yieldk single stop m1
876
686
877------------------------------------------------------------------------------
687------------------------------------------------------------------------------
878-- Converting folds
688-- Converting folds
@@ -893,14 +703,14 @@ toStreamK = id
893{-# INLINE scanx #-}
703{-# INLINE scanx #-}
894scanx :: IsStream t => (x -> a -> x) -> x -> (x -> b) -> t m a -> t m b
704scanx :: IsStream t => (x -> a -> x) -> x -> (x -> b) -> t m a -> t m b
895scanx step begin done m =
705scanx step begin done m =
896− cons (done begin) $ fromStream $ go (toStream m) begin
706+ cons (done begin) $ go m begin
897 where
707 where
898− go m1 !acc = Stream $ \st stp sng yld ->
708+ go m1 !acc = mkStream $ \st yld sng stp ->
899 let single a = sng (done $ step acc a)
709 let single a = sng (done $ step acc a)
900 yieldk a r =
710 yieldk a r =
901 let s = step acc a
711 let s = step acc a
902 in yld (done s) (go r s)
712 in yld (done s) (go r s)
903− in unStream m1 (rstState st) stp single yieldk
713+ in foldStream (adaptState st) yieldk single stp m1
904
714
905{-# INLINE scanl' #-}
715{-# INLINE scanl' #-}
906scanl' :: IsStream t => (b -> a -> b) -> b -> t m a -> t m b
716scanl' :: IsStream t => (b -> a -> b) -> b -> t m a -> t m b
@@ -912,91 +722,84 @@ scanl' step begin = scanx step begin id
912
722
913{-# INLINE filter #-}
723{-# INLINE filter #-}
914filter :: IsStream t => (a -> Bool) -> t m a -> t m a
724filter :: IsStream t => (a -> Bool) -> t m a -> t m a
915−filter p m = fromStream $ go (toStream m)
725+filter p m = go m
916 where
726 where
917− go m1 = Stream $ \st stp sng yld ->
727+ go m1 = mkStream $ \st yld sng stp ->
918 let single a | p a = sng a
728 let single a | p a = sng a
919 | otherwise = stp
729 | otherwise = stp
920 yieldk a r | p a = yld a (go r)
730 yieldk a r | p a = yld a (go r)
921− | otherwise = unStream r (rstState st) stp single yieldk
731+ | otherwise = foldStream st yieldk single stp r
922− in unStream m1 (rstState st) stp single yieldk
732+ in foldStream st yieldk single stp m1
923
733
924{-# INLINE take #-}
734{-# INLINE take #-}
925take :: IsStream t => Int -> t m a -> t m a
735take :: IsStream t => Int -> t m a -> t m a
926−take n m = fromStream $ go n (toStream m)
736+take n m = go n m
927 where
737 where
928− go n1 m1 = Stream $ \st stp sng yld ->
738+ go n1 m1 = mkStream $ \st yld sng stp ->
929 let yieldk a r = yld a (go (n1 - 1) r)
739 let yieldk a r = yld a (go (n1 - 1) r)
930 in if n1 <= 0
740 in if n1 <= 0
931 then stp
741 then stp
932− else unStream m1 (rstState st) stp sng yieldk
742+ else foldStream st yieldk sng stp m1
933
743
934{-# INLINE takeWhile #-}
744{-# INLINE takeWhile #-}
935takeWhile :: IsStream t => (a -> Bool) -> t m a -> t m a
745takeWhile :: IsStream t => (a -> Bool) -> t m a -> t m a
936−takeWhile p m = fromStream $ go (toStream m)
746+takeWhile p m = go m
937 where
747 where
938− go m1 = Stream $ \st stp sng yld ->
748+ go m1 = mkStream $ \st yld sng stp ->
939 let single a | p a = sng a
749 let single a | p a = sng a
940 | otherwise = stp
750 | otherwise = stp
941 yieldk a r | p a = yld a (go r)
751 yieldk a r | p a = yld a (go r)
942 | otherwise = stp
752 | otherwise = stp
943− in unStream m1 (rstState st) stp single yieldk
753+ in foldStream st yieldk single stp m1
944
754
755+{-# INLINE drop #-}
945drop :: IsStream t => Int -> t m a -> t m a
756drop :: IsStream t => Int -> t m a -> t m a
946−drop n m = fromStream $ Stream $ \st stp sng yld ->
757+drop n m = fromStream $ unShare (go n (toStream m))
947− unStream (go n (toStream m)) (rstState st) stp sng yld
948 where
758 where
949− go n1 m1 = Stream $ \st stp sng yld ->
759+ go n1 m1 = mkStream $ \st yld sng stp ->
950 let single _ = stp
760 let single _ = stp
951− yieldk _ r = (unStream $ go (n1 - 1) r) st stp sng yld
761+ yieldk _ r = foldStreamShared st yld sng stp $ go (n1 - 1) r
952 -- Somehow "<=" check performs better than a ">"
762 -- Somehow "<=" check performs better than a ">"
953 in if n1 <= 0
763 in if n1 <= 0
954− then unStream m1 st stp sng yld
764+ then foldStreamShared st yld sng stp m1
955− else unStream m1 st stp single yieldk
765+ else foldStreamShared st yieldk single stp m1
956
766
957{-# INLINE dropWhile #-}
767{-# INLINE dropWhile #-}
958dropWhile :: IsStream t => (a -> Bool) -> t m a -> t m a
768dropWhile :: IsStream t => (a -> Bool) -> t m a -> t m a
959−dropWhile p m = fromStream $ go (toStream m)
769+dropWhile p m = go m
960 where
770 where
961− go m1 = Stream $ \st stp sng yld ->
771+ go m1 = mkStream $ \st yld sng stp ->
962 let single a | p a = stp
772 let single a | p a = stp
963 | otherwise = sng a
773 | otherwise = sng a
964− yieldk a r | p a = unStream r (rstState st) stp single yieldk
774+ yieldk a r | p a = foldStream st yieldk single stp r
965 | otherwise = yld a r
775 | otherwise = yld a r
966− in unStream m1 (rstState st) stp single yieldk
776+ in foldStream st yieldk single stp m1
967
777
968-------------------------------------------------------------------------------
778-------------------------------------------------------------------------------
969-- Mapping
779-- Mapping
970-------------------------------------------------------------------------------
780-------------------------------------------------------------------------------
971
781
972−{-# INLINE map #-}
973−map :: (IsStream t, Monad m) => (a -> b) -> t m a -> t m b
974−map f m = fromStream $ Stream $ \st stp sng yld ->
975− let single = sng . f
976− yieldk a r = yld (f a) (fmap f r)
977− in unStream (toStream m) (rstState st) stp single yieldk
978−
979-- Be careful when modifying this, this uses a consM (|:) deliberately to allow
782-- Be careful when modifying this, this uses a consM (|:) deliberately to allow
980-- other stream types to overload it.
783-- other stream types to overload it.
981{-# INLINE mapM #-}
784{-# INLINE mapM #-}
982mapM :: (IsStream t, MonadAsync m) => (a -> m b) -> t m a -> t m b
785mapM :: (IsStream t, MonadAsync m) => (a -> m b) -> t m a -> t m b
983−mapM f m = go (toStream m)
786+mapM f m = go m
984 where
787 where
985− go m1 = fromStream $ Stream $ \st stp sng yld ->
788+ go m1 = mkStream $ \st yld sng stp ->
986 let single a = f a >>= sng
789 let single a = f a >>= sng
987− yieldk a r = unStream (toStream (f a |: go r)) st stp sng yld
790+ yieldk a r = foldStreamShared st yld sng stp $ f a |: go r
988− in unStream m1 (rstState st) stp single yieldk
791+ in foldStream (adaptState st) yieldk single stp m1
989
792
990-- Be careful when modifying this, this uses a consM (|:) deliberately to allow
793-- Be careful when modifying this, this uses a consM (|:) deliberately to allow
991-- other stream types to overload it.
794-- other stream types to overload it.
992{-# INLINE sequence #-}
795{-# INLINE sequence #-}
993sequence :: (IsStream t, MonadAsync m) => t m (m a) -> t m a
796sequence :: (IsStream t, MonadAsync m) => t m (m a) -> t m a
994−sequence m = go (toStream m)
797+sequence m = go m
995 where
798 where
996− go m1 = fromStream $ Stream $ \st stp sng yld ->
799+ go m1 = mkStream $ \st yld sng stp ->
997 let single ma = ma >>= sng
800 let single ma = ma >>= sng
998− yieldk ma r = unStream (toStream $ ma |: go r) st stp sng yld
801+ yieldk ma r = foldStreamShared st yld sng stp $ ma |: go r
999− in unStream m1 (rstState st) stp single yieldk
802+ in foldStream (adaptState st) yieldk single stp m1
1000
803
1001-------------------------------------------------------------------------------
804-------------------------------------------------------------------------------
1002-- Inserting
805-- Inserting
@@ -1004,21 +807,21 @@ sequence m = go (toStream m)
1004
807
1005{-# INLINE intersperseM #-}
808{-# INLINE intersperseM #-}
1006intersperseM :: (IsStream t, MonadAsync m) => m a -> t m a -> t m a
809intersperseM :: (IsStream t, MonadAsync m) => m a -> t m a -> t m a
1007−intersperseM a m = fromStream $ prependingStart (toStream m)
810+intersperseM a m = prependingStart m
1008 where
811 where
1009− prependingStart m1 = Stream $ \st stp sng yld ->
812+ prependingStart m1 = mkStream $ \st yld sng stp ->
1010− let yieldk i x = unStream (return i |: go x) st stp sng yld
813+ let yieldk i x = foldStreamShared st yld sng stp $ return i |: go x
1011− in unStream m1 (rstState st) stp sng yieldk
814+ in foldStream st yieldk sng stp m1
1012− go m2 = fromStream $ Stream $ \st stp sng yld ->
815+ go m2 = mkStream $ \st yld sng stp ->
1013− let single i = unStream (a |: yield i) st stp sng yld
816+ let single i = foldStreamShared st yld sng stp $ a |: yield i
1014− yieldk i x = unStream (a |: return i |: go x) st stp sng yld
817+ yieldk i x = foldStreamShared st yld sng stp $ a |: return i |: go x
1015− in unStream m2 (rstState st) stp single yieldk
818+ in foldStream st yieldk single stp m2
1016
819
1017{-# INLINE insertBy #-}
820{-# INLINE insertBy #-}
1018insertBy :: IsStream t => (a -> a -> Ordering) -> a -> t m a -> t m a
821insertBy :: IsStream t => (a -> a -> Ordering) -> a -> t m a -> t m a
1019−insertBy cmp x m = fromStream $ go (toStream m)
822+insertBy cmp x m = go m
1020 where
823 where
1021− go m1 = Stream $ \st _ _ yld ->
824+ go m1 = mkStream $ \st yld _ _ ->
1022 let single a = case cmp x a of
825 let single a = case cmp x a of
1023 GT -> yld a (yield x)
826 GT -> yld a (yield x)
1024 _ -> yld x (yield a)
827 _ -> yld x (yield a)
@@ -1026,7 +829,7 @@ insertBy cmp x m = fromStream $ go (toStream m)
1026 yieldk a r = case cmp x a of
829 yieldk a r = case cmp x a of
1027 GT -> yld a (go r)
830 GT -> yld a (go r)
1028 _ -> yld x (a `cons` r)
831 _ -> yld x (a `cons` r)
1029− in unStream m1 (rstState st) stop single yieldk
832+ in foldStream st yieldk single stop m1
1030
833
1031------------------------------------------------------------------------------
834------------------------------------------------------------------------------
1032-- Deleting
835-- Deleting
@@ -1034,14 +837,14 @@ insertBy cmp x m = fromStream $ go (toStream m)
1034
837
1035{-# INLINE deleteBy #-}
838{-# INLINE deleteBy #-}
1036deleteBy :: IsStream t => (a -> a -> Bool) -> a -> t m a -> t m a
839deleteBy :: IsStream t => (a -> a -> Bool) -> a -> t m a -> t m a
1037−deleteBy eq x m = fromStream $ go (toStream m)
840+deleteBy eq x m = go m
1038 where
841 where
1039− go m1 = Stream $ \st stp sng yld ->
842+ go m1 = mkStream $ \st yld sng stp ->
1040 let single a = if eq x a then stp else sng a
843 let single a = if eq x a then stp else sng a
1041 yieldk a r = if eq x a
844 yieldk a r = if eq x a
1042− then unStream r (rstState st) stp sng yld
845+ then foldStream st yld sng stp r
1043 else yld a (go r)
846 else yld a (go r)
1044− in unStream m1 (rstState st) stp single yieldk
847+ in foldStream st yieldk single stp m1
1045
848
1046-------------------------------------------------------------------------------
849-------------------------------------------------------------------------------
1047-- Map and Filter
850-- Map and Filter
@@ -1049,70 +852,67 @@ deleteBy eq x m = fromStream $ go (toStream m)
1049
852
1050{-# INLINE mapMaybe #-}
853{-# INLINE mapMaybe #-}
1051mapMaybe :: IsStream t => (a -> Maybe b) -> t m a -> t m b
854mapMaybe :: IsStream t => (a -> Maybe b) -> t m a -> t m b
1052−mapMaybe f m = go (toStream m)
855+mapMaybe f m = go m
1053 where
856 where
1054− go m1 = fromStream $ Stream $ \st stp sng yld ->
857+ go m1 = mkStream $ \st yld sng stp ->
1055 let single a = case f a of
858 let single a = case f a of
1056 Just b -> sng b
859 Just b -> sng b
1057 Nothing -> stp
860 Nothing -> stp
1058 yieldk a r = case f a of
861 yieldk a r = case f a of
1059− Just b -> yld b (toStream $ go r)
862+ Just b -> yld b $ go r
1060− Nothing -> unStream r (rstState st) stp single yieldk
863+ Nothing -> foldStream (adaptState st) yieldk single stp r
1061− in unStream m1 (rstState st) stp single yieldk
864+ in foldStream (adaptState st) yieldk single stp m1
1062
865
1063------------------------------------------------------------------------------
866------------------------------------------------------------------------------
1064-- Serial Zipping
867-- Serial Zipping
1065------------------------------------------------------------------------------
868------------------------------------------------------------------------------
1066
869
1067−{-# INLINE zipWithS #-}
870+-- | Zip two streams serially using a pure zipping function.
1068−zipWithS :: (a -> b -> c) -> Stream m a -> Stream m b -> Stream m c
871+--
1069−zipWithS f = go
872+-- @since 0.1.0
873+{-# INLINABLE zipWith #-}
874+zipWith :: IsStream t => (a -> b -> c) -> t m a -> t m b -> t m c
875+zipWith f = go
1070 where
876 where
1071− go mx my = Stream $ \st stp sng yld -> do
877+ go mx my = mkStream $ \st yld sng stp -> do
1072 let merge a ra =
878 let merge a ra =
1073 let single2 b = sng (f a b)
879 let single2 b = sng (f a b)
1074 yield2 b rb = yld (f a b) (go ra rb)
880 yield2 b rb = yld (f a b) (go ra rb)
1075− in unStream my (rstState st) stp single2 yield2
881+ in foldStream (adaptState st) yield2 single2 stp my
1076 let single1 a = merge a nil
882 let single1 a = merge a nil
1077 yield1 = merge
883 yield1 = merge
1078− unStream mx (rstState st) stp single1 yield1
884+ foldStream (adaptState st) yield1 single1 stp mx
1079−
1080−-- | Zip two streams serially using a pure zipping function.
1081−--
1082−-- @since 0.1.0
1083−{-# INLINABLE zipWith #-}
1084−zipWith :: IsStream t => (a -> b -> c) -> t m a -> t m b -> t m c
1085−zipWith f m1 m2 = fromStream $ zipWithS f (toStream m1) (toStream m2)
1086
885
1087-- | Zip two streams serially using a monadic zipping function.
886-- | Zip two streams serially using a monadic zipping function.
1088--
887--
1089-- @since 0.1.0
888-- @since 0.1.0
889+{-# INLINABLE zipWithM #-}
1090zipWithM :: (IsStream t, Monad m) => (a -> b -> m c) -> t m a -> t m b -> t m c
890zipWithM :: (IsStream t, Monad m) => (a -> b -> m c) -> t m a -> t m b -> t m c
1091−zipWithM f m1 m2 = fromStream $ go (toStream m1) (toStream m2)
891+zipWithM f m1 m2 = go m1 m2
1092 where
892 where
1093− go mx my = Stream $ \st stp sng yld -> do
893+ go mx my = mkStream $ \st yld sng stp -> do
1094 let merge a ra =
894 let merge a ra =
1095− let runIt x = unStream x (rstState st) stp sng yld
895+ let runIt x = foldStream st yld sng stp x
1096 single2 b = f a b >>= sng
896 single2 b = f a b >>= sng
1097 yield2 b rb = f a b >>= \x -> runIt (x `cons` go ra rb)
897 yield2 b rb = f a b >>= \x -> runIt (x `cons` go ra rb)
1098− in unStream my (rstState st) stp single2 yield2
898+ in foldStream (adaptState st) yield2 single2 stp my
1099 let single1 a = merge a nil
899 let single1 a = merge a nil
1100 yield1 = merge
900 yield1 = merge
1101− unStream mx (rstState st) stp single1 yield1
901+ foldStream (adaptState st) yield1 single1 stp mx
1102
902
1103------------------------------------------------------------------------------
903------------------------------------------------------------------------------
1104-- Merging
904-- Merging
1105------------------------------------------------------------------------------
905------------------------------------------------------------------------------
1106
906
1107−{-# INLINE mergeByS #-}
907+{-# INLINE mergeByM #-}
1108−mergeByS
908+mergeByM
1109− :: Monad m
909+ :: (IsStream t, Monad m)
1110− => (a -> a -> m Ordering) -> Stream m a -> Stream m a -> Stream m a
910+ => (a -> a -> m Ordering) -> t m a -> t m a -> t m a
1111−mergeByS cmp = go
911+mergeByM cmp = go
1112 where
912 where
1113− go mx my = Stream $ \st stp sng yld -> do
913+ go mx my = mkStream $ \st yld sng stp -> do
1114 let mergeWithY a ra =
914 let mergeWithY a ra =
1115− let stop2 = unStream mx (rstState st) stp sng yld
915+ let stop2 = foldStream st yld sng stp mx
1116 single2 b = do
916 single2 b = do
1117 r <- cmp a b
917 r <- cmp a b
1118 case r of
918 case r of
@@ -1123,17 +923,11 @@ mergeByS cmp = go
1123 case r of
923 case r of
1124 GT -> yld b (go (a `cons` ra) rb)
924 GT -> yld b (go (a `cons` ra) rb)
1125 _ -> yld a (go ra (b `cons` rb))
925 _ -> yld a (go ra (b `cons` rb))
1126− in unStream my (rstState st) stop2 single2 yield2
926+ in foldStream st yield2 single2 stop2 my
1127− let stopX = unStream my (rstState st) stp sng yld
927+ let stopX = foldStream st yld sng stp my
1128 singleX a = mergeWithY a nil
928 singleX a = mergeWithY a nil
1129 yieldX = mergeWithY
929 yieldX = mergeWithY
1130− unStream mx (rstState st) stopX singleX yieldX
930+ foldStream st yieldX singleX stopX mx
1131−
1132−{-# INLINABLE mergeByM #-}
1133−mergeByM
1134− :: (IsStream t, Monad m)
1135− => (a -> a -> m Ordering) -> t m a -> t m a -> t m a
1136−mergeByM f m1 m2 = fromStream $ mergeByS f (toStream m1) (toStream m2)
1137
931
1138{-# INLINABLE mergeBy #-}
932{-# INLINABLE mergeBy #-}
1139mergeBy
933mergeBy
@@ -1151,48 +945,14 @@ the m = do
1151 r <- uncons m
945 r <- uncons m
1152 case r of
946 case r of
1153 Nothing -> return Nothing
947 Nothing -> return Nothing
1154− Just (h, t) -> go h (toStream t)
948+ Just (h, t) -> go h t
1155 where
949 where
1156 go h m1 =
950 go h m1 =
1157 let single a | h == a = return $ Just h
951 let single a | h == a = return $ Just h
1158 | otherwise = return Nothing
952 | otherwise = return Nothing
1159 yieldk a r | h == a = go h r
953 yieldk a r | h == a = go h r
1160 | otherwise = return Nothing
954 | otherwise = return Nothing
1161− in unStream m1 defState (return $ Just h) single yieldk
955+ in foldStream defState yieldk single (return $ Just h) m1
1162−
1163−------------------------------------------------------------------------------
1164−-- Semigroup
1165−------------------------------------------------------------------------------
1166−
1167−-- | Concatenates two streams sequentially i.e. the first stream is
1168−-- exhausted completely before yielding any element from the second stream.
1169−{-# INLINE serial #-}
1170−serial :: Stream m a -> Stream m a -> Stream m a
1171−serial m1 m2 = go m1
1172− where
1173− go (Stream m) = Stream $ \st stp sng yld ->
1174− let stop = unStream m2 (rstState st) stp sng yld
1175− single a = yld a m2
1176− yieldk a r = yld a (go r)
1177− in m (rstState st) stop single yieldk
1178−
1179−instance Semigroup (Stream m a) where
1180− (<>) = serial
1181−
1182−------------------------------------------------------------------------------
1183−-- Monoid
1184−------------------------------------------------------------------------------
1185−
1186−instance Monoid (Stream m a) where
1187− mempty = nil
1188− mappend = (<>)
1189−
1190−-------------------------------------------------------------------------------
1191−-- Functor
1192−-------------------------------------------------------------------------------
1193−
1194−instance Monad m => Functor (Stream m) where
1195− fmap = map
1196
956
1197-------------------------------------------------------------------------------
957-------------------------------------------------------------------------------
1198-- Bind utility
958-- Bind utility
@@ -1200,40 +960,40 @@ instance Monad m => Functor (Stream m) where
1200
960
1201{-# INLINE bindWith #-}
961{-# INLINE bindWith #-}
1202bindWith
962bindWith
963+ :: IsStream t
1203− :: (forall c. Stream m c -> Stream m c -> Stream m c)
964+ => (forall c. t m c -> t m c -> t m c)
1204− -> Stream m a
965+ -> t m a
1205− -> (a -> Stream m b)
966+ -> (a -> t m b)
1206− -> Stream m b
967+ -> t m b
1207−bindWith par m f = go m
968+bindWith par m1 f = go m1
1208 where
969 where
1209− go (Stream g) =
970+ go m =
1210− Stream $ \st stp sng yld ->
971+ mkStream $ \st yld sng stp ->
1211− let runShared x = unstreamShared x st stp sng yld
972+ let foldShared = foldStreamShared st yld sng stp
1212− runIsolated x = unStreamIsolated x st stp sng yld
973+ single a = foldShared $ unShare (f a)
1213−
1214− single a = runIsolated $ f a
1215− yieldk a r = runShared $ isolateStream (f a) `par` go r
974+ yieldk a r = foldShared $ unShare (f a) `par` go r
1216− in g (rstState st) stp single yieldk
975+ in foldStream (adaptState st) yieldk single stp m
1217
976
1218------------------------------------------------------------------------------
977------------------------------------------------------------------------------
1219-- Alternative & MonadPlus
978-- Alternative & MonadPlus
1220------------------------------------------------------------------------------
979------------------------------------------------------------------------------
1221
980
1222_alt :: Stream m a -> Stream m a -> Stream m a
981_alt :: Stream m a -> Stream m a -> Stream m a
1223−_alt m1 m2 = Stream $ \st stp sng yld ->
982+_alt m1 m2 = mkStream $ \st yld sng stp ->
1224− let stop = unStream m2 (rstState st) stp sng yld
983+ let stop = foldStream st yld sng stp m2
1225− in unStream m1 (rstState st) stop sng yld
984+ in foldStream st yld sng stop m1
1226
985
1227------------------------------------------------------------------------------
986------------------------------------------------------------------------------
1228-- MonadReader
987-- MonadReader
1229------------------------------------------------------------------------------
988------------------------------------------------------------------------------
1230
989
990+{-# INLINABLE withLocal #-}
1231withLocal :: MonadReader r m => (r -> r) -> Stream m a -> Stream m a
991withLocal :: MonadReader r m => (r -> r) -> Stream m a -> Stream m a
1232withLocal f m =
992withLocal f m =
1233− Stream $ \st stp sng yld ->
993+ mkStream $ \st yld sng stp ->
1234 let single = local f . sng
994 let single = local f . sng
1235 yieldk a r = local f $ yld a (withLocal f r)
995 yieldk a r = local f $ yld a (withLocal f r)
1236− in unStream m (rstState st) (local f stp) single yieldk
996+ in foldStream st yieldk single (local f stp) m
1237
997
1238------------------------------------------------------------------------------
998------------------------------------------------------------------------------
1239-- MonadError
999-- MonadError
@@ -1245,16 +1005,9 @@ withCatchError
1245 :: MonadError e m
1005 :: MonadError e m
1246 => Stream m a -> (e -> Stream m a) -> Stream m a
1006 => Stream m a -> (e -> Stream m a) -> Stream m a
1247withCatchError m h =
1007withCatchError m h =
1248− Stream $ \_ stp sng yld ->
1008+ mkStream $ \_ stp sng yld ->
1249 let run x = unStream x Nothing stp sng yieldk
1009 let run x = unStream x Nothing stp sng yieldk
1250 handle r = r `catchError` \e -> run $ h e
1010 handle r = r `catchError` \e -> run $ h e
1251 yieldk a r = yld a (withCatchError r h)
1011 yieldk a r = yld a (withCatchError r h)
1252 in handle $ run m
1012 in handle $ run m
1253-}
1013-}
1254−
1255−-------------------------------------------------------------------------------
1256−-- Transformers
1257−-------------------------------------------------------------------------------
1258−
1259−instance MonadTrans Stream where
1260− lift = yieldM
src/Streamly/Streams/StreamK/Type.hsnew file+418
@@ -0,0 +1,418 @@
1+{-# LANGUAGE BangPatterns #-}
2+{-# LANGUAGE CPP #-}
3+{-# LANGUAGE ConstraintKinds #-}
4+{-# LANGUAGE FlexibleContexts #-}
5+{-# LANGUAGE FlexibleInstances #-}
6+{-# LANGUAGE InstanceSigs #-}
7+{-# LANGUAGE MultiParamTypeClasses #-}
8+{-# LANGUAGE PatternSynonyms #-}
9+{-# LANGUAGE ViewPatterns #-}
10+{-# LANGUAGE RankNTypes #-}
11+{-# LANGUAGE UndecidableInstances #-} -- XXX
12+
13+#include "../inline.hs"
14+
15+-- |
16+-- Module : Streamly.Streams.StreamK.Type
17+-- Copyright : (c) 2017 Harendra Kumar
18+--
19+-- License : BSD3
20+-- Maintainer : harendra.kumar@gmail.com
21+-- Stability : experimental
22+-- Portability : GHC
23+--
24+--
25+-- Continuation passing style (CPS) stream implementation. The symbol 'K' below
26+-- denotes a function as well as a Kontinuation.
27+--
28+module Streamly.Streams.StreamK.Type
29+ (
30+ -- * A class for streams
31+ IsStream (..)
32+ , adapt
33+
34+ -- * The stream type
35+ , Stream ()
36+
37+ -- * Construction
38+ , mkStream
39+ , fromStopK
40+ , fromYieldK
41+ , consK
42+
43+ -- * Elimination
44+ , foldStream
45+ , foldStreamShared
46+ , foldStreamSVar
47+
48+ -- instances
49+ , consMStream
50+
51+ , nil
52+ , serial
53+ , map
54+ , yieldM
55+
56+ , Streaming -- deprecated
57+ )
58+where
59+
60+import Control.Monad (void)
61+import Control.Monad.IO.Class (MonadIO(liftIO))
62+import Control.Monad.Trans.Class (MonadTrans(lift))
63+import Data.Semigroup (Semigroup(..))
64+import Prelude hiding (map)
65+
66+import Streamly.SVar
67+
68+------------------------------------------------------------------------------
69+-- Basic stream type
70+------------------------------------------------------------------------------
71+
72+-- | The type @Stream m a@ represents a monadic stream of values of type 'a'
73+-- constructed using actions in monad 'm'. It uses stop, singleton and yield
74+-- continuations equivalent to the following direct style type:
75+--
76+-- @
77+-- data Stream m a = Stop | Singleton a | Yield a (Stream m a)
78+-- @
79+--
80+-- To facilitate parallel composition we maintain a local state in an 'SVar'
81+-- that is shared across and is used for synchronization of the streams being
82+-- composed.
83+--
84+-- The singleton case can be expressed in terms of stop and yield but we have
85+-- it as a separate case to optimize composition operations for streams with
86+-- single element. We build singleton streams in the implementation of 'pure'
87+-- for Applicative and Monad, and in 'lift' for MonadTrans.
88+--
89+-- XXX remove the Stream type parameter from State as it is always constant.
90+-- We can remove it from SVar as well
91+--
92+newtype Stream m a =
93+ MkStream (forall r.
94+ State Stream m a -- state
95+ -> (a -> Stream m a -> m r) -- yield
96+ -> (a -> m r) -- singleton
97+ -> m r -- stop
98+ -> m r
99+ )
100+
101+------------------------------------------------------------------------------
102+-- Types that can behave as a Stream
103+------------------------------------------------------------------------------
104+
105+infixr 5 `consM`
106+infixr 5 |:
107+
108+-- XXX Use a different SVar based on the stream type. But we need to make sure
109+-- that we do not lose performance due to polymorphism.
110+--
111+-- | Class of types that can represent a stream of elements of some type 'a' in
112+-- some monad 'm'.
113+--
114+-- @since 0.2.0
115+class IsStream t where
116+ toStream :: t m a -> Stream m a
117+ fromStream :: Stream m a -> t m a
118+ -- | Constructs a stream by adding a monadic action at the head of an
119+ -- existing stream. For example:
120+ --
121+ -- @
122+ -- > toList $ getLine \`consM` getLine \`consM` nil
123+ -- hello
124+ -- world
125+ -- ["hello","world"]
126+ -- @
127+ --
128+ -- /Concurrent (do not use 'parallely' to construct infinite streams)/
129+ --
130+ -- @since 0.2.0
131+ consM :: MonadAsync m => m a -> t m a -> t m a
132+ -- | Operator equivalent of 'consM'. We can read it as "@parallel colon@"
133+ -- to remember that @|@ comes before ':'.
134+ --
135+ -- @
136+ -- > toList $ getLine |: getLine |: nil
137+ -- hello
138+ -- world
139+ -- ["hello","world"]
140+ -- @
141+ --
142+ -- @
143+ -- let delay = threadDelay 1000000 >> print 1
144+ -- runStream $ serially $ delay |: delay |: delay |: nil
145+ -- runStream $ parallely $ delay |: delay |: delay |: nil
146+ -- @
147+ --
148+ -- /Concurrent (do not use 'parallely' to construct infinite streams)/
149+ --
150+ -- @since 0.2.0
151+ (|:) :: MonadAsync m => m a -> t m a -> t m a
152+ -- We can define (|:) just as 'consM' but it is defined explicitly for each
153+ -- type because we want to use SPECIALIZE pragma on the definition.
154+
155+-- | Same as 'IsStream'.
156+--
157+-- @since 0.1.0
158+{-# DEPRECATED Streaming "Please use IsStream instead." #-}
159+type Streaming = IsStream
160+
161+-------------------------------------------------------------------------------
162+-- Type adapting combinators
163+-------------------------------------------------------------------------------
164+
165+-- XXX Move/reset the State here by reconstructing the stream with cleared
166+-- state. Can we make sure we do not do that when t1 = t2? If we do this then
167+-- we do not need to do that explicitly using svarStyle. It would act as
168+-- unShare when the stream type is the same.
169+--
170+-- | Adapt any specific stream type to any other specific stream type.
171+--
172+-- @since 0.1.0
173+adapt :: (IsStream t1, IsStream t2) => t1 m a -> t2 m a
174+adapt = fromStream . toStream
175+
176+------------------------------------------------------------------------------
177+-- Building a stream
178+------------------------------------------------------------------------------
179+
180+-- XXX The State is always parameterized by "Stream" which means State is not
181+-- different for different stream types. So we have to manually make sure that
182+-- when converting from one stream to another we migrate the state correctly.
183+-- This can be fixed if we use a different SVar type for different streams.
184+-- Currently we always use "SVar Stream" and therefore a different State type
185+-- parameterized by that stream.
186+--
187+-- XXX Since t is coercible we should be able to coerce k
188+-- mkStream k = fromStream $ MkStream $ coerce k
189+--
190+-- | Build a stream from an 'SVar', a stop continuation, a singleton stream
191+-- continuation and a yield continuation.
192+{-# INLINE_EARLY mkStream #-}
193+mkStream :: IsStream t
194+ => (forall r. State Stream m a
195+ -> (a -> t m a -> m r)
196+ -> (a -> m r)
197+ -> m r
198+ -> m r)
199+ -> t m a
200+mkStream k = fromStream $ MkStream $ \st yld sng stp ->
201+ let yieldk a r = yld a (toStream r)
202+ in k st yieldk sng stp
203+
204+{-# RULES "mkStream from stream" mkStream = mkStreamFromStream #-}
205+mkStreamFromStream :: IsStream t
206+ => (forall r. State Stream m a
207+ -> (a -> Stream m a -> m r)
208+ -> (a -> m r)
209+ -> m r
210+ -> m r)
211+ -> t m a
212+mkStreamFromStream k = fromStream $ MkStream k
213+
214+{-# RULES "mkStream stream" mkStream = mkStreamStream #-}
215+mkStreamStream
216+ :: (forall r. State Stream m a
217+ -> (a -> Stream m a -> m r)
218+ -> (a -> m r)
219+ -> m r
220+ -> m r)
221+ -> Stream m a
222+mkStreamStream = MkStream
223+
224+-- | A terminal function that has no continuation to follow.
225+type StopK m = forall r. m r -> m r
226+
227+-- | A monadic continuation, it is a function that yields a value of type "a"
228+-- and calls the argument (a -> m r) as a continuation with that value. We can
229+-- also think of it as a callback with a handler (a -> m r). Category
230+-- theorists call it a codensity type, a special type of right kan extension.
231+type YieldK m a = forall r. (a -> m r) -> m r
232+
233+_wrapM :: Monad m => m a -> YieldK m a
234+_wrapM m = \k -> m >>= k
235+
236+-- | Make an empty stream from a stop function.
237+fromStopK :: IsStream t => StopK m -> t m a
238+fromStopK k = mkStream $ \_ _ _ stp -> k stp
239+
240+-- | Make a singleton stream from a yield function.
241+fromYieldK :: IsStream t => YieldK m a -> t m a
242+fromYieldK k = mkStream $ \_ _ sng _ -> k sng
243+
244+-- | Add a yield function at the head of the stream.
245+consK :: IsStream t => YieldK m a -> t m a -> t m a
246+consK k r = mkStream $ \_ yld _ _ -> k (\x -> yld x r)
247+
248+-- XXX Build a stream from a repeating callback function.
249+
250+------------------------------------------------------------------------------
251+-- Folding a stream
252+------------------------------------------------------------------------------
253+
254+-- | Fold a stream by providing an SVar, a stop continuation, a singleton
255+-- continuation and a yield continuation. The stream would share the current
256+-- SVar passed via the State.
257+{-# INLINE_EARLY foldStreamShared #-}
258+foldStreamShared
259+ :: IsStream t
260+ => State Stream m a
261+ -> (a -> t m a -> m r)
262+ -> (a -> m r)
263+ -> m r
264+ -> t m a
265+ -> m r
266+foldStreamShared st yld sng stp m =
267+ let yieldk a x = yld a (fromStream x)
268+ MkStream k = toStream m
269+ in k st yieldk sng stp
270+
271+-- XXX write a similar rule for foldStream as well?
272+{-# RULES "foldStreamShared from stream"
273+ foldStreamShared = foldStreamSharedStream #-}
274+foldStreamSharedStream
275+ :: State Stream m a
276+ -> (a -> Stream m a -> m r)
277+ -> (a -> m r)
278+ -> m r
279+ -> Stream m a
280+ -> m r
281+foldStreamSharedStream st yld sng stp m =
282+ let MkStream k = toStream m
283+ in k st yld sng stp
284+
285+-- | Fold a stream by providing a State, stop continuation, a singleton
286+-- continuation and a yield continuation. The stream will not use the SVar
287+-- passed via State.
288+{-# INLINE foldStream #-}
289+foldStream
290+ :: IsStream t
291+ => State Stream m a
292+ -> (a -> t m a -> m r)
293+ -> (a -> m r)
294+ -> m r
295+ -> t m a
296+ -> m r
297+foldStream st yld sng stp m =
298+ let yieldk a x = yld a (fromStream x)
299+ MkStream k = toStream m
300+ in k (adaptState st) yieldk sng stp
301+
302+-- Run the stream using a run function associated with the SVar that runs the
303+-- streams with a captured snapshot of the monadic state.
304+{-# INLINE foldStreamSVar #-}
305+foldStreamSVar
306+ :: (IsStream t, MonadIO m)
307+ => SVar Stream m a
308+ -> State Stream m a -- state
309+ -> (a -> t m a -> m r) -- yield
310+ -> (a -> m r) -- singleton
311+ -> m r -- stop
312+ -> t m a
313+ -> m ()
314+foldStreamSVar sv st yld sng stp m =
315+ let mrun = runInIO $ svarMrun sv
316+ in void $ liftIO $ mrun $ foldStreamShared st yld sng stp m
317+
318+-------------------------------------------------------------------------------
319+-- Instances
320+-------------------------------------------------------------------------------
321+
322+-- NOTE: specializing the function outside the instance definition seems to
323+-- improve performance quite a bit at times, even if we have the same
324+-- SPECIALIZE in the instance definition.
325+{-# INLINE consMStream #-}
326+{-# SPECIALIZE consMStream :: IO a -> Stream IO a -> Stream IO a #-}
327+consMStream :: (Monad m) => m a -> Stream m a -> Stream m a
328+consMStream m r = MkStream $ \_ yld _ _ -> m >>= \a -> yld a r
329+
330+-------------------------------------------------------------------------------
331+-- IsStream Stream
332+-------------------------------------------------------------------------------
333+
334+instance IsStream Stream where
335+ toStream = id
336+ fromStream = id
337+
338+ {-# INLINE consM #-}
339+ {-# SPECIALIZE consM :: IO a -> Stream IO a -> Stream IO a #-}
340+ consM :: Monad m => m a -> Stream m a -> Stream m a
341+ consM = consMStream
342+
343+ {-# INLINE (|:) #-}
344+ {-# SPECIALIZE (|:) :: IO a -> Stream IO a -> Stream IO a #-}
345+ (|:) :: Monad m => m a -> Stream m a -> Stream m a
346+ (|:) = consMStream
347+
348+------------------------------------------------------------------------------
349+-- Semigroup
350+------------------------------------------------------------------------------
351+
352+-- | Polymorphic version of the 'Semigroup' operation '<>' of 'SerialT'.
353+-- Appends two streams sequentially, yielding all elements from the first
354+-- stream, and then all elements from the second stream.
355+--
356+-- @since 0.2.0
357+{-# INLINE serial #-}
358+serial :: IsStream t => t m a -> t m a -> t m a
359+serial m1 m2 = go m1
360+ where
361+ go m = mkStream $ \st yld sng stp ->
362+ let stop = foldStream st yld sng stp m2
363+ single a = yld a m2
364+ yieldk a r = yld a (go r)
365+ in foldStream st yieldk single stop m
366+
367+instance Semigroup (Stream m a) where
368+ (<>) = serial
369+
370+------------------------------------------------------------------------------
371+-- Monoid
372+------------------------------------------------------------------------------
373+
374+-- | An empty stream.
375+--
376+-- @
377+-- > toList nil
378+-- []
379+-- @
380+--
381+-- @since 0.1.0
382+{-# INLINE nil #-}
383+nil :: IsStream t => t m a
384+nil = mkStream $ \_ _ _ stp -> stp
385+
386+instance Monoid (Stream m a) where
387+ mempty = nil
388+ mappend = (<>)
389+
390+-------------------------------------------------------------------------------
391+-- Functor
392+-------------------------------------------------------------------------------
393+
394+{-# INLINE map #-}
395+map :: IsStream t => (a -> b) -> t m a -> t m b
396+map f m = go m
397+ where
398+ go m1 =
399+ mkStream $ \st yld sng stp ->
400+ let single = sng . f
401+ yieldk a r = yld (f a) (go r)
402+ in foldStream (adaptState st) yieldk single stp m1
403+
404+-- in fact use the Stream type everywhere and only use polymorphism in the high
405+-- level modules/prelude.
406+instance Monad m => Functor (Stream m) where
407+ fmap = map
408+
409+-------------------------------------------------------------------------------
410+-- Transformers
411+-------------------------------------------------------------------------------
412+
413+{-# INLINE yieldM #-}
414+yieldM :: (Monad m, IsStream t) => m a -> t m a
415+yieldM m = fromStream $ mkStream $ \_ _ single _ -> m >>= single
416+
417+instance MonadTrans Stream where
418+ lift = yieldM
src/Streamly/Streams/Zip.hs+24−15
@@ -48,10 +48,10 @@ import Text.Read (Lexeme(Ident), lexP, parens, prec, readPrec, readListPrec,
48 readListPrecDefault)
48 readListPrecDefault)
49import Prelude hiding (map, repeat, zipWith)
49import Prelude hiding (map, repeat, zipWith)
50
50
51−import Streamly.Streams.StreamK (IsStream(..), Stream(..))
51+import Streamly.Streams.StreamK (IsStream(..), Stream, mkStream, foldStream)
52import Streamly.Streams.Async (mkAsync')
52import Streamly.Streams.Async (mkAsync')
53import Streamly.Streams.Serial (map)
53import Streamly.Streams.Serial (map)
54−import Streamly.SVar (MonadAsync, rstState)
54+import Streamly.SVar (MonadAsync, adaptState)
55
55
56import qualified Streamly.Streams.Prelude as P
56import qualified Streamly.Streams.Prelude as P
57import qualified Streamly.Streams.StreamK as K
57import qualified Streamly.Streams.StreamK as K
@@ -106,6 +106,9 @@ zipSerially = K.adapt
106zipping :: IsStream t => ZipSerialM m a -> t m a
106zipping :: IsStream t => ZipSerialM m a -> t m a
107zipping = zipSerially
107zipping = zipSerially
108
108
109+consMZip :: Monad m => m a -> ZipSerialM m a -> ZipSerialM m a
110+consMZip m ms = fromStream $ K.consMStream m (toStream ms)
111+
109instance IsStream ZipSerialM where
112instance IsStream ZipSerialM where
110 toStream = getZipSerialM
113 toStream = getZipSerialM
111 fromStream = ZipSerialM
114 fromStream = ZipSerialM
@@ -113,12 +116,12 @@ instance IsStream ZipSerialM where
113 {-# INLINE consM #-}
116 {-# INLINE consM #-}
114 {-# SPECIALIZE consM :: IO a -> ZipSerialM IO a -> ZipSerialM IO a #-}
117 {-# SPECIALIZE consM :: IO a -> ZipSerialM IO a -> ZipSerialM IO a #-}
115 consM :: Monad m => m a -> ZipSerialM m a -> ZipSerialM m a
118 consM :: Monad m => m a -> ZipSerialM m a -> ZipSerialM m a
116− consM m r = fromStream $ K.consMSerial m (toStream r)
119+ consM = consMZip
117
120
118 {-# INLINE (|:) #-}
121 {-# INLINE (|:) #-}
119 {-# SPECIALIZE (|:) :: IO a -> ZipSerialM IO a -> ZipSerialM IO a #-}
122 {-# SPECIALIZE (|:) :: IO a -> ZipSerialM IO a -> ZipSerialM IO a #-}
120 (|:) :: Monad m => m a -> ZipSerialM m a -> ZipSerialM m a
123 (|:) :: Monad m => m a -> ZipSerialM m a -> ZipSerialM m a
121− m |: r = fromStream $ K.consMSerial m (toStream r)
124+ (|:) = consMZip
122
125
123LIST_INSTANCES(ZipSerialM)
126LIST_INSTANCES(ZipSerialM)
124
127
@@ -127,7 +130,7 @@ instance Monad m => Functor (ZipSerialM m) where
127
130
128instance Monad m => Applicative (ZipSerialM m) where
131instance Monad m => Applicative (ZipSerialM m) where
129 pure = ZipSerialM . K.repeat
132 pure = ZipSerialM . K.repeat
130− m1 <*> m2 = fromStream $ K.zipWith id (toStream m1) (toStream m2)
133+ (<*>) = K.zipWith id
131
134
132FOLDABLE_INSTANCE(ZipSerialM)
135FOLDABLE_INSTANCE(ZipSerialM)
133TRAVERSABLE_INSTANCE(ZipSerialM)
136TRAVERSABLE_INSTANCE(ZipSerialM)
@@ -140,23 +143,25 @@ TRAVERSABLE_INSTANCE(ZipSerialM)
140-- are generated concurrently.
143-- are generated concurrently.
141--
144--
142-- @since 0.1.0
145-- @since 0.1.0
146+{-# INLINABLE zipAsyncWith #-}
143zipAsyncWith :: (IsStream t, MonadAsync m)
147zipAsyncWith :: (IsStream t, MonadAsync m)
144 => (a -> b -> c) -> t m a -> t m b -> t m c
148 => (a -> b -> c) -> t m a -> t m b -> t m c
145−zipAsyncWith f m1 m2 = fromStream $ Stream $ \st stp sng yld -> do
149+zipAsyncWith f m1 m2 = mkStream $ \st stp sng yld -> do
146− ma <- mkAsync' (rstState st) m1
150+ ma <- mkAsync' (adaptState st) m1
147− mb <- mkAsync' (rstState st) m2
151+ mb <- mkAsync' (adaptState st) m2
148− unStream (toStream (K.zipWith f ma mb)) (rstState st) stp sng yld
152+ foldStream st stp sng yld (K.zipWith f ma mb)
149
153
150-- | Like 'zipWithM' but zips concurrently i.e. both the streams being zipped
154-- | Like 'zipWithM' but zips concurrently i.e. both the streams being zipped
151-- are generated concurrently.
155-- are generated concurrently.
152--
156--
153-- @since 0.4.0
157-- @since 0.4.0
158+{-# INLINABLE zipAsyncWithM #-}
154zipAsyncWithM :: (IsStream t, MonadAsync m)
159zipAsyncWithM :: (IsStream t, MonadAsync m)
155 => (a -> b -> m c) -> t m a -> t m b -> t m c
160 => (a -> b -> m c) -> t m a -> t m b -> t m c
156−zipAsyncWithM f m1 m2 = fromStream $ Stream $ \st stp sng yld -> do
161+zipAsyncWithM f m1 m2 = mkStream $ \st stp sng yld -> do
157− ma <- mkAsync' (rstState st) m1
162+ ma <- mkAsync' (adaptState st) m1
158− mb <- mkAsync' (rstState st) m2
163+ mb <- mkAsync' (adaptState st) m2
159− unStream (toStream (K.zipWithM f ma mb)) (rstState st) stp sng yld
164+ foldStream st stp sng yld (K.zipWithM f ma mb)
160
165
161------------------------------------------------------------------------------
166------------------------------------------------------------------------------
162-- Parallely Zipping Streams
167-- Parallely Zipping Streams
@@ -199,6 +204,10 @@ zipAsyncly = K.adapt
199{-# DEPRECATED zippingAsync "Please use zipAsyncly instead." #-}
204{-# DEPRECATED zippingAsync "Please use zipAsyncly instead." #-}
200zippingAsync :: IsStream t => ZipAsyncM m a -> t m a
205zippingAsync :: IsStream t => ZipAsyncM m a -> t m a
201zippingAsync = zipAsyncly
206zippingAsync = zipAsyncly
207+
208+consMZipAsync :: Monad m => m a -> ZipAsyncM m a -> ZipAsyncM m a
209+consMZipAsync m ms = fromStream $ K.consMStream m (toStream ms)
210+
202instance IsStream ZipAsyncM where
211instance IsStream ZipAsyncM where
203 toStream = getZipAsyncM
212 toStream = getZipAsyncM
204 fromStream = ZipAsyncM
213 fromStream = ZipAsyncM
@@ -206,12 +215,12 @@ instance IsStream ZipAsyncM where
206 {-# INLINE consM #-}
215 {-# INLINE consM #-}
207 {-# SPECIALIZE consM :: IO a -> ZipAsyncM IO a -> ZipAsyncM IO a #-}
216 {-# SPECIALIZE consM :: IO a -> ZipAsyncM IO a -> ZipAsyncM IO a #-}
208 consM :: Monad m => m a -> ZipAsyncM m a -> ZipAsyncM m a
217 consM :: Monad m => m a -> ZipAsyncM m a -> ZipAsyncM m a
209− consM m r = fromStream $ K.consMSerial m (toStream r)
218+ consM = consMZipAsync
210
219
211 {-# INLINE (|:) #-}
220 {-# INLINE (|:) #-}
212 {-# SPECIALIZE (|:) :: IO a -> ZipAsyncM IO a -> ZipAsyncM IO a #-}
221 {-# SPECIALIZE (|:) :: IO a -> ZipAsyncM IO a -> ZipAsyncM IO a #-}
213 (|:) :: Monad m => m a -> ZipAsyncM m a -> ZipAsyncM m a
222 (|:) :: Monad m => m a -> ZipAsyncM m a -> ZipAsyncM m a
214− m |: r = fromStream $ K.consMSerial m (toStream r)
223+ (|:) = consMZipAsync
215
224
216instance Monad m => Functor (ZipAsyncM m) where
225instance Monad m => Functor (ZipAsyncM m) where
217 fmap = map
226 fmap = map
streamly.cabal+7
@@ -128,7 +128,9 @@ library
128 other-modules: Streamly.SVar
128 other-modules: Streamly.SVar
129
129
130 -- Base streams
130 -- Base streams
131+ , Streamly.Streams.StreamK.Type
131 , Streamly.Streams.StreamK
132 , Streamly.Streams.StreamK
133+ , Streamly.Streams.StreamD.Type
132 , Streamly.Streams.StreamD
134 , Streamly.Streams.StreamD
133 , Streamly.Streams.Prelude
135 , Streamly.Streams.Prelude
134
136
@@ -479,7 +481,9 @@ benchmark base
479 hs-source-dirs: benchmark, src
481 hs-source-dirs: benchmark, src
480 main-is: BaseStreams.hs
482 main-is: BaseStreams.hs
481 other-modules: Streamly.SVar
483 other-modules: Streamly.SVar
484+ , Streamly.Streams.StreamK.Type
482 , Streamly.Streams.StreamK
485 , Streamly.Streams.StreamK
486+ , Streamly.Streams.StreamD.Type
483 , Streamly.Streams.StreamD
487 , Streamly.Streams.StreamD
484 , Streamly.Streams.Prelude
488 , Streamly.Streams.Prelude
485
489
@@ -535,7 +539,9 @@ executable nano-bench
535 hs-source-dirs: benchmark, src
539 hs-source-dirs: benchmark, src
536 main-is: NanoBenchmarks.hs
540 main-is: NanoBenchmarks.hs
537 other-modules: Streamly.SVar
541 other-modules: Streamly.SVar
542+ , Streamly.Streams.StreamK.Type
538 , Streamly.Streams.StreamK
543 , Streamly.Streams.StreamK
544+ , Streamly.Streams.StreamD.Type
539 , Streamly.Streams.StreamD
545 , Streamly.Streams.StreamD
540 default-language: Haskell2010
546 default-language: Haskell2010
541 ghc-options: -O2 -Wall
547 ghc-options: -O2 -Wall
@@ -548,6 +554,7 @@ executable nano-bench
548 , ghc-prim >= 0.2 && < 0.6
554 , ghc-prim >= 0.2 && < 0.6
549 , containers >= 0.5 && < 0.7
555 , containers >= 0.5 && < 0.7
550 , heaps >= 0.3 && < 0.4
556 , heaps >= 0.3 && < 0.4
557+ , random >= 1.0 && < 2.0
551
558
552 -- concurrency
559 -- concurrency
553 , atomic-primops >= 0.8 && < 0.9
560 , atomic-primops >= 0.8 && < 0.9