on master help sign in
Refactor StreamD/IsStream for terminating folds
82efd3aHarendra Kumar
benchmark/Streamly/Benchmark/FileSystem/Handle/Read.hs+29−32
@@ -32,18 +32,17 @@ import GHC.Magic (noinline)
32#endif
32#endif
33import System.IO (Handle)
33import System.IO (Handle)
34
34
35−import qualified Streamly.Data.Fold as FL
36−import qualified Streamly.Unicode.Stream as SS
37import qualified Streamly.FileSystem.Handle as FH
35import qualified Streamly.FileSystem.Handle as FH
38−import qualified Streamly.Internal.Data.Parser as PR
39−import qualified Streamly.Internal.Data.Stream.StreamD as D
40−import qualified Streamly.Internal.Unicode.Stream as IUS
41−import qualified Streamly.Internal.FileSystem.Handle as IFH
42import qualified Streamly.Internal.Data.Array.Storable.Foreign as A
36import qualified Streamly.Internal.Data.Array.Storable.Foreign as A
43import qualified Streamly.Internal.Data.Array.Storable.Foreign.Types as AT
37import qualified Streamly.Internal.Data.Array.Storable.Foreign.Types as AT
44−import qualified Streamly.Internal.Memory.ArrayStream as AS
38+import qualified Streamly.Internal.Data.Fold as FL
39+import qualified Streamly.Internal.Data.Parser as PR
45import qualified Streamly.Internal.Data.Stream.IsStream as IP
40import qualified Streamly.Internal.Data.Stream.IsStream as IP
41+import qualified Streamly.Internal.FileSystem.Handle as IFH
42+import qualified Streamly.Internal.Memory.ArrayStream as AS
43+import qualified Streamly.Internal.Unicode.Stream as IUS
46import qualified Streamly.Prelude as S
44import qualified Streamly.Prelude as S
45+import qualified Streamly.Unicode.Stream as SS
47
46
48import Gauge hiding (env)
47import Gauge hiding (env)
49import Prelude hiding (last, length)
48import Prelude hiding (last, length)
@@ -52,6 +51,7 @@ import Streamly.Benchmark.Common.Handle
52#ifdef INSPECTION
51#ifdef INSPECTION
53import Streamly.Internal.Data.Stream.StreamD.Type (Step(..), GroupState)
52import Streamly.Internal.Data.Stream.StreamD.Type (Step(..), GroupState)
54
53
54+import qualified Streamly.Internal.Data.Stream.StreamD as D
55import qualified Streamly.Internal.Data.Unfold as IUF
55import qualified Streamly.Internal.Data.Unfold as IUF
56
56
57import Test.Inspection
57import Test.Inspection
@@ -309,9 +309,14 @@ o_1_space_reduce_toBytes env =
309chunksOfSum :: Int -> Handle -> IO Int
309chunksOfSum :: Int -> Handle -> IO Int
310chunksOfSum n inh = S.length $ S.chunksOf n FL.sum (S.unfold FH.read inh)
310chunksOfSum n inh = S.length $ S.chunksOf n FL.sum (S.unfold FH.read inh)
311
311
312+foldManyChunksOfSum :: Int -> Handle -> IO Int
313+foldManyChunksOfSum n inh =
314+ S.length $ IP.foldMany (FL.ltake n FL.sum) (S.unfold FH.read inh)
315+
312parseManyChunksOfSum :: Int -> Handle -> IO Int
316parseManyChunksOfSum :: Int -> Handle -> IO Int
313parseManyChunksOfSum n inh =
317parseManyChunksOfSum n inh =
318+ S.length
314− S.length $ IP.parseMany (PR.take n FL.sum) (S.unfold FH.read inh)
319+ $ IP.parseMany (PR.fromFold $ FL.ltake n FL.sum) (S.unfold FH.read inh)
315
320
316-- XXX investigate why we need an INLINE in this case (GHC)
321-- XXX investigate why we need an INLINE in this case (GHC)
317-- Even though allocations remain the same in both cases inlining improves time
322-- Even though allocations remain the same in both cases inlining improves time
@@ -333,25 +338,6 @@ inspect $ 'chunksOf `hasNoType` ''IUF.ConcatState -- FH.read/UF.concat
333inspect $ 'chunksOf `hasNoType` ''A.ReadUState -- FH.read/A.read
338inspect $ 'chunksOf `hasNoType` ''A.ReadUState -- FH.read/A.read
334#endif
339#endif
335
340
336−-- This is to make sure that the concatMap in FH.read, groupsOf and foldlM'
337−-- together can fuse.
338−--
339−-- | Slice in chunks of size n and get the count of chunks.
340−_chunksOfD :: Int -> Handle -> IO Int
341−_chunksOfD n inh =
342− D.foldlM' (\i _ -> return $ i + 1) (return 0)
343− $ D.groupsOf n (AT.writeNUnsafe n)
344− $ D.fromStreamK (S.unfold FH.read inh)
345−
346−#ifdef INSPECTION
347−inspect $ hasNoTypeClasses '_chunksOfD
348−inspect $ '_chunksOfD `hasNoType` ''Step
349−inspect $ '_chunksOfD `hasNoType` ''GroupState
350−inspect $ '_chunksOfD `hasNoType` ''AT.ArrayUnsafe -- AT.writeNUnsafe
351−inspect $ '_chunksOfD `hasNoType` ''IUF.ConcatState -- FH.read/UF.concat
352−inspect $ '_chunksOfD `hasNoType` ''A.ReadUState -- FH.read/A.read
353−#endif
354−
355o_1_space_reduce_read_grouped :: BenchEnv -> [Benchmark]
341o_1_space_reduce_read_grouped :: BenchEnv -> [Benchmark]
356o_1_space_reduce_read_grouped env =
342o_1_space_reduce_read_grouped env =
357 [ bgroup "reduce/read/chunks"
343 [ bgroup "reduce/read/chunks"
@@ -363,11 +349,22 @@ o_1_space_reduce_read_grouped env =
363
349
364 -- XXX investigate why we need inline/noinline in these cases (GHC)
350 -- XXX investigate why we need inline/noinline in these cases (GHC)
365 -- Chunk using parsers
351 -- Chunk using parsers
352+ , mkBenchSmall
366− , mkBenchSmall ("S.parseMany (PR.take " ++ show (bigSize env) ++ " FL.sum)")
353+ ("S.foldMany (FL.take " ++ show (bigSize env) ++ " FL.sum)")
367− env $ \inh _ ->
354+ env
355+ $ \inh _ -> noinline foldManyChunksOfSum (bigSize env) inh
356+ , mkBench
357+ "S.foldMany (FL.take 1 FL.sum)"
358+ env
359+ $ \inh _ -> inline foldManyChunksOfSum 1 inh
360+ , mkBenchSmall
361+ ("S.parseMany (FL.take " ++ show (bigSize env) ++ " FL.sum)")
362+ env
368− noinline parseManyChunksOfSum (bigSize env) inh
363+ $ \inh _ -> noinline parseManyChunksOfSum (bigSize env) inh
364+ , mkBench
369− , mkBench "S.parseMany (PR.take 1 FL.sum)" env $ \inh _ ->
365+ "S.parseMany (FL.take 1 FL.sum)"
366+ env
370− inline parseManyChunksOfSum 1 inh
367+ $ \inh _ -> inline parseManyChunksOfSum 1 inh
371
368
372 -- folding chunks to arrays
369 -- folding chunks to arrays
373 , mkBenchSmall "S.arraysOf 1" env $ \inh _ ->
370 , mkBenchSmall "S.arraysOf 1" env $ \inh _ ->
benchmark/Streamly/Benchmark/Prelude/Serial/Split.hs+21−7
@@ -24,13 +24,13 @@ import Data.Char (ord)
24import Data.Word (Word8)
24import Data.Word (Word8)
25import System.IO (Handle)
25import System.IO (Handle)
26
26
27−import qualified Streamly.Data.Fold as FL
28import qualified Streamly.FileSystem.Handle as FH
27import qualified Streamly.FileSystem.Handle as FH
29−import qualified Streamly.Internal.Data.Parser as PR
30−import qualified Streamly.Internal.Unicode.Stream as IUS
31−import qualified Streamly.Internal.FileSystem.Handle as IFH
32import qualified Streamly.Internal.Data.Array.Storable.Foreign as A
28import qualified Streamly.Internal.Data.Array.Storable.Foreign as A
29+import qualified Streamly.Internal.Data.Fold as FL
30+import qualified Streamly.Internal.Data.Parser as PR
33import qualified Streamly.Internal.Data.Stream.IsStream as IP
31import qualified Streamly.Internal.Data.Stream.IsStream as IP
32+import qualified Streamly.Internal.FileSystem.Handle as IFH
33+import qualified Streamly.Internal.Unicode.Stream as IUS
34import qualified Streamly.Prelude as S
34import qualified Streamly.Prelude as S
35
35
36import Gauge hiding (env)
36import Gauge hiding (env)
@@ -95,11 +95,23 @@ inspect $ 'splitWithSuffix `hasNoType` ''IUF.ConcatState -- FH.read/UF.concat
95inspect $ 'splitWithSuffix `hasNoType` ''A.ReadUState -- FH.read/A.read
95inspect $ 'splitWithSuffix `hasNoType` ''A.ReadUState -- FH.read/A.read
96#endif
96#endif
97
97
98+-- | Split on line feed.
99+foldManySepBy :: Handle -> IO Int
100+foldManySepBy inh =
101+ (S.length
102+ $ IP.foldMany
103+ (FL.sliceSepBy (== lf) FL.drain)
104+ (S.unfold FH.read inh)
105+ ) -- >>= print
106+
98-- | Split on line feed.
107-- | Split on line feed.
99parseManySepBy :: Handle -> IO Int
108parseManySepBy :: Handle -> IO Int
100parseManySepBy inh =
109parseManySepBy inh =
110+ (S.length
111+ $ IP.parseMany
101− (S.length $ IP.parseMany (PR.sliceSepBy (== lf) FL.drain)
112+ (PR.fromFold $ FL.sliceSepBy (== lf) FL.drain)
102− (S.unfold FH.read inh)) -- >>= print
113+ (S.unfold FH.read inh)
114+ ) -- >>= print
103
115
104-- | Words by space
116-- | Words by space
105wordsBy :: Handle -> IO Int
117wordsBy :: Handle -> IO Int
@@ -146,7 +158,9 @@ splitOnSuffixSeq str inh =
146o_1_space_reduce_read_split :: BenchEnv -> [Benchmark]
158o_1_space_reduce_read_split :: BenchEnv -> [Benchmark]
147o_1_space_reduce_read_split env =
159o_1_space_reduce_read_split env =
148 [ bgroup "split"
160 [ bgroup "split"
161+ [ mkBench "S.foldMany (FL.sliceSepBy (== lf) FL.drain)" env
162+ $ \inh _ -> foldManySepBy inh
149− [ mkBench "S.parseMany (PR.sliceSepBy (== lf) FL.drain)" env
163+ , mkBench "S.parseMany (FL.sliceSepBy (== lf) FL.drain)" env
150 $ \inh _ -> parseManySepBy inh
164 $ \inh _ -> parseManySepBy inh
151 , mkBench "S.wordsBy isSpace FL.drain" env $ \inh _ ->
165 , mkBench "S.wordsBy isSpace FL.drain" env $ \inh _ ->
152 wordsBy inh
166 wordsBy inh
benchmark/Streamly/Benchmark/Prelude/Serial/Transformation2.hs+21−2
@@ -17,11 +17,12 @@ module Serial.Transformation2 (benchmarks) where
17import Control.DeepSeq (NFData(..))
17import Control.DeepSeq (NFData(..))
18import Control.Monad (when)
18import Control.Monad (when)
19import Control.Monad.IO.Class (MonadIO(..))
19import Control.Monad.IO.Class (MonadIO(..))
20+import Data.Monoid (Sum(..))
20import GHC.Generics (Generic)
21import GHC.Generics (Generic)
21
22
22−import qualified Streamly.Prelude as S
23−import qualified Streamly.Internal.Data.Stream.IsStream as Internal
24import qualified Streamly.Internal.Data.Fold as FL
23import qualified Streamly.Internal.Data.Fold as FL
24+import qualified Streamly.Internal.Data.Stream.IsStream as Internal
25+import qualified Streamly.Prelude as S
25
26
26import Gauge
27import Gauge
27import Streamly.Prelude (SerialT, serially)
28import Streamly.Prelude (SerialT, serially)
@@ -131,6 +132,22 @@ groupsByRollingEq :: MonadIO m => SerialT m Int -> m ()
131groupsByRollingEq =
132groupsByRollingEq =
132 S.drain . S.groupsByRolling (==) FL.drain
133 S.drain . S.groupsByRolling (==) FL.drain
133
134
135+{-# INLINE foldMany #-}
136+foldMany :: Monad m => SerialT m Int -> m ()
137+foldMany =
138+ S.drain
139+ . S.map getSum
140+ . Internal.foldMany (FL.ltake 2 FL.mconcat)
141+ . S.map Sum
142+
143+{-# INLINE _foldIterate #-}
144+_foldIterate :: Monad m => SerialT m Int -> m ()
145+_foldIterate =
146+ S.drain
147+ . S.map getSum
148+ . Internal.foldIterate (FL.ltake 2 . FL.sconcat) (Sum 0)
149+ . S.map Sum
150+
134o_1_space_grouping :: Int -> [Benchmark]
151o_1_space_grouping :: Int -> [Benchmark]
135o_1_space_grouping value =
152o_1_space_grouping value =
136 -- Buffering operations using heap proportional to group/window sizes.
153 -- Buffering operations using heap proportional to group/window sizes.
@@ -140,6 +157,8 @@ o_1_space_grouping value =
140 , benchIOSink value "groupsByEq" groupsByEq
157 , benchIOSink value "groupsByEq" groupsByEq
141 , benchIOSink value "groupsByRollingLT" groupsByRollingLT
158 , benchIOSink value "groupsByRollingLT" groupsByRollingLT
142 , benchIOSink value "groupsByRollingEq" groupsByRollingEq
159 , benchIOSink value "groupsByRollingEq" groupsByRollingEq
160+ , benchIOSink value "foldMany" foldMany
161+ -- , benchIOSink value "foldIterate" foldIterate
143 ]
162 ]
144 ]
163 ]
145
164
src/Streamly/Internal/Data/Stream/IsStream.hs+145−24
@@ -136,10 +136,22 @@ module Streamly.Internal.Data.Stream.IsStream
136 , foldlM'
136 , foldlM'
137
137
138 -- ** Composable Left Folds
138 -- ** Composable Left Folds
139+ -- | See "Streamly.Internal.Data.Fold"
139 , fold
140 , fold
141+ , foldMany
142+ , foldSequence
143+ , foldIterate
144+
145+ -- ** Parsers
146+ -- | See "Streamly.Internal.Data.Parser"
140 , parse
147 , parse
141 , parseK
148 , parseK
142 , parseD
149 , parseD
150+ , parseMany
151+ , parseManyD
152+ , parseManyTill
153+ , parseSequence
154+ , parseIterate
143
155
144 -- ** Concurrent Folds
156 -- ** Concurrent Folds
145 , foldAsync
157 , foldAsync
@@ -319,12 +331,6 @@ module Streamly.Internal.Data.Stream.IsStream
319 , reverse
331 , reverse
320 , reverse'
332 , reverse'
321
333
322− -- ** Parsing
323− , parseMany
324− , parseManyD
325− , parseManyTill
326− , parseIterate
327−
328 -- ** Trimming
334 -- ** Trimming
329 , take
335 , take
330 -- , takeGE
336 -- , takeGE
@@ -643,8 +649,7 @@ import Streamly.Internal.Data.IORef.Prim (Prim, IORef)
643import Streamly.Internal.Data.Tuple.Strict (Tuple'(..))
649import Streamly.Internal.Data.Tuple.Strict (Tuple'(..))
644
650
645import qualified Streamly.Internal.Data.Array.Storable.Foreign as A
651import qualified Streamly.Internal.Data.Array.Storable.Foreign as A
646−import qualified Streamly.Data.Fold as FL
652+import qualified Streamly.Internal.Data.Fold as FL
647−import qualified Streamly.Internal.Data.Fold.Types as FL
648import qualified Streamly.Internal.Data.Stream.Prelude as P
653import qualified Streamly.Internal.Data.Stream.Prelude as P
649import qualified Streamly.Internal.Data.Stream.StreamK as K
654import qualified Streamly.Internal.Data.Stream.StreamK as K
650import qualified Streamly.Internal.Data.Stream.StreamD as D
655import qualified Streamly.Internal.Data.Stream.StreamD as D
@@ -1410,7 +1415,10 @@ foldlM' step begin m = S.foldlM' step begin $ toStreamS m
1410-- Running a Fold
1415-- Running a Fold
1411------------------------------------------------------------------------------
1416------------------------------------------------------------------------------
1412
1417
1413−-- | Fold a stream using the supplied left fold.
1418+-- | Fold a stream using the supplied left 'Fold' and reducing the resulting
1419+-- expression strictly at each step. The behavior is similar to 'foldl''. A
1420+-- 'Fold' can terminate early without consuming the full stream. See the
1421+-- documentation of individual 'Fold's for termination behavior.
1414--
1422--
1415-- >>> S.fold FL.sum (S.enumerateFromTo 1 100)
1423-- >>> S.fold FL.sum (S.enumerateFromTo 1 100)
1416-- 5050
1424-- 5050
@@ -1461,6 +1469,7 @@ parse = parseD . PRK.fromParserK
1461
1469
1462-- |
1470-- |
1463-- > drain = mapM_ (\_ -> return ())
1471-- > drain = mapM_ (\_ -> return ())
1472+-- > drain = fold Fold.drain
1464--
1473--
1465-- Run a stream, discarding the results. By default it interprets the stream
1474-- Run a stream, discarding the results. By default it interprets the stream
1466-- as 'SerialT', to run other types of streams use the type adapting
1475-- as 'SerialT', to run other types of streams use the type adapting
@@ -1483,6 +1492,7 @@ runStream = drain
1483
1492
1484-- |
1493-- |
1485-- > drainN n = drain . take n
1494-- > drainN n = drain . take n
1495+-- > drainN n = fold (Fold.ltake n Fold.drain)
1486--
1496--
1487-- Run maximum up to @n@ iterations of a stream.
1497-- Run maximum up to @n@ iterations of a stream.
1488--
1498--
@@ -1504,6 +1514,7 @@ runN = drainN
1504
1514
1505-- |
1515-- |
1506-- > drainWhile p = drain . takeWhile p
1516-- > drainWhile p = drain . takeWhile p
1517+-- > drainWhile p = fold (Fold.sliceSepBy (not . p) Fold.drain)
1507--
1518--
1508-- Run a stream as long as the predicate holds true.
1519-- Run a stream as long as the predicate holds true.
1509--
1520--
@@ -1525,6 +1536,8 @@ runWhile = drainWhile
1525
1536
1526-- | Determine whether the stream is empty.
1537-- | Determine whether the stream is empty.
1527--
1538--
1539+-- > null = fold Fold.null
1540+--
1528-- @since 0.1.1
1541-- @since 0.1.1
1529{-# INLINE null #-}
1542{-# INLINE null #-}
1530null :: Monad m => SerialT m a -> m Bool
1543null :: Monad m => SerialT m a -> m Bool
@@ -1533,6 +1546,7 @@ null = S.null . toStreamS
1533-- | Extract the first element of the stream, if any.
1546-- | Extract the first element of the stream, if any.
1534--
1547--
1535-- > head = (!! 0)
1548-- > head = (!! 0)
1549+-- > head = fold Fold.head
1536--
1550--
1537-- @since 0.1.0
1551-- @since 0.1.0
1538{-# INLINE head #-}
1552{-# INLINE head #-}
@@ -1568,6 +1582,7 @@ init m = K.init (K.adapt m)
1568-- | Extract the last element of the stream, if any.
1582-- | Extract the last element of the stream, if any.
1569--
1583--
1570-- > last xs = xs !! (length xs - 1)
1584-- > last xs = xs !! (length xs - 1)
1585+-- > last = fold Fold.last
1571--
1586--
1572-- @since 0.1.1
1587-- @since 0.1.1
1573{-# INLINE last #-}
1588{-# INLINE last #-}
@@ -1576,6 +1591,8 @@ last m = S.last $ toStreamS m
1576
1591
1577-- | Determine whether an element is present in the stream.
1592-- | Determine whether an element is present in the stream.
1578--
1593--
1594+-- > elem = fold Fold.elem
1595+--
1579-- @since 0.1.0
1596-- @since 0.1.0
1580{-# INLINE elem #-}
1597{-# INLINE elem #-}
1581elem :: (Monad m, Eq a) => a -> SerialT m a -> m Bool
1598elem :: (Monad m, Eq a) => a -> SerialT m a -> m Bool
@@ -1583,6 +1600,8 @@ elem e m = S.elem e (toStreamS m)
1583
1600
1584-- | Determine whether an element is not present in the stream.
1601-- | Determine whether an element is not present in the stream.
1585--
1602--
1603+-- > notElem = fold Fold.notElem
1604+--
1586-- @since 0.1.0
1605-- @since 0.1.0
1587{-# INLINE notElem #-}
1606{-# INLINE notElem #-}
1588notElem :: (Monad m, Eq a) => a -> SerialT m a -> m Bool
1607notElem :: (Monad m, Eq a) => a -> SerialT m a -> m Bool
@@ -1590,6 +1609,8 @@ notElem e m = S.notElem e (toStreamS m)
1590
1609
1591-- | Determine the length of the stream.
1610-- | Determine the length of the stream.
1592--
1611--
1612+-- > notElem = fold Fold.length
1613+--
1593-- @since 0.1.0
1614-- @since 0.1.0
1594{-# INLINE length #-}
1615{-# INLINE length #-}
1595length :: Monad m => SerialT m a -> m Int
1616length :: Monad m => SerialT m a -> m Int
@@ -1597,6 +1618,8 @@ length = foldl' (\n _ -> n + 1) 0
1597
1618
1598-- | Determine whether all elements of a stream satisfy a predicate.
1619-- | Determine whether all elements of a stream satisfy a predicate.
1599--
1620--
1621+-- > all = fold Fold.all
1622+--
1600-- @since 0.1.0
1623-- @since 0.1.0
1601{-# INLINE all #-}
1624{-# INLINE all #-}
1602all :: Monad m => (a -> Bool) -> SerialT m a -> m Bool
1625all :: Monad m => (a -> Bool) -> SerialT m a -> m Bool
@@ -1604,6 +1627,8 @@ all p m = S.all p (toStreamS m)
1604
1627
1605-- | Determine whether any of the elements of a stream satisfy a predicate.
1628-- | Determine whether any of the elements of a stream satisfy a predicate.
1606--
1629--
1630+-- > any = fold Fold.any
1631+--
1607-- @since 0.1.0
1632-- @since 0.1.0
1608{-# INLINE any #-}
1633{-# INLINE any #-}
1609any :: Monad m => (a -> Bool) -> SerialT m a -> m Bool
1634any :: Monad m => (a -> Bool) -> SerialT m a -> m Bool
@@ -1611,6 +1636,8 @@ any p m = S.any p (toStreamS m)
1611
1636
1612-- | Determines if all elements of a boolean stream are True.
1637-- | Determines if all elements of a boolean stream are True.
1613--
1638--
1639+-- > and = fold Fold.and
1640+--
1614-- @since 0.5.0
1641-- @since 0.5.0
1615{-# INLINE and #-}
1642{-# INLINE and #-}
1616and :: Monad m => SerialT m Bool -> m Bool
1643and :: Monad m => SerialT m Bool -> m Bool
@@ -1618,6 +1645,8 @@ and = all (==True)
1618
1645
1619-- | Determines whether at least one element of a boolean stream is True.
1646-- | Determines whether at least one element of a boolean stream is True.
1620--
1647--
1648+-- > or = fold Fold.or
1649+--
1621-- @since 0.5.0
1650-- @since 0.5.0
1622{-# INLINE or #-}
1651{-# INLINE or #-}
1623or :: Monad m => SerialT m Bool -> m Bool
1652or :: Monad m => SerialT m Bool -> m Bool
@@ -1627,6 +1656,8 @@ or = any (==True)
1627-- the stream is empty. Note that this is not numerically stable for floating
1656-- the stream is empty. Note that this is not numerically stable for floating
1628-- point numbers.
1657-- point numbers.
1629--
1658--
1659+-- > sum = fold Fold.sum
1660+--
1630-- @since 0.1.0
1661-- @since 0.1.0
1631{-# INLINE sum #-}
1662{-# INLINE sum #-}
1632sum :: (Monad m, Num a) => SerialT m a -> m a
1663sum :: (Monad m, Num a) => SerialT m a -> m a
@@ -1635,6 +1666,8 @@ sum = foldl' (+) 0
1635-- | Determine the product of all elements of a stream of numbers. Returns @1@
1666-- | Determine the product of all elements of a stream of numbers. Returns @1@
1636-- when the stream is empty.
1667-- when the stream is empty.
1637--
1668--
1669+-- > product = fold Fold.product
1670+--
1638-- @since 0.1.1
1671-- @since 0.1.1
1639{-# INLINE product #-}
1672{-# INLINE product #-}
1640product :: (Monad m, Num a) => SerialT m a -> m a
1673product :: (Monad m, Num a) => SerialT m a -> m a
@@ -1642,6 +1675,8 @@ product = foldl' (*) 1
1642
1675
1643-- | Fold a stream of monoid elements by appending them.
1676-- | Fold a stream of monoid elements by appending them.
1644--
1677--
1678+-- > mconcat = fold Fold.mconcat
1679+--
1645-- /Internal/
1680-- /Internal/
1646{-# INLINE mconcat #-}
1681{-# INLINE mconcat #-}
1647mconcat :: (Monad m, Monoid a) => SerialT m a -> m a
1682mconcat :: (Monad m, Monoid a) => SerialT m a -> m a
@@ -1650,6 +1685,7 @@ mconcat = foldr mappend mempty
1650-- |
1685-- |
1651-- @
1686-- @
1652-- minimum = 'minimumBy' compare
1687-- minimum = 'minimumBy' compare
1688+-- minimum = fold Fold.minimum
1653-- @
1689-- @
1654--
1690--
1655-- Determine the minimum element in a stream.
1691-- Determine the minimum element in a stream.
@@ -1662,6 +1698,8 @@ minimum m = S.minimum (toStreamS m)
1662-- | Determine the minimum element in a stream using the supplied comparison
1698-- | Determine the minimum element in a stream using the supplied comparison
1663-- function.
1699-- function.
1664--
1700--
1701+-- > minimumBy = fold Fold.minimumBy
1702+--
1665-- @since 0.6.0
1703-- @since 0.6.0
1666{-# INLINE minimumBy #-}
1704{-# INLINE minimumBy #-}
1667minimumBy :: Monad m => (a -> a -> Ordering) -> SerialT m a -> m (Maybe a)
1705minimumBy :: Monad m => (a -> a -> Ordering) -> SerialT m a -> m (Maybe a)
@@ -1670,6 +1708,7 @@ minimumBy cmp m = S.minimumBy cmp (toStreamS m)
1670-- |
1708-- |
1671-- @
1709-- @
1672-- maximum = 'maximumBy' compare
1710-- maximum = 'maximumBy' compare
1711+-- maximum = fold Fold.maximum
1673-- @
1712-- @
1674--
1713--
1675-- Determine the maximum element in a stream.
1714-- Determine the maximum element in a stream.
@@ -1682,6 +1721,8 @@ maximum = P.maximum
1682-- | Determine the maximum element in a stream using the supplied comparison
1721-- | Determine the maximum element in a stream using the supplied comparison
1683-- function.
1722-- function.
1684--
1723--
1724+-- > maximumBy = fold Fold.maximumBy
1725+--
1685-- @since 0.6.0
1726-- @since 0.6.0
1686{-# INLINE maximumBy #-}
1727{-# INLINE maximumBy #-}
1687maximumBy :: Monad m => (a -> a -> Ordering) -> SerialT m a -> m (Maybe a)
1728maximumBy :: Monad m => (a -> a -> Ordering) -> SerialT m a -> m (Maybe a)
@@ -1698,6 +1739,7 @@ m !! i = toStreamS m S.!! i
1698-- first pair where the key equals the given value @a@.
1739-- first pair where the key equals the given value @a@.
1699--
1740--
1700-- > lookup = snd <$> find ((==) . fst)
1741-- > lookup = snd <$> find ((==) . fst)
1742+-- > lookup = fold Fold.lookup
1701--
1743--
1702-- @since 0.5.0
1744-- @since 0.5.0
1703{-# INLINE lookup #-}
1745{-# INLINE lookup #-}
@@ -1707,6 +1749,7 @@ lookup a m = S.lookup a (toStreamS m)
1707-- | Like 'findM' but with a non-monadic predicate.
1749-- | Like 'findM' but with a non-monadic predicate.
1708--
1750--
1709-- > find p = findM (return . p)
1751-- > find p = findM (return . p)
1752+-- > find = fold Fold.find
1710--
1753--
1711-- @since 0.5.0
1754-- @since 0.5.0
1712{-# INLINE find #-}
1755{-# INLINE find #-}
@@ -1715,6 +1758,8 @@ find p m = S.find p (toStreamS m)
1715
1758
1716-- | Returns the first element that satisfies the given predicate.
1759-- | Returns the first element that satisfies the given predicate.
1717--
1760--
1761+-- > findM = fold Fold.findM
1762+--
1718-- @since 0.6.0
1763-- @since 0.6.0
1719{-# INLINE findM #-}
1764{-# INLINE findM #-}
1720findM :: Monad m => (a -> m Bool) -> SerialT m a -> m (Maybe a)
1765findM :: Monad m => (a -> m Bool) -> SerialT m a -> m (Maybe a)
@@ -1723,6 +1768,8 @@ findM p m = S.findM p (toStreamS m)
1723-- | Find all the indices where the element in the stream satisfies the given
1768-- | Find all the indices where the element in the stream satisfies the given
1724-- predicate.
1769-- predicate.
1725--
1770--
1771+-- > findIndices = fold Fold.findIndices
1772+--
1726-- @since 0.5.0
1773-- @since 0.5.0
1727{-# INLINE findIndices #-}
1774{-# INLINE findIndices #-}
1728findIndices :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> t m Int
1775findIndices :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> t m Int
@@ -1730,6 +1777,8 @@ findIndices p m = fromStreamS $ S.findIndices p (toStreamS m)
1730
1777
1731-- | Returns the first index that satisfies the given predicate.
1778-- | Returns the first index that satisfies the given predicate.
1732--
1779--
1780+-- > findIndex = fold Fold.findIndex
1781+--
1733-- @since 0.5.0
1782-- @since 0.5.0
1734{-# INLINE findIndex #-}
1783{-# INLINE findIndex #-}
1735findIndex :: Monad m => (a -> Bool) -> SerialT m a -> m (Maybe Int)
1784findIndex :: Monad m => (a -> Bool) -> SerialT m a -> m (Maybe Int)
@@ -1738,10 +1787,12 @@ findIndex p = head . findIndices p
1738-- | Find all the indices where the value of the element in the stream is equal
1787-- | Find all the indices where the value of the element in the stream is equal
1739-- to the given value.
1788-- to the given value.
1740--
1789--
1790+-- > elemIndices a = findIndices (== a)
1791+--
1741-- @since 0.5.0
1792-- @since 0.5.0
1742{-# INLINE elemIndices #-}
1793{-# INLINE elemIndices #-}
1743elemIndices :: (IsStream t, Eq a, Monad m) => a -> t m a -> t m Int
1794elemIndices :: (IsStream t, Eq a, Monad m) => a -> t m a -> t m Int
1744−elemIndices a = findIndices (==a)
1795+elemIndices a = findIndices (== a)
1745
1796
1746-- | Returns the first index where a given value is found in the stream.
1797-- | Returns the first index where a given value is found in the stream.
1747--
1798--
@@ -3636,7 +3687,7 @@ iterateMapLeftsWith
3636iterateMapLeftsWith combine f = iterateMapWith combine (either f (const K.nil))
3687iterateMapLeftsWith combine f = iterateMapWith combine (either f (const K.nil))
3637
3688
3638------------------------------------------------------------------------------
3689------------------------------------------------------------------------------
3639−-- Parsing
3690+-- Folding/Parsing chunks in a stream
3640------------------------------------------------------------------------------
3691------------------------------------------------------------------------------
3641
3692
3642-- Splitting operations that take a predicate and a Fold can be
3693-- Splitting operations that take a predicate and a Fold can be
@@ -3645,6 +3696,67 @@ iterateMapLeftsWith combine f = iterateMapWith combine (either f (const K.nil))
3645--
3696--
3646-- XXX We need takeGE/takeBetween to implement "some" using "many".
3697-- XXX We need takeGE/takeBetween to implement "some" using "many".
3647
3698
3699+-- | Apply a 'Fold' repeatedly on a stream and emit the parsed values in the
3700+-- output stream.
3701+--
3702+-- This is the streaming dual of the 'Streamly.Internal.Data.Fold.many'
3703+-- parse combinator.
3704+--
3705+-- >>> f = Fold.ltake 2 Fold.sum
3706+-- >>> Stream.toList $ Stream.foldMany f $ Stream.fromList [1..10]
3707+-- > [3,7,11,15,19]
3708+--
3709+-- >>> f = Fold.sliceEndWith Fold.toList
3710+-- >>> Stream.toList $ Stream.foldMany f $ Stream.fromList "hello\nworld"
3711+-- > ["hello\n","world"]
3712+--
3713+-- /Internal/
3714+--
3715+{-# INLINE foldMany #-}
3716+foldMany
3717+ :: (IsStream t, Monad m)
3718+ => Fold m a b
3719+ -> t m a
3720+ -> t m b
3721+foldMany f m = D.fromStreamD $ D.foldMany f (D.toStreamD m)
3722+
3723+-- | Apply a stream of folds to an input stream and emit the results in the
3724+-- output stream.
3725+--
3726+-- /Internal/
3727+--
3728+{-# INLINE foldSequence #-}
3729+foldSequence
3730+ :: -- (IsStream t, Monad m) =>
3731+ t m (Fold m a b)
3732+ -> t m a
3733+ -> t m b
3734+foldSequence _f _m = undefined
3735+
3736+-- | Iterate a fold generator on a stream. The initial value @b@ is used to
3737+-- generate the first fold, the fold is applied on the stream and the result of
3738+-- the fold is used to generate the next fold and so on.
3739+--
3740+-- >>> f x = Fold.ltake 2 (Fold.mconcatTo x)
3741+-- >>> s = Stream.map Sum $ Stream.fromList [1..10]
3742+-- >>> Stream.toList $ Stream.map getSum $ Stream.foldIterate f 0 s
3743+-- > [3,10,21,36,55,55]
3744+--
3745+-- This is the streaming equivalent of monad like sequenced application of
3746+-- folds where next fold is dependent on the previous fold.
3747+--
3748+-- /Internal/
3749+--
3750+{-# INLINE foldIterate #-}
3751+foldIterate
3752+ :: -- (IsStream t, Monad m) =>
3753+ (b -> Fold m a b)
3754+ -> b
3755+ -> t m a
3756+ -> t m b
3757+foldIterate _f _i _m = undefined
3758+-- D.fromStreamD $ D.foldIterate f i (D.toStreamD m)
3759+
3648-- | Apply a 'Parser' repeatedly on a stream and emit the parsed values in the
3760-- | Apply a 'Parser' repeatedly on a stream and emit the parsed values in the
3649-- output stream.
3761-- output stream.
3650--
3762--
@@ -3657,7 +3769,7 @@ iterateMapLeftsWith combine f = iterateMapWith combine (either f (const K.nil))
3657-- >>> S.toList $ S.parseMany (PR.line FL.toList) $ S.fromList "hello\nworld"
3769-- >>> S.toList $ S.parseMany (PR.line FL.toList) $ S.fromList "hello\nworld"
3658-- > ["hello\n","world"]
3770-- > ["hello\n","world"]
3659--
3771--
3660−-- /Internal
3772+-- /Internal/
3661--
3773--
3662{-# INLINE parseMany #-}
3774{-# INLINE parseMany #-}
3663parseMany
3775parseMany
@@ -3677,6 +3789,19 @@ parseManyD
3677parseManyD p m =
3789parseManyD p m =
3678 D.fromStreamD $ D.parseMany p (D.toStreamD m)
3790 D.fromStreamD $ D.parseMany p (D.toStreamD m)
3679
3791
3792+-- | Apply a stream of parsers to an input stream and emit the results in the
3793+-- output stream.
3794+--
3795+-- /Internal/
3796+--
3797+{-# INLINE parseSequence #-}
3798+parseSequence
3799+ :: -- (IsStream t, Monad m) =>
3800+ t m (Parser m a b)
3801+ -> t m a
3802+ -> t m b
3803+parseSequence _f _m = undefined
3804+
3680-- | @parseManyTill collect test stream@ tries the parser @test@ on the input,
3805-- | @parseManyTill collect test stream@ tries the parser @test@ on the input,
3681-- if @test@ fails it backtracks and tries @collect@, after @collect@ succeeds
3806-- if @test@ fails it backtracks and tries @collect@, after @collect@ succeeds
3682-- @test@ is tried again and so on. The parser stops when @test@ succeeds. The
3807-- @test@ is tried again and so on. The parser stops when @test@ succeeds. The
@@ -3786,7 +3911,7 @@ groupScan split fold m = undefined
3786chunksOf
3911chunksOf
3787 :: (IsStream t, Monad m)
3912 :: (IsStream t, Monad m)
3788 => Int -> Fold m a b -> t m a -> t m b
3913 => Int -> Fold m a b -> t m a -> t m b
3789−chunksOf n f m = D.fromStreamD $ D.groupsOf n f (D.toStreamD m)
3914+chunksOf n f = foldMany (FL.ltake n f)
3790
3915
3791-- |
3916-- |
3792--
3917--
@@ -3831,8 +3956,6 @@ intervalsOf n f xs =
3831-- N-ary APIs
3956-- N-ary APIs
3832------------------------------------------------------------------------------
3957------------------------------------------------------------------------------
3833
3958
3834−-- XXX We should probably change the order of the comparision and update the
3835−-- docs accordingly.
3836-- | @groupsBy cmp f $ S.fromList [a,b,c,...]@ assigns the element @a@ to the
3959-- | @groupsBy cmp f $ S.fromList [a,b,c,...]@ assigns the element @a@ to the
3837-- first group, if @b \`cmp` a@ is 'True' then @b@ is also assigned to the same
3960-- first group, if @b \`cmp` a@ is 'True' then @b@ is also assigned to the same
3838-- group. If @c \`cmp` a@ is 'True' then @c@ is also assigned to the same
3961-- group. If @c \`cmp` a@ is 'True' then @c@ is also assigned to the same
@@ -3945,8 +4068,7 @@ groups = groupsBy (==)
3945splitOn
4068splitOn
3946 :: (IsStream t, Monad m)
4069 :: (IsStream t, Monad m)
3947 => (a -> Bool) -> Fold m a b -> t m a -> t m b
4070 => (a -> Bool) -> Fold m a b -> t m a -> t m b
3948−splitOn predicate f m =
4071+splitOn predicate f = foldMany (FL.sliceSepBy predicate f)
3949− D.fromStreamD $ D.splitBy predicate f (D.toStreamD m)
3950
4072
3951-- | Like 'splitOn' but the separator is considered as suffixed to the segments
4073-- | Like 'splitOn' but the separator is considered as suffixed to the segments
3952-- in the stream. A missing suffix at the end is allowed. A separator at the
4074-- in the stream. A missing suffix at the end is allowed. A separator at the
@@ -3998,7 +4120,7 @@ splitOnSuffix
3998 :: (IsStream t, Monad m)
4120 :: (IsStream t, Monad m)
3999 => (a -> Bool) -> Fold m a b -> t m a -> t m b
4121 => (a -> Bool) -> Fold m a b -> t m a -> t m b
4000splitOnSuffix predicate f m =
4122splitOnSuffix predicate f m =
4001− D.fromStreamD $ D.splitSuffixBy predicate f (D.toStreamD m)
4123+ D.fromStreamD $ D.foldMany1 (FL.sliceSepBy predicate f) (D.toStreamD m)
4002
4124
4003-- | Like 'splitOn' after stripping leading, trailing, and repeated separators.
4125-- | Like 'splitOn' after stripping leading, trailing, and repeated separators.
4004-- Therefore, @".a..b."@ with '.' as the separator would be parsed as
4126-- Therefore, @".a..b."@ with '.' as the separator would be parsed as
@@ -4068,7 +4190,7 @@ splitWithSuffix
4068 :: (IsStream t, Monad m)
4190 :: (IsStream t, Monad m)
4069 => (a -> Bool) -> Fold m a b -> t m a -> t m b
4191 => (a -> Bool) -> Fold m a b -> t m a -> t m b
4070splitWithSuffix predicate f m =
4192splitWithSuffix predicate f m =
4071− D.fromStreamD $ D.splitSuffixWith predicate f (D.toStreamD m)
4193+ D.fromStreamD $ D.foldMany1 (FL.sliceEndWith predicate f) (D.toStreamD m)
4072
4194
4073------------------------------------------------------------------------------
4195------------------------------------------------------------------------------
4074-- Split on a delimiter sequence
4196-- Split on a delimiter sequence
@@ -4758,13 +4880,12 @@ classifySessionsBy tick tmout reset ejectPred
4758 -- better performance.
4880 -- better performance.
4759 --
4881 --
4760 let curTime = max sessionEventTime timestamp
4882 let curTime = max sessionEventTime timestamp
4761− extractOld v =
4762− case v of
4763− Nothing -> initial
4764− Just (Tuple' _ acc) -> return acc
4765 mOld = Map.lookup key sessionKeyValueMap
4883 mOld = Map.lookup key sessionKeyValueMap
4766
4884
4767− fs <- extractOld mOld
4885+ fs <-
4886+ case mOld of
4887+ Nothing -> initial
4888+ Just (Tuple' _ acc) -> return acc
4768 res <- step fs value
4889 res <- step fs value
4769 case res of
4890 case res of
4770 FL.Done fb -> do
4891 FL.Done fb -> do
src/Streamly/Internal/Data/Stream/StreamD.hs+152−166
@@ -103,6 +103,8 @@ module Streamly.Internal.Data.Stream.StreamD
103 , foldlx'
103 , foldlx'
104 , foldlMx'
104 , foldlMx'
105 , foldOnce
105 , foldOnce
106+ , foldMany
107+ , foldMany1
106
108
107 , parselMx'
109 , parselMx'
108 , parseMany
110 , parseMany
@@ -157,16 +159,12 @@ module Streamly.Internal.Data.Stream.StreamD
157 , interpose
159 , interpose
158
160
159 -- ** Grouping
161 -- ** Grouping
160− , groupsOf
161 , groupsOf2
162 , groupsOf2
162 , groupsBy
163 , groupsBy
163 , groupsRollingBy
164 , groupsRollingBy
164
165
165 -- ** Splitting
166 -- ** Splitting
166− , splitBy
167− , splitSuffixBy
168 , wordsBy
167 , wordsBy
169− , splitSuffixWith
170
168
171 , splitOnSeq
169 , splitOnSeq
172 , splitOnSuffixSeq
170 , splitOnSuffixSeq
@@ -1519,11 +1517,6 @@ reverse' m =
1519-- Grouping/Splitting
1517-- Grouping/Splitting
1520------------------------------------------------------------------------------
1518------------------------------------------------------------------------------
1521
1519
1522−{-# INLINE_NORMAL splitSuffixWith #-}
1523−splitSuffixWith :: Monad m
1524− => (a -> Bool) -> Fold m a b -> Stream m a -> Stream m b
1525−splitSuffixWith predicate f = foldMany1 (FL.sliceEndWith predicate f)
1526−
1527{-# INLINE_NORMAL groupsBy #-}
1520{-# INLINE_NORMAL groupsBy #-}
1528groupsBy :: Monad m
1521groupsBy :: Monad m
1529 => (a -> a -> Bool)
1522 => (a -> a -> Bool)
@@ -1540,11 +1533,11 @@ groupsBy cmp f (Stream step state) = Stream (stepOuter f) (Just state, Nothing)
1540 case res of
1533 case res of
1541 Yield x s -> do
1534 Yield x s -> do
1542 fs <- initial
1535 fs <- initial
1543− sfs <- fstep fs x
1536+ r <- fstep fs x
1544− case sfs of
1537+ case r of
1545 FL.Partial fs1 -> go SPEC x s fs1
1538 FL.Partial fs1 -> go SPEC x s fs1
1546− FL.Done fb -> return $ Yield fb (Just s, Just x)
1539+ FL.Done b -> return $ Yield b (Just s, Just x)
1547− Skip s -> return $ Skip $ (Just s, Nothing)
1540+ Skip s -> return $ Skip (Just s, Nothing)
1548 Stop -> return Stop
1541 Stop -> return Stop
1549
1542
1550 where
1543 where
@@ -1555,19 +1548,19 @@ groupsBy cmp f (Stream step state) = Stream (stepOuter f) (Just state, Nothing)
1555 Yield x s -> do
1548 Yield x s -> do
1556 if cmp x prev
1549 if cmp x prev
1557 then do
1550 then do
1558− sfs <- fstep acc x
1551+ r <- fstep acc x
1559− case sfs of
1552+ case r of
1560 FL.Partial fs1 -> go SPEC prev s fs1
1553 FL.Partial fs1 -> go SPEC prev s fs1
1561− FL.Done fb -> return $ Yield fb (Just s, Just x)
1554+ FL.Done b -> return $ Yield b (Just s, Just x)
1562 else done acc >>= \r -> return $ Yield r (Just s, Just x)
1555 else done acc >>= \r -> return $ Yield r (Just s, Just x)
1563 Skip s -> go SPEC prev s acc
1556 Skip s -> go SPEC prev s acc
1564 Stop -> done acc >>= \r -> return $ Yield r (Nothing, Nothing)
1557 Stop -> done acc >>= \r -> return $ Yield r (Nothing, Nothing)
1565 stepOuter (Fold fstep initial done) gst (Just st, Just prev) = do
1558 stepOuter (Fold fstep initial done) gst (Just st, Just prev) = do
1566 fs <- initial
1559 fs <- initial
1567− sfs <- fstep fs prev
1560+ r <- fstep fs prev
1568− case sfs of
1561+ case r of
1569 FL.Partial fs1 -> go SPEC st fs1
1562 FL.Partial fs1 -> go SPEC st fs1
1570− FL.Done fb -> return $ Yield fb (Just st, Nothing)
1563+ FL.Done b -> return $ Yield b (Just st, Nothing)
1571
1564
1572 where
1565 where
1573
1566
@@ -1578,10 +1571,10 @@ groupsBy cmp f (Stream step state) = Stream (stepOuter f) (Just state, Nothing)
1578 Yield x s -> do
1571 Yield x s -> do
1579 if cmp x prev
1572 if cmp x prev
1580 then do
1573 then do
1581− sfs <- fstep acc x
1574+ r <- fstep acc x
1582− case sfs of
1575+ case r of
1583 FL.Partial fs1 -> go SPEC s fs1
1576 FL.Partial fs1 -> go SPEC s fs1
1584− FL.Done fb -> return $ Yield fb (Just s, Just x)
1577+ FL.Done b -> return $ Yield b (Just s, Just x)
1585 else done acc >>= \r -> return $ Yield r (Just s, Just x)
1578 else done acc >>= \r -> return $ Yield r (Just s, Just x)
1586 Skip s -> go SPEC s acc
1579 Skip s -> go SPEC s acc
1587 Stop -> done acc >>= \r -> return $ Yield r (Nothing, Nothing)
1580 Stop -> done acc >>= \r -> return $ Yield r (Nothing, Nothing)
@@ -1604,10 +1597,10 @@ groupsRollingBy cmp f (Stream step state) =
1604 case res of
1597 case res of
1605 Yield x s -> do
1598 Yield x s -> do
1606 fs <- initial
1599 fs <- initial
1607− sfs <- fstep fs x
1600+ r <- fstep fs x
1608− case sfs of
1601+ case r of
1609 FL.Partial fs1 -> go SPEC x s fs1
1602 FL.Partial fs1 -> go SPEC x s fs1
1610− FL.Done fb -> return $ Yield fb (Just s, Just x)
1603+ FL.Done b -> return $ Yield b (Just s, Just x)
1611 Skip s -> return $ Skip $ (Just s, Nothing)
1604 Skip s -> return $ Skip $ (Just s, Nothing)
1612 Stop -> return Stop
1605 Stop -> return Stop
1613
1606
@@ -1619,19 +1612,19 @@ groupsRollingBy cmp f (Stream step state) =
1619 Yield x s -> do
1612 Yield x s -> do
1620 if cmp prev x
1613 if cmp prev x
1621 then do
1614 then do
1622− sfs <- fstep acc x
1615+ r <- fstep acc x
1623− case sfs of
1616+ case r of
1624 FL.Partial fs1 -> go SPEC x s fs1
1617 FL.Partial fs1 -> go SPEC x s fs1
1625− FL.Done fb -> return $ Yield fb (Just s, Just x)
1618+ FL.Done b -> return $ Yield b (Just s, Just x)
1626 else done acc >>= \r -> return $ Yield r (Just s, Just x)
1619 else done acc >>= \r -> return $ Yield r (Just s, Just x)
1627 Skip s -> go SPEC prev s acc
1620 Skip s -> go SPEC prev s acc
1628 Stop -> done acc >>= \r -> return $ Yield r (Nothing, Nothing)
1621 Stop -> done acc >>= \r -> return $ Yield r (Nothing, Nothing)
1629 stepOuter (Fold fstep initial done) gst (Just st, Just prev') = do
1622 stepOuter (Fold fstep initial done) gst (Just st, Just prev') = do
1630 fs <- initial
1623 fs <- initial
1631− sfs <- fstep fs prev'
1624+ r <- fstep fs prev'
1632− case sfs of
1625+ case r of
1633 FL.Partial fs1 -> go SPEC prev' st fs1
1626 FL.Partial fs1 -> go SPEC prev' st fs1
1634− FL.Done fb -> return $ Yield fb (Just st, Nothing)
1627+ FL.Done b -> return $ Yield b (Just st, Nothing)
1635
1628
1636 where
1629 where
1637
1630
@@ -1641,24 +1634,15 @@ groupsRollingBy cmp f (Stream step state) =
1641 Yield x s -> do
1634 Yield x s -> do
1642 if cmp prevv x
1635 if cmp prevv x
1643 then do
1636 then do
1644− sfs <- fstep acc x
1637+ r <- fstep acc x
1645− case sfs of
1638+ case r of
1646 FL.Partial fs1 -> go SPEC x s fs1
1639 FL.Partial fs1 -> go SPEC x s fs1
1647− FL.Done fb -> return $ Yield fb (Just s, Just x)
1640+ FL.Done b -> return $ Yield b (Just s, Just x)
1648 else done acc >>= \r -> return $ Yield r (Just s, Just x)
1641 else done acc >>= \r -> return $ Yield r (Just s, Just x)
1649 Skip s -> go SPEC prevv s acc
1642 Skip s -> go SPEC prevv s acc
1650 Stop -> done acc >>= \r -> return $ Yield r (Nothing, Nothing)
1643 Stop -> done acc >>= \r -> return $ Yield r (Nothing, Nothing)
1651 stepOuter _ _ (Nothing, _) = return Stop
1644 stepOuter _ _ (Nothing, _) = return Stop
1652
1645
1653−{-# INLINE_NORMAL splitBy #-}
1654−splitBy :: Monad m => (a -> Bool) -> Fold m a b -> Stream m a -> Stream m b
1655−splitBy predicate f = foldMany (FL.sliceSepBy predicate f)
1656−
1657−{-# INLINE_NORMAL splitSuffixBy #-}
1658−splitSuffixBy :: Monad m
1659− => (a -> Bool) -> Fold m a b -> Stream m a -> Stream m b
1660−splitSuffixBy predicate f = foldMany1 (FL.sliceSepBy predicate f)
1661−
1662data WordsByState s = WordsByJust s | WordsByNothing
1646data WordsByState s = WordsByJust s | WordsByNothing
1663
1647
1664{-# INLINE_NORMAL wordsBy #-}
1648{-# INLINE_NORMAL wordsBy #-}
@@ -1677,10 +1661,10 @@ wordsBy predicate f (Stream step state) =
1677 then return $ Skip (WordsByJust s)
1661 then return $ Skip (WordsByJust s)
1678 else do
1662 else do
1679 fs <- initial
1663 fs <- initial
1680− sfs <- fstep fs x
1664+ r <- fstep fs x
1681− case sfs of
1665+ case r of
1682 FL.Partial fs1 -> go SPEC s fs1
1666 FL.Partial fs1 -> go SPEC s fs1
1683− FL.Done fb -> return $ Yield fb (WordsByJust s)
1667+ FL.Done b -> return $ Yield b (WordsByJust s)
1684
1668
1685 Skip s -> return $ Skip $ WordsByJust s
1669 Skip s -> return $ Skip $ WordsByJust s
1686 Stop -> return Stop
1670 Stop -> return Stop
@@ -1694,10 +1678,10 @@ wordsBy predicate f (Stream step state) =
1694 if predicate x
1678 if predicate x
1695 then done acc >>= \r -> return $ Yield r (WordsByJust s)
1679 then done acc >>= \r -> return $ Yield r (WordsByJust s)
1696 else do
1680 else do
1697− sfs <- fstep acc x
1681+ r <- fstep acc x
1698− case sfs of
1682+ case r of
1699 FL.Partial fs1 -> go SPEC s fs1
1683 FL.Partial fs1 -> go SPEC s fs1
1700− FL.Done fb -> return $ Yield fb (WordsByJust s)
1684+ FL.Done b -> return $ Yield b (WordsByJust s)
1701 Skip s -> go SPEC s acc
1685 Skip s -> go SPEC s acc
1702 Stop -> done acc >>= \r -> return $ Yield r WordsByNothing
1686 Stop -> done acc >>= \r -> return $ Yield r WordsByNothing
1703
1687
@@ -1808,13 +1792,13 @@ splitOnSeq patArr (Fold fstep initial done) (Stream step state) =
1808 res <- step (adaptState gst) st
1792 res <- step (adaptState gst) st
1809 case res of
1793 case res of
1810 Yield x s -> do
1794 Yield x s -> do
1811− acc <- initial
1795+ fs <- initial
1812− sfs <- fstep acc x
1796+ r <- fstep fs x
1813− case sfs of
1797+ case r of
1814− FL.Partial acc1 -> do
1798+ FL.Partial fs1 -> do
1815− r <- done acc1
1799+ b <- done fs1
1816− skip $ SplitOnSeqYield r (SplitOnSeqEmpty s)
1800+ skip $ SplitOnSeqYield b (SplitOnSeqEmpty s)
1817− FL.Done fb -> skip $ SplitOnSeqYield fb (SplitOnSeqEmpty s)
1801+ FL.Done b -> skip $ SplitOnSeqYield b (SplitOnSeqEmpty s)
1818
1802
1819 Skip s -> return $ Skip (SplitOnSeqEmpty s)
1803 Skip s -> return $ Skip (SplitOnSeqEmpty s)
1820 Stop -> return Stop
1804 Stop -> return Stop
@@ -1839,12 +1823,12 @@ splitOnSeq patArr (Fold fstep initial done) (Stream step state) =
1839 fs1 <- initial
1823 fs1 <- initial
1840 return $ Skip $ SplitOnSeqYield r (SplitOnSeqSingle fs1 s pat)
1824 return $ Skip $ SplitOnSeqYield r (SplitOnSeqSingle fs1 s pat)
1841 else do
1825 else do
1842− sfs <- fstep fs x
1826+ r <- fstep fs x
1843− case sfs of
1827+ case r of
1844− FL.Partial fs1 -> skip $ (SplitOnSeqSingle fs1 s pat)
1828+ FL.Partial fs1 -> skip $ SplitOnSeqSingle fs1 s pat
1845− FL.Done fb -> do
1829+ FL.Done b -> do
1846 fs1 <- initial
1830 fs1 <- initial
1847− skip $ SplitOnSeqYield fb (SplitOnSeqSingle fs1 s pat)
1831+ skip $ SplitOnSeqYield b (SplitOnSeqSingle fs1 s pat)
1848 Skip s -> return $ Skip $ SplitOnSeqSingle fs s pat
1832 Skip s -> return $ Skip $ SplitOnSeqSingle fs s pat
1849 Stop -> do
1833 Stop -> do
1850 r <- done fs
1834 r <- done fs
@@ -1859,13 +1843,13 @@ splitOnSeq patArr (Fold fstep initial done) (Stream step state) =
1859 skip $ SplitOnSeqYield r SplitOnSeqDone
1843 skip $ SplitOnSeqYield r SplitOnSeqDone
1860 stepOuter _ (SplitOnSeqWordDone n fs wrd) = do
1844 stepOuter _ (SplitOnSeqWordDone n fs wrd) = do
1861 let old = elemMask .&. (wrd `shiftR` (elemBits * (n - 1)))
1845 let old = elemMask .&. (wrd `shiftR` (elemBits * (n - 1)))
1862− sfs <- fstep fs (toEnum $ fromIntegral old)
1846+ r <- fstep fs (toEnum $ fromIntegral old)
1863− case sfs of
1847+ case r of
1864 FL.Partial fs1 -> skip $ SplitOnSeqWordDone (n - 1) fs1 wrd
1848 FL.Partial fs1 -> skip $ SplitOnSeqWordDone (n - 1) fs1 wrd
1865− FL.Done r -> do
1849+ FL.Done b -> do
1866 fs1 <- initial
1850 fs1 <- initial
1867 let next = SplitOnSeqWordDone (n - 1) fs1 wrd
1851 let next = SplitOnSeqWordDone (n - 1) fs1 wrd
1868− skip $ SplitOnSeqYield r next
1852+ skip $ SplitOnSeqYield b next
1869
1853
1870 stepOuter gst (SplitOnSeqWordInit st0) =
1854 stepOuter gst (SplitOnSeqWordInit st0) =
1871 go SPEC 0 0 st0
1855 go SPEC 0 0 st0
@@ -1910,18 +1894,18 @@ splitOnSeq patArr (Fold fstep initial done) (Stream step state) =
1910 let wrd1 = addToWord wrd x
1894 let wrd1 = addToWord wrd x
1911 old = (wordMask .&. wrd)
1895 old = (wordMask .&. wrd)
1912 `shiftR` (elemBits * (patLen - 1))
1896 `shiftR` (elemBits * (patLen - 1))
1913− sfs <- fstep fs (toEnum $ fromIntegral old)
1897+ r <- fstep fs (toEnum $ fromIntegral old)
1914− case sfs of
1898+ case r of
1915 FL.Partial fs1 -> do
1899 FL.Partial fs1 -> do
1916 if wrd1 .&. wordMask == wordPat
1900 if wrd1 .&. wordMask == wordPat
1917 then do
1901 then do
1918− r <- done fs1
1902+ b <- done fs1
1919 let next = SplitOnSeqWordInit s
1903 let next = SplitOnSeqWordInit s
1920− skip $ SplitOnSeqYield r next
1904+ skip $ SplitOnSeqYield b next
1921 else go SPEC wrd1 s fs1
1905 else go SPEC wrd1 s fs1
1922− FL.Done r ->
1906+ FL.Done b ->
1923 let next = SplitOnSeqWordInit s
1907 let next = SplitOnSeqWordInit s
1924− in skip $ SplitOnSeqYield r next
1908+ in skip $ SplitOnSeqYield b next
1925 Skip s -> go SPEC wrd s fs
1909 Skip s -> go SPEC wrd s fs
1926 Stop -> skip $ SplitOnSeqWordDone patLen fs wrd
1910 Stop -> skip $ SplitOnSeqWordDone patLen fs wrd
1927
1911
@@ -1963,16 +1947,16 @@ splitOnSeq patArr (Fold fstep initial done) (Stream step state) =
1963 Yield x s -> do
1947 Yield x s -> do
1964 old <- liftIO $ peek rh
1948 old <- liftIO $ peek rh
1965 let cksum1 = deltaCksum cksum old x
1949 let cksum1 = deltaCksum cksum old x
1966− sfs <- fstep fs old
1950+ r <- fstep fs old
1967− case sfs of
1951+ case r of
1968 FL.Partial fs1 -> do
1952 FL.Partial fs1 -> do
1969 rh1 <- liftIO (RB.unsafeInsert rb rh x)
1953 rh1 <- liftIO (RB.unsafeInsert rb rh x)
1970− if (cksum1 == patHash)
1954+ if cksum1 == patHash
1971 then skip $ SplitOnSeqKRCheck fs1 s rb rh1
1955 then skip $ SplitOnSeqKRCheck fs1 s rb rh1
1972 else go SPEC fs1 s rh1 cksum1
1956 else go SPEC fs1 s rh1 cksum1
1973− FL.Done r ->
1957+ FL.Done b ->
1974 let next = SplitOnSeqKRInit 0 s rb (RB.startOf rb)
1958 let next = SplitOnSeqKRInit 0 s rb (RB.startOf rb)
1975− in skip $ SplitOnSeqYield r next
1959+ in skip $ SplitOnSeqYield b next
1976 Skip s -> go SPEC fs s rh cksum
1960 Skip s -> go SPEC fs s rh cksum
1977 Stop -> skip $ SplitOnSeqKRDone patLen fs rb rh
1961 Stop -> skip $ SplitOnSeqKRDone patLen fs rb rh
1978
1962
@@ -2015,13 +1999,13 @@ splitOnSeq patArr (Fold fstep initial done) (Stream step state) =
2015 stepOuter _ (SplitOnSeqKRDone n fs rb rh) = do
1999 stepOuter _ (SplitOnSeqKRDone n fs rb rh) = do
2016 old <- liftIO $ peek rh
2000 old <- liftIO $ peek rh
2017 let rh1 = RB.advance rb rh
2001 let rh1 = RB.advance rb rh
2018− sfs <- fstep fs old
2002+ r <- fstep fs old
2019− case sfs of
2003+ case r of
2020 FL.Partial fs1 -> skip $ SplitOnSeqKRDone (n - 1) fs1 rb rh1
2004 FL.Partial fs1 -> skip $ SplitOnSeqKRDone (n - 1) fs1 rb rh1
2021− FL.Done r -> do
2005+ FL.Done b -> do
2022 fs1 <- initial
2006 fs1 <- initial
2023 let next = SplitOnSeqKRDone (n - 1) fs1 rb rh1
2007 let next = SplitOnSeqKRDone (n - 1) fs1 rb rh1
2024− skip $ SplitOnSeqYield r next
2008+ skip $ SplitOnSeqYield b next
2025
2009
2026{-# ANN type SplitOnSuffixSeqState Fuse #-}
2010{-# ANN type SplitOnSuffixSeqState Fuse #-}
2027data SplitOnSuffixSeqState rb rh ck w fs s b x =
2011data SplitOnSuffixSeqState rb rh ck w fs s b x =
@@ -2078,22 +2062,22 @@ splitOnSuffixSeq withSep patArr (Fold fstep initial done) (Stream step state) =
2078 processYieldSingle pat x s fs =
2062 processYieldSingle pat x s fs =
2079 if pat == x
2063 if pat == x
2080 then do
2064 then do
2081− sfs <- if withSep then fstep fs x else return $ FL.Partial fs
2065+ r <- if withSep then fstep fs x else return $ FL.Partial fs
2082− case sfs of
2066+ case r of
2083 FL.Partial fs1 -> do
2067 FL.Partial fs1 -> do
2084− r <- done fs1
2068+ b <- done fs1
2085 let next = SplitOnSuffixSeqSingleInit s pat
2069 let next = SplitOnSuffixSeqSingleInit s pat
2086− skip $ SplitOnSuffixSeqYield r next
2070+ skip $ SplitOnSuffixSeqYield b next
2087− FL.Done r ->
2071+ FL.Done b ->
2088 let next = SplitOnSuffixSeqSingleInit s pat
2072 let next = SplitOnSuffixSeqSingleInit s pat
2089− in skip $ SplitOnSuffixSeqYield r next
2073+ in skip $ SplitOnSuffixSeqYield b next
2090 else do
2074 else do
2091− sfs <- fstep fs x
2075+ r <- fstep fs x
2092− case sfs of
2076+ case r of
2093 FL.Partial fs1 -> skip $ SplitOnSuffixSeqSingle fs1 s pat
2077 FL.Partial fs1 -> skip $ SplitOnSuffixSeqSingle fs1 s pat
2094− FL.Done r ->
2078+ FL.Done b ->
2095 let next = SplitOnSuffixSeqSingleInit s pat
2079 let next = SplitOnSuffixSeqSingleInit s pat
2096− in skip $ SplitOnSuffixSeqYield r next
2080+ in skip $ SplitOnSuffixSeqYield b next
2097
2081
2098 -- For Rabin-Karp search
2082 -- For Rabin-Karp search
2099 k = 2891336453 :: Word32
2083 k = 2891336453 :: Word32
@@ -2135,13 +2119,13 @@ splitOnSuffixSeq withSep patArr (Fold fstep initial done) (Stream step state) =
2135 case res of
2119 case res of
2136 Yield x s -> do
2120 Yield x s -> do
2137 acc <- initial
2121 acc <- initial
2138− sfs <- fstep acc x
2122+ r <- fstep acc x
2139− case sfs of
2123+ case r of
2140− FL.Partial acc1 -> do
2124+ FL.Partial fs -> do
2141− r <- done acc1
2125+ b <- done fs
2142− skip $ SplitOnSuffixSeqYield r (SplitOnSuffixSeqEmpty s)
2126+ skip $ SplitOnSuffixSeqYield b (SplitOnSuffixSeqEmpty s)
2143− FL.Done r ->
2127+ FL.Done b ->
2144− skip $ SplitOnSuffixSeqYield r (SplitOnSuffixSeqEmpty s)
2128+ skip $ SplitOnSuffixSeqYield b (SplitOnSuffixSeqEmpty s)
2145 Skip s -> skip (SplitOnSuffixSeqEmpty s)
2129 Skip s -> skip (SplitOnSuffixSeqEmpty s)
2146 Stop -> return Stop
2130 Stop -> return Stop
2147
2131
@@ -2180,13 +2164,13 @@ splitOnSuffixSeq withSep patArr (Fold fstep initial done) (Stream step state) =
2180 skip $ SplitOnSuffixSeqYield r SplitOnSuffixSeqDone
2164 skip $ SplitOnSuffixSeqYield r SplitOnSuffixSeqDone
2181 stepOuter _ (SplitOnSuffixSeqWordDone n fs wrd) = do
2165 stepOuter _ (SplitOnSuffixSeqWordDone n fs wrd) = do
2182 let old = elemMask .&. (wrd `shiftR` (elemBits * (n - 1)))
2166 let old = elemMask .&. (wrd `shiftR` (elemBits * (n - 1)))
2183− sfs <- fstep fs (toEnum $ fromIntegral old)
2167+ r <- fstep fs (toEnum $ fromIntegral old)
2184− case sfs of
2168+ case r of
2185 FL.Partial fs1 -> skip $ SplitOnSuffixSeqWordDone (n - 1) fs1 wrd
2169 FL.Partial fs1 -> skip $ SplitOnSuffixSeqWordDone (n - 1) fs1 wrd
2186− FL.Done r -> do
2170+ FL.Done b -> do
2187 fs1 <- initial
2171 fs1 <- initial
2188 let next = SplitOnSuffixSeqWordDone (n - 1) fs1 wrd
2172 let next = SplitOnSuffixSeqWordDone (n - 1) fs1 wrd
2189− skip $ SplitOnSuffixSeqYield r next
2173+ skip $ SplitOnSuffixSeqYield b next
2190
2174
2191 stepOuter gst (SplitOnSuffixSeqWordInit st0) = do
2175 stepOuter gst (SplitOnSuffixSeqWordInit st0) = do
2192 res <- step (adaptState gst) st0
2176 res <- step (adaptState gst) st0
@@ -2194,12 +2178,12 @@ splitOnSuffixSeq withSep patArr (Fold fstep initial done) (Stream step state) =
2194 Yield x s -> do
2178 Yield x s -> do
2195 fs <- initial
2179 fs <- initial
2196 let wrd = addToWord 0 x
2180 let wrd = addToWord 0 x
2197− sfs <- if withSep then fstep fs x else return $ FL.Partial fs
2181+ r <- if withSep then fstep fs x else return $ FL.Partial fs
2198− case sfs of
2182+ case r of
2199 FL.Partial fs1 -> go SPEC 1 wrd s fs1
2183 FL.Partial fs1 -> go SPEC 1 wrd s fs1
2200− FL.Done r -> do
2184+ FL.Done b -> do
2201 let next = SplitOnSuffixSeqWordInit s
2185 let next = SplitOnSuffixSeqWordInit s
2202− in skip $ SplitOnSuffixSeqYield r next
2186+ in skip $ SplitOnSuffixSeqYield b next
2203 Skip s -> skip (SplitOnSuffixSeqWordInit s)
2187 Skip s -> skip (SplitOnSuffixSeqWordInit s)
2204 Stop -> return Stop
2188 Stop -> return Stop
2205
2189
@@ -2211,20 +2195,20 @@ splitOnSuffixSeq withSep patArr (Fold fstep initial done) (Stream step state) =
2211 case res of
2195 case res of
2212 Yield x s -> do
2196 Yield x s -> do
2213 let wrd1 = addToWord wrd x
2197 let wrd1 = addToWord wrd x
2214− sfs <- if withSep then fstep fs x else return $ FL.Partial fs
2198+ r <- if withSep then fstep fs x else return $ FL.Partial fs
2215− case sfs of
2199+ case r of
2216 FL.Partial fs1 ->
2200 FL.Partial fs1 ->
2217 if idx /= maxIndex
2201 if idx /= maxIndex
2218 then go SPEC (idx + 1) wrd1 s fs1
2202 then go SPEC (idx + 1) wrd1 s fs1
2219 else if wrd1 .&. wordMask /= wordPat
2203 else if wrd1 .&. wordMask /= wordPat
2220 then skip $ SplitOnSuffixSeqWordLoop wrd1 s fs1
2204 then skip $ SplitOnSuffixSeqWordLoop wrd1 s fs1
2221 else do
2205 else do
2222− r <- done fs
2206+ b <- done fs
2223 let next = SplitOnSuffixSeqWordInit s
2207 let next = SplitOnSuffixSeqWordInit s
2224− skip $ SplitOnSuffixSeqYield r next
2208+ skip $ SplitOnSuffixSeqYield b next
2225− FL.Done r ->
2209+ FL.Done b ->
2226 let next = SplitOnSuffixSeqWordInit s
2210 let next = SplitOnSuffixSeqWordInit s
2227− in skip $ SplitOnSuffixSeqYield r next
2211+ in skip $ SplitOnSuffixSeqYield b next
2228 Skip s -> go SPEC idx wrd s fs
2212 Skip s -> go SPEC idx wrd s fs
2229 Stop -> skip $ SplitOnSuffixSeqWordDone idx fs wrd
2213 Stop -> skip $ SplitOnSuffixSeqWordDone idx fs wrd
2230
2214
@@ -2241,21 +2225,21 @@ splitOnSuffixSeq withSep patArr (Fold fstep initial done) (Stream step state) =
2241 let wrd1 = addToWord wrd x
2225 let wrd1 = addToWord wrd x
2242 old = (wordMask .&. wrd)
2226 old = (wordMask .&. wrd)
2243 `shiftR` (elemBits * (patLen - 1))
2227 `shiftR` (elemBits * (patLen - 1))
2244− sfs <-
2228+ r <-
2245 if withSep
2229 if withSep
2246 then fstep fs x
2230 then fstep fs x
2247 else fstep fs (toEnum $ fromIntegral old)
2231 else fstep fs (toEnum $ fromIntegral old)
2248− case sfs of
2232+ case r of
2249 FL.Partial fs1 ->
2233 FL.Partial fs1 ->
2250 if wrd1 .&. wordMask == wordPat
2234 if wrd1 .&. wordMask == wordPat
2251 then do
2235 then do
2252− r <- done fs1
2236+ b <- done fs1
2253 let next = SplitOnSuffixSeqWordInit s
2237 let next = SplitOnSuffixSeqWordInit s
2254− skip $ SplitOnSuffixSeqYield r next
2238+ skip $ SplitOnSuffixSeqYield b next
2255 else go SPEC wrd1 s fs1
2239 else go SPEC wrd1 s fs1
2256− FL.Done r ->
2240+ FL.Done b ->
2257 let next = SplitOnSuffixSeqWordInit s
2241 let next = SplitOnSuffixSeqWordInit s
2258− in skip $ SplitOnSuffixSeqYield r next
2242+ in skip $ SplitOnSuffixSeqYield b next
2259 Skip s -> go SPEC wrd s fs
2243 Skip s -> go SPEC wrd s fs
2260 Stop ->
2244 Stop ->
2261 if wrd .&. wordMask == wordPat
2245 if wrd .&. wordMask == wordPat
@@ -2276,12 +2260,13 @@ splitOnSuffixSeq withSep patArr (Fold fstep initial done) (Stream step state) =
2276 Yield x s -> do
2260 Yield x s -> do
2277 rh1 <- liftIO $ RB.unsafeInsert rb rh0 x
2261 rh1 <- liftIO $ RB.unsafeInsert rb rh0 x
2278 fs <- initial
2262 fs <- initial
2279− sfs <- if withSep then fstep fs x else return $ FL.Partial fs
2263+ r <- if withSep then fstep fs x else return $ FL.Partial fs
2280− case sfs of
2264+ case r of
2265+ FL.Partial fs1 ->
2281− FL.Partial fs1 -> skip $ SplitOnSuffixSeqKRInit1 fs1 s rb rh1
2266+ skip $ SplitOnSuffixSeqKRInit1 fs1 s rb rh1
2282− FL.Done r ->
2267+ FL.Done b ->
2283 let next = SplitOnSuffixSeqKRInit 0 s rb (RB.startOf rb)
2268 let next = SplitOnSuffixSeqKRInit 0 s rb (RB.startOf rb)
2284− in skip $ SplitOnSuffixSeqYield r next
2269+ in skip $ SplitOnSuffixSeqYield b next
2285 Skip s -> skip $ SplitOnSuffixSeqKRInit idx0 s rb rh0
2270 Skip s -> skip $ SplitOnSuffixSeqKRInit idx0 s rb rh0
2286 Stop -> return Stop
2271 Stop -> return Stop
2287
2272
@@ -2295,8 +2280,8 @@ splitOnSuffixSeq withSep patArr (Fold fstep initial done) (Stream step state) =
2295 case res of
2280 case res of
2296 Yield x s -> do
2281 Yield x s -> do
2297 rh1 <- liftIO (RB.unsafeInsert rb rh x)
2282 rh1 <- liftIO (RB.unsafeInsert rb rh x)
2298− sfs <- if withSep then fstep fs x else return $ FL.Partial fs
2283+ r <- if withSep then fstep fs x else return $ FL.Partial fs
2299− case sfs of
2284+ case r of
2300 FL.Partial fs1 ->
2285 FL.Partial fs1 ->
2301 if idx /= maxIndex
2286 if idx /= maxIndex
2302 then go SPEC (idx + 1) rh1 s fs1
2287 then go SPEC (idx + 1) rh1 s fs1
@@ -2305,10 +2290,12 @@ splitOnSuffixSeq withSep patArr (Fold fstep initial done) (Stream step state) =
2305 !ringHash = fold addCksum 0 rb
2290 !ringHash = fold addCksum 0 rb
2306 in if ringHash == patHash
2291 in if ringHash == patHash
2307 then SplitOnSuffixSeqKRCheck fs1 s rb rh1
2292 then SplitOnSuffixSeqKRCheck fs1 s rb rh1
2308− else SplitOnSuffixSeqKRLoop fs1 s rb rh1 ringHash
2293+ else SplitOnSuffixSeqKRLoop
2294+ fs1 s rb rh1 ringHash
2309− FL.Done r ->
2295+ FL.Done b ->
2310− let next = SplitOnSuffixSeqKRInit 0 st rb (RB.startOf rb)
2296+ let next = SplitOnSuffixSeqKRInit
2297+ 0 st rb (RB.startOf rb)
2311− in skip $ SplitOnSuffixSeqYield r next
2298+ in skip $ SplitOnSuffixSeqYield b next
2312 Skip s -> go SPEC idx rh s fs
2299 Skip s -> go SPEC idx rh s fs
2313 Stop -> do
2300 Stop -> do
2314 -- do not issue a blank segment when we end at pattern
2301 -- do not issue a blank segment when we end at pattern
@@ -2332,15 +2319,16 @@ splitOnSuffixSeq withSep patArr (Fold fstep initial done) (Stream step state) =
2332 old <- liftIO $ peek rh
2319 old <- liftIO $ peek rh
2333 rh1 <- liftIO (RB.unsafeInsert rb rh x)
2320 rh1 <- liftIO (RB.unsafeInsert rb rh x)
2334 let cksum1 = deltaCksum cksum old x
2321 let cksum1 = deltaCksum cksum old x
2335− sfs <- if withSep then fstep fs x else fstep fs old
2322+ r <- if withSep then fstep fs x else fstep fs old
2336− case sfs of
2323+ case r of
2337 FL.Partial fs1 ->
2324 FL.Partial fs1 ->
2338 if (cksum1 /= patHash)
2325 if (cksum1 /= patHash)
2339 then go SPEC fs1 s rh1 cksum1
2326 then go SPEC fs1 s rh1 cksum1
2340 else skip $ SplitOnSuffixSeqKRCheck fs1 s rb rh1
2327 else skip $ SplitOnSuffixSeqKRCheck fs1 s rb rh1
2341− FL.Done r ->
2328+ FL.Done b ->
2342− let next = SplitOnSuffixSeqKRInit 0 st rb (RB.startOf rb)
2329+ let next = SplitOnSuffixSeqKRInit
2330+ 0 st rb (RB.startOf rb)
2343− in skip $ SplitOnSuffixSeqYield r next
2331+ in skip $ SplitOnSuffixSeqYield b next
2344 Skip s -> go SPEC fs s rh cksum
2332 Skip s -> go SPEC fs s rh cksum
2345 Stop ->
2333 Stop ->
2346 if RB.unsafeEqArray rb rh patArr
2334 if RB.unsafeEqArray rb rh patArr
@@ -2365,13 +2353,13 @@ splitOnSuffixSeq withSep patArr (Fold fstep initial done) (Stream step state) =
2365 stepOuter _ (SplitOnSuffixSeqKRDone n fs rb rh) = do
2353 stepOuter _ (SplitOnSuffixSeqKRDone n fs rb rh) = do
2366 old <- liftIO $ peek rh
2354 old <- liftIO $ peek rh
2367 let rh1 = RB.advance rb rh
2355 let rh1 = RB.advance rb rh
2368− sfs <- fstep fs old
2356+ r <- fstep fs old
2369− case sfs of
2357+ case r of
2370 FL.Partial fs1 -> skip $ SplitOnSuffixSeqKRDone (n - 1) fs1 rb rh1
2358 FL.Partial fs1 -> skip $ SplitOnSuffixSeqKRDone (n - 1) fs1 rb rh1
2371− FL.Done r -> do
2359+ FL.Done b -> do
2372 fs1 <- initial
2360 fs1 <- initial
2373 let next = SplitOnSuffixSeqKRDone (n - 1) fs1 rb rh1
2361 let next = SplitOnSuffixSeqKRDone (n - 1) fs1 rb rh1
2374− skip $ SplitOnSuffixSeqYield r next
2362+ skip $ SplitOnSuffixSeqYield b next
2375
2363
2376{-# ANN type SplitState Fuse #-}
2364{-# ANN type SplitState Fuse #-}
2377data SplitState s arr
2365data SplitState s arr
@@ -3765,12 +3753,10 @@ scanlMx' fstep begin done s =
3765 (begin >>= \x -> x `seq` done x) `consM` postscanlMx' fstep begin done s
3753 (begin >>= \x -> x `seq` done x) `consM` postscanlMx' fstep begin done s
3766
3754
3767
3755
3768−data PostScanState fsM s a = PostScan s !fsM
3756+data PostScanState s f = PostScan s !f
3769
3757
3770−-- XXX PostScanWith is can be eliminated if we abstract Yield
3771{-# INLINE_NORMAL postscanOnce #-}
3758{-# INLINE_NORMAL postscanOnce #-}
3772−postscanOnce :: Monad m
3773− => FL.Fold m a b -> Stream m a -> Stream m b
3759+postscanOnce :: Monad m => FL.Fold m a b -> Stream m a -> Stream m b
3774postscanOnce (FL.Fold fstep begin done) (Stream step state) =
3760postscanOnce (FL.Fold fstep begin done) (Stream step state) =
3775 Stream step' (PostScan state begin)
3761 Stream step' (PostScan state begin)
3776
3762
@@ -3780,15 +3766,14 @@ postscanOnce (FL.Fold fstep begin done) (Stream step state) =
3780 step' gst (PostScan st acc) = do
3766 step' gst (PostScan st acc) = do
3781 r <- step (adaptState gst) st
3767 r <- step (adaptState gst) st
3782 case r of
3768 case r of
3783− -- XXX Move Yield to a common function
3784 Yield x s -> do
3769 Yield x s -> do
3785 old <- acc
3770 old <- acc
3786− y <- fstep old x
3771+ res <- fstep old x
3787− case y of
3772+ case res of
3788− FL.Partial sres -> do
3773+ FL.Partial fs -> do
3789− !v <- done sres
3774+ !v <- done fs
3790− return $ Yield v $ PostScan s (return sres)
3775+ return $ Yield v $ PostScan s (return fs)
3791− FL.Done _ -> return $ Stop
3776+ FL.Done _ -> return Stop
3792 Skip s -> return $ Skip $ PostScan s acc
3777 Skip s -> return $ Skip $ PostScan s acc
3793 Stop -> return Stop
3778 Stop -> return Stop
3794
3779
@@ -4027,17 +4012,17 @@ tap (Fold fstep initial extract) (Stream step state) = Stream step' TapInit
4027 step' gst (Tapping acc st) = do
4012 step' gst (Tapping acc st) = do
4028 r <- step gst st
4013 r <- step gst st
4029 case r of
4014 case r of
4030− -- XXX Abstract Yield?
4031 Yield x s -> do
4015 Yield x s -> do
4032− acc1 <- fstep acc x
4016+ res <- fstep acc x
4033 return
4017 return
4018+ $ Yield x
4034− $ case acc1 of
4019+ $ case res of
4035− FL.Partial sres -> Yield x (Tapping sres s)
4020+ FL.Partial fs -> Tapping fs s
4036− FL.Done _ -> Yield x (TapDone s)
4021+ FL.Done _ -> TapDone s
4037 Skip s -> return $ Skip (Tapping acc s)
4022 Skip s -> return $ Skip (Tapping acc s)
4038 Stop -> do
4023 Stop -> do
4039 void $ extract acc
4024 void $ extract acc
4040− return $ Stop
4025+ return Stop
4041 step' gst (TapDone st) = do
4026 step' gst (TapDone st) = do
4042 r <- step gst st
4027 r <- step gst st
4043 return
4028 return
@@ -4067,21 +4052,22 @@ tapOffsetEvery offset n (Fold fstep initial extract) (Stream step state) =
4067 step' gst (TapOffTapping acc st count) = do
4052 step' gst (TapOffTapping acc st count) = do
4068 r <- step gst st
4053 r <- step gst st
4069 case r of
4054 case r of
4070− Yield x s ->
4055+ Yield x s -> do
4056+ next <-
4071− if count <= 0
4057+ if count <= 0
4072− -- XXX Abstract the then branch?
4058+ then do
4073− then do
4074− acc1 <- fstep acc x
4059+ res <- fstep acc x
4075− return
4060+ return
4076− $ case acc1 of
4061+ $ case res of
4077− FL.Partial sres ->
4062+ FL.Partial sres ->
4078− Yield x $ TapOffTapping sres s (n - 1)
4063+ TapOffTapping sres s (n - 1)
4079− FL.Done _ -> Yield x (TapOffDone s)
4064+ FL.Done _ -> TapOffDone s
4080− else return $ Yield x $ TapOffTapping acc s (count - 1)
4065+ else return $ TapOffTapping acc s (count - 1)
4066+ return $ Yield x next
4081 Skip s -> return $ Skip (TapOffTapping acc s count)
4067 Skip s -> return $ Skip (TapOffTapping acc s count)
4082 Stop -> do
4068 Stop -> do
4083 void $ extract acc
4069 void $ extract acc
4084− return $ Stop
4070+ return Stop
4085 step' gst (TapOffDone st) = do
4071 step' gst (TapOffDone st) = do
4086 r <- step gst st
4072 r <- step gst st
4087 return
4073 return
src/Streamly/Internal/Data/Stream/StreamD/Type.hs+20−26
@@ -48,7 +48,6 @@ module Streamly.Internal.Data.Stream.StreamD.Type
48 , GroupState (..) -- for inspection testing
48 , GroupState (..) -- for inspection testing
49 , foldMany
49 , foldMany
50 , foldMany1
50 , foldMany1
51− , groupsOf
52 , groupsOf2
51 , groupsOf2
53 )
52 )
54where
53where
@@ -66,8 +65,8 @@ import Fusion.Plugin.Types (Fuse(..))
66import Streamly.Internal.Data.SVar (State(..), adaptState, defState)
65import Streamly.Internal.Data.SVar (State(..), adaptState, defState)
67import Streamly.Internal.Data.Fold.Types (Fold(..), Fold2(..))
66import Streamly.Internal.Data.Fold.Types (Fold(..), Fold2(..))
68
67
69−import qualified Streamly.Internal.Data.Stream.StreamK as K
70import qualified Streamly.Internal.Data.Fold.Types as FL
68import qualified Streamly.Internal.Data.Fold.Types as FL
69+import qualified Streamly.Internal.Data.Stream.StreamK as K
71
70
72------------------------------------------------------------------------------
71------------------------------------------------------------------------------
73-- The direct style stream type
72-- The direct style stream type
@@ -589,12 +588,10 @@ take n (Stream step state) = n `seq` Stream step' (state, 0)
589{-# ANN type GroupState Fuse #-}
588{-# ANN type GroupState Fuse #-}
590data GroupState s fs b a
589data GroupState s fs b a
591 = GroupStart s
590 = GroupStart s
592− | GroupConsume s fs a
593 | GroupBuffer s fs
591 | GroupBuffer s fs
594 | GroupYield b (GroupState s fs b a)
592 | GroupYield b (GroupState s fs b a)
595 | GroupFinish
593 | GroupFinish
596
594
597−-- XXX Remove GroupConsume
598{-# INLINE_NORMAL foldMany #-}
595{-# INLINE_NORMAL foldMany #-}
599foldMany :: Monad m => Fold m a b -> Stream m a -> Stream m b
596foldMany :: Monad m => Fold m a b -> Stream m a -> Stream m b
600foldMany (Fold fstep initial extract) (Stream step state) =
597foldMany (Fold fstep initial extract) (Stream step state) =
@@ -607,15 +604,16 @@ foldMany (Fold fstep initial extract) (Stream step state) =
607 -- fs = fold state
604 -- fs = fold state
608 fs <- initial
605 fs <- initial
609 return $ Skip (GroupBuffer st fs)
606 return $ Skip (GroupBuffer st fs)
610− step' _ (GroupConsume st fs x) = do
611− fs' <- fstep fs x
612− case fs' of
613− FL.Done b -> return $ Skip (GroupYield b (GroupStart st))
614− FL.Partial ps -> return $ Skip (GroupBuffer st ps)
615 step' gst (GroupBuffer st fs) = do
607 step' gst (GroupBuffer st fs) = do
616 r <- step (adaptState gst) st
608 r <- step (adaptState gst) st
617 case r of
609 case r of
618− Yield x s -> return $ Skip $ GroupConsume s fs x
610+ Yield x s -> do
611+ res <- fstep fs x
612+ return
613+ $ Skip
614+ $ case res of
615+ FL.Done b -> GroupYield b (GroupStart s)
616+ FL.Partial ps -> GroupBuffer s ps
619 Skip s -> return $ Skip (GroupBuffer s fs)
617 Skip s -> return $ Skip (GroupBuffer s fs)
620 Stop -> do
618 Stop -> do
621 b <- extract fs
619 b <- extract fs
@@ -630,25 +628,26 @@ foldMany1 (Fold fstep initial extract) (Stream step state) =
630
628
631 where
629 where
632
630
631+ {-# INLINE consume #-}
632+ consume x s fs = do
633+ res <- fstep fs x
634+ return
635+ $ Skip
636+ $ case res of
637+ FL.Done b -> GroupYield b (GroupStart s)
638+ FL.Partial ps -> GroupBuffer s ps
639+
633 {-# INLINE_LATE step' #-}
640 {-# INLINE_LATE step' #-}
634 step' gst (GroupStart st) = do
641 step' gst (GroupStart st) = do
635− -- fs = fold state
636 r <- step (adaptState gst) st
642 r <- step (adaptState gst) st
637 case r of
643 case r of
638− Yield x s -> do
644+ Yield x s -> initial >>= consume x s
639− fi <- initial
640− return $ Skip $ GroupConsume s fi x
641 Skip s -> return $ Skip (GroupStart s)
645 Skip s -> return $ Skip (GroupStart s)
642− Stop -> return $ Stop
646+ Stop -> return Stop
643− step' _ (GroupConsume st fs x) = do
644− fs' <- fstep fs x
645− case fs' of
646− FL.Done b -> return $ Skip (GroupYield b (GroupStart st))
647− FL.Partial ps -> return $ Skip (GroupBuffer st ps)
648 step' gst (GroupBuffer st fs) = do
647 step' gst (GroupBuffer st fs) = do
649 r <- step (adaptState gst) st
648 r <- step (adaptState gst) st
650 case r of
649 case r of
651− Yield x s -> return $ Skip $ GroupConsume s fs x
650+ Yield x s -> consume x s fs
652 Skip s -> return $ Skip (GroupBuffer s fs)
651 Skip s -> return $ Skip (GroupBuffer s fs)
653 Stop -> do
652 Stop -> do
654 b <- extract fs
653 b <- extract fs
@@ -656,11 +655,6 @@ foldMany1 (Fold fstep initial extract) (Stream step state) =
656 step' _ (GroupYield b next) = return $ Yield b next
655 step' _ (GroupYield b next) = return $ Yield b next
657 step' _ GroupFinish = return Stop
656 step' _ GroupFinish = return Stop
658
657
659−-- XXX Investigate performance
660−{-# INLINE groupsOf #-}
661−groupsOf :: Monad m => Int -> Fold m a b -> Stream m a -> Stream m b
662−groupsOf n fld = foldMany (FL.ltake n fld)
663−
664data GroupState2 s fs
658data GroupState2 s fs
665 = GroupStart2 s
659 = GroupStart2 s
666 | GroupBuffer2 s fs Int
660 | GroupBuffer2 s fs Int