@@ -66,6 +66,7 @@ module Streamly.Internal.Data.Fold
66 -- ** Collectors
66 -- ** Collectors
68 , toListRevF -- experimental
68 , toListRevF -- experimental
69 , toParallelSVar
70 , toParallelSVar
71 -- * Terminating Folds
72 -- * Terminating Folds
@@ -224,6 +225,7 @@ where
225import Control.Monad (void, join)
226import Control.Monad (void, join)
226import Control.Monad.IO.Class (MonadIO(..))
227import Control.Monad.IO.Class (MonadIO(..))
228+import Data.Bifunctor (first)
227import Data.Functor.Identity (Identity(..))
229import Data.Functor.Identity (Identity(..))
228import Data.Int (Int64)
230import Data.Int (Int64)
229import Data.Map.Strict (Map)
231import Data.Map.Strict (Map)
@@ -235,6 +237,8 @@ import Streamly.Internal.Data.Either.Strict (Either'(..))
235import Streamly.Internal.Data.Maybe.Strict (Maybe'(..), toMaybe)
237import Streamly.Internal.Data.Maybe.Strict (Maybe'(..), toMaybe)
236import Streamly.Internal.Data.Pipe.Types (Pipe (..), PipeState(..))
238import Streamly.Internal.Data.Pipe.Types (Pipe (..), PipeState(..))
237import Streamly.Internal.Data.Tuple.Strict (Tuple'(..), Tuple3'(..))
239import Streamly.Internal.Data.Tuple.Strict (Tuple'(..), Tuple3'(..))
240+import Streamly.Internal.Data.Either.Strict
241+ (fromLeft', fromRight', isLeft', isRight')
239import qualified Data.Map.Strict as Map
243import qualified Data.Map.Strict as Map
240import qualified Streamly.Internal.Data.Fold.Types as FL
244import qualified Streamly.Internal.Data.Fold.Types as FL
@@ -265,7 +269,7 @@ mkAccum :: Monad m => (s -> a -> s) -> s -> (s -> b) -> Fold m a b
265mkAccum step initial extract =
269mkAccum step initial extract =
267 (\s a -> return $ Partial $ step s a)
271 (\s a -> return $ Partial $ step s a)
268− (return initial)
272+ (return (Partial initial))
269 (return . extract)
273 (return . extract)
271-- | Similar to 'mkAccum' but the final state extracted is identical to the
275-- | Similar to 'mkAccum' but the final state extracted is identical to the
@@ -284,7 +288,8 @@ mkAccum_ step initial = mkAccum step initial id
285{-# INLINE mkAccumM #-}
289{-# INLINE mkAccumM #-}
286mkAccumM :: Functor m => (s -> a -> m s) -> m s -> (s -> m b) -> Fold m a b
290mkAccumM :: Functor m => (s -> a -> m s) -> m s -> (s -> m b) -> Fold m a b
291+mkAccumM step initial =
287−mkAccumM step = Fold (\s a -> Partial <$> step s a)
292+ Fold (\s a -> Partial <$> step s a) (Partial <$> initial)
289-- | Similar to 'mkAccumM' but the final state extracted is identical to the
294-- | Similar to 'mkAccumM' but the final state extracted is identical to the
290-- intermediate state.
295-- intermediate state.
@@ -301,7 +306,7 @@ mkAccumM_ step initial = mkAccumM step initial return
301-- /Internal/
306-- /Internal/
303{-# INLINE mkFold #-}
308{-# INLINE mkFold #-}
304−mkFold :: Monad m => (s -> a -> Step s b) -> s -> (s -> b) -> Fold m a b
309+mkFold :: Monad m => (s -> a -> Step s b) -> Step s b -> (s -> b) -> Fold m a b
305mkFold step initial extract =
310mkFold step initial extract =
306 Fold (\s a -> return $ step s a) (return initial) (return . extract)
311 Fold (\s a -> return $ step s a) (return initial) (return . extract)
@@ -311,7 +316,7 @@ mkFold step initial extract =
311-- /Internal/
316-- /Internal/
313{-# INLINE mkFold_ #-}
318{-# INLINE mkFold_ #-}
314−mkFold_ :: Monad m => (b -> a -> Step b b) -> b -> Fold m a b
319+mkFold_ :: Monad m => (b -> a -> Step b b) -> Step b b -> Fold m a b
315mkFold_ step initial = mkFold step initial id
320mkFold_ step initial = mkFold step initial id
317-- | Make a terminating fold with an effectful step function and initial state,
322-- | Make a terminating fold with an effectful step function and initial state,
@@ -324,7 +329,7 @@ mkFold_ step initial = mkFold step initial id
324-- /Internal/
329-- /Internal/
326{-# INLINE mkFoldM #-}
331{-# INLINE mkFoldM #-}
327−mkFoldM :: (s -> a -> m (Step s b)) -> m s -> (s -> m b) -> Fold m a b
332+mkFoldM :: (s -> a -> m (Step s b)) -> m (Step s b) -> (s -> m b) -> Fold m a b
328mkFoldM = Fold
333mkFoldM = Fold
330-- | Similar to 'mkFoldM' but the final state extracted is identical to the
335-- | Similar to 'mkFoldM' but the final state extracted is identical to the
@@ -333,8 +338,8 @@ mkFoldM = Fold
333-- /Internal/
338-- /Internal/
335{-# INLINE mkFoldM_ #-}
340{-# INLINE mkFoldM_ #-}
336−mkFoldM_ :: Monad m => (b -> a -> m (Step b b)) -> m b -> Fold m a b
341+mkFoldM_ :: Monad m => (b -> a -> m (Step b b)) -> m (Step b b) -> Fold m a b
337−mkFoldM_ step initial = Fold step initial return
342+mkFoldM_ step initial = mkFoldM step initial return
339------------------------------------------------------------------------------
344------------------------------------------------------------------------------
@@ -364,16 +369,19 @@ generally = hoist (return . runIdentity)
364-- @since 0.7.0
369-- @since 0.7.0
365{-# INLINE sequence #-}
370{-# INLINE sequence #-}
366sequence :: Monad m => Fold m a (m b) -> Fold m a b
371sequence :: Monad m => Fold m a (m b) -> Fold m a b
367−sequence (Fold step initial extract) = Fold step' initial extract'
372+sequence (Fold step initial extract) = Fold step' initial1 extract'
371− step' s a = do
376+ eval res =
373 case res of
377 case res of
374 Partial x -> return $ Partial x
378 Partial x -> return $ Partial x
375 Done b -> Done <$> b
379 Done b -> Done <$> b
381+ initial1 = initial >>= eval
383+ step' s a = step s a >>= eval
377 extract' = join . extract
385 extract' = join . extract
379-- | Map a monadic function on the output of a fold.
387-- | Map a monadic function on the output of a fold.
@@ -413,7 +421,7 @@ transform (Pipe pstep1 pstep2 pinitial) (Fold fstep finitial fextract) =
416− initial = Tuple' pinitial <$> finitial
424+ initial = first (Tuple' pinitial) <$> finitial
418 step (Tuple' ps fs) x = do
426 step (Tuple' ps fs) x = do
419 r <- pstep1 ps x
427 r <- pstep1 ps x
@@ -452,12 +460,12 @@ transform (Pipe pstep1 pstep2 pinitial) (Fold fstep finitial fextract) =
452-- from the 'Foldable', the result is 'None' for empty containers.
460-- from the 'Foldable', the result is 'None' for empty containers.
453{-# INLINABLE _Fold1 #-}
461{-# INLINABLE _Fold1 #-}
454_Fold1 :: Monad m => (a -> a -> a) -> Fold m a (Maybe a)
462_Fold1 :: Monad m => (a -> a -> a) -> Fold m a (Maybe a)
455−_Fold1 step = Fold step_ (return Nothing') (return . toMaybe)
463+_Fold1 step = mkAccum step_ Nothing' toMaybe
459− step_ Nothing' a = return $ Partial $ Just' a
467+ step_ Nothing' a = Just' a
460− step_ (Just' x) a = return $ Partial $ Just' $ step x a
468+ step_ (Just' x) a = Just' $ step x a
462------------------------------------------------------------------------------
470------------------------------------------------------------------------------
463-- Left folds
471-- Left folds
@@ -475,15 +483,7 @@ _Fold1 step = Fold step_ (return Nothing') (return . toMaybe)
475-- @since 0.7.0
483-- @since 0.7.0
476{-# INLINABLE drain #-}
484{-# INLINABLE drain #-}
477drain :: Monad m => Fold m a ()
485drain :: Monad m => Fold m a ()
478−drain = Fold step begin done
486+drain = mkAccum_ (\_ _ -> ()) ()
484− step _ _ = return $ FL.Partial ()
489-- > drainBy f = lmapM f drain
489-- > drainBy f = lmapM f drain
@@ -495,7 +495,7 @@ drain = Fold step begin done
495-- @since 0.7.0
495-- @since 0.7.0
496{-# INLINABLE drainBy #-}
496{-# INLINABLE drainBy #-}
497drainBy :: Monad m => (a -> m b) -> Fold m a ()
497drainBy :: Monad m => (a -> m b) -> Fold m a ()
498−drainBy f = Fold (const (fmap FL.Partial . void . f)) (return ()) return
498+drainBy f = lmapM f drain
500{-# INLINABLE drainBy2 #-}
500{-# INLINABLE drainBy2 #-}
501drainBy2 :: Monad m => (a -> m b) -> Fold2 m c a ()
501drainBy2 :: Monad m => (a -> m b) -> Fold2 m c a ()
@@ -521,7 +521,7 @@ last = _Fold1 (\_ x -> x)
521-- @since 0.7.0
521-- @since 0.7.0
522{-# INLINE genericLength #-}
522{-# INLINE genericLength #-}
523genericLength :: (Monad m, Num b) => Fold m a b
523genericLength :: (Monad m, Num b) => Fold m a b
524−genericLength = Fold (\n _ -> return $ Partial $ n + 1) (return 0) return
524+genericLength = mkAccum_ (\n _ -> n + 1) 0
526-- | Determine the length of the input stream.
526-- | Determine the length of the input stream.
@@ -541,7 +541,7 @@ length = genericLength
541-- @since 0.7.0
541-- @since 0.7.0
542{-# INLINE sum #-}
542{-# INLINE sum #-}
543sum :: (Monad m, Num a) => Fold m a a
543sum :: (Monad m, Num a) => Fold m a a
544−sum = Fold (\x a -> return $ Partial $ x + a) (return 0) return
544+sum = mkAccum_ (+) 0
546-- | Determine the product of all elements of a stream of numbers. Returns
546-- | Determine the product of all elements of a stream of numbers. Returns
547-- multiplicative identity (@1@) when the stream is empty. The fold terminates
547-- multiplicative identity (@1@) when the stream is empty. The fold terminates
@@ -553,15 +553,14 @@ sum = Fold (\x a -> return $ Partial $ x + a) (return 0) return
553-- /Since 0.8.0 (Added 'Eq' constraint)/
553-- /Since 0.8.0 (Added 'Eq' constraint)/
554{-# INLINE product #-}
554{-# INLINE product #-}
555product :: (Monad m, Num a, Eq a) => Fold m a a
555product :: (Monad m, Num a, Eq a) => Fold m a a
556−product = Fold step (return 1) return
556+product = mkFold_ step (Partial 1)
560 step x a =
560 step x a =
562− $ if a == 0
561+ if a == 0
563− then Done 0
562+ then Done 0
564− else Partial $ x * a
563+ else Partial $ x * a
566------------------------------------------------------------------------------
565------------------------------------------------------------------------------
567-- To Summary (Maybe)
566-- To Summary (Maybe)
@@ -634,16 +633,15 @@ minimum = _Fold1 min
634-- @since 0.7.0
633-- @since 0.7.0
635{-# INLINABLE mean #-}
634{-# INLINABLE mean #-}
636mean :: (Monad m, Fractional a) => Fold m a a
635mean :: (Monad m, Fractional a) => Fold m a a
637−mean = Fold step (return begin) (return . done)
636+mean = mkAccum step begin done
641 begin = Tuple' 0 0
640 begin = Tuple' 0 0
643 step (Tuple' x n) y =
642 step (Tuple' x n) y =
645− $ let n' = n + 1
643+ let n1 = n + 1
646− in Partial $ Tuple' (x + (y - x) / n') n'
644+ in Tuple' (x + (y - x) / n1) n1
648 done (Tuple' x _) = x
646 done (Tuple' x _) = x
@@ -653,13 +651,13 @@ mean = Fold step (return begin) (return . done)
653-- @since 0.7.0
651-- @since 0.7.0
654{-# INLINABLE variance #-}
652{-# INLINABLE variance #-}
655variance :: (Monad m, Fractional a) => Fold m a a
653variance :: (Monad m, Fractional a) => Fold m a a
656−variance = Fold step (return begin) (return . done)
654+variance = mkAccum step begin done
660 begin = Tuple3' 0 0 0
658 begin = Tuple3' 0 0 0
662− step (Tuple3' n mean_ m2) x = return $ Partial $ Tuple3' n' mean' m2'
660+ step (Tuple3' n mean_ m2) x = Tuple3' n' mean' m2'
@@ -692,17 +690,13 @@ stdDev = sqrt variance
692-- @since 0.7.0
690-- @since 0.7.0
693{-# INLINABLE rollingHashWithSalt #-}
691{-# INLINABLE rollingHashWithSalt #-}
694rollingHashWithSalt :: (Monad m, Enum a) => Int64 -> Fold m a Int64
692rollingHashWithSalt :: (Monad m, Enum a) => Int64 -> Fold m a Int64
695−rollingHashWithSalt salt = Fold step initial extract
693+rollingHashWithSalt = mkAccum_ step
699 k = 2891336453 :: Int64
697 k = 2891336453 :: Int64
701− initial = return salt
703− step cksum a = return $ Partial $ cksum * k + fromIntegral (fromEnum a)
699+ step cksum a = cksum * k + fromIntegral (fromEnum a)
707-- | A default salt used in the implementation of 'rollingHash'.
701-- | A default salt used in the implementation of 'rollingHash'.
708{-# INLINE defaultSalt #-}
702{-# INLINE defaultSalt #-}
@@ -738,7 +732,7 @@ rollingHashFirstN n = ltake n rollingHash
739{-# INLINE sconcat #-}
733{-# INLINE sconcat #-}
740sconcat :: (Monad m, Semigroup a) => a -> Fold m a a
734sconcat :: (Monad m, Semigroup a) => a -> Fold m a a
741−sconcat i = Fold (\x a -> return $ Partial $ x <> a) (return i) return
735+sconcat = mkAccum_ (<>)
743-- | Fold an input stream consisting of monoidal elements using 'mappend'
737-- | Fold an input stream consisting of monoidal elements using 'mappend'
744-- and 'mempty'.
738-- and 'mempty'.
@@ -783,17 +777,13 @@ foldMap f = lmap f mconcat
783-- @since 0.7.0
777-- @since 0.7.0
784{-# INLINABLE foldMapM #-}
778{-# INLINABLE foldMapM #-}
785foldMapM :: (Monad m, Monoid b) => (a -> m b) -> Fold m a b
779foldMapM :: (Monad m, Monoid b) => (a -> m b) -> Fold m a b
786−foldMapM act = Fold step begin done
780+foldMapM act = mkAccumM_ step (pure mempty)
792− begin = return mempty
794 step m a = do
784 step m a = do
795 m' <- act a
785 m' <- act a
796− return $! Partial $! mappend m m'
786+ return $! mappend m m'
798------------------------------------------------------------------------------
788------------------------------------------------------------------------------
799-- To Containers
789-- To Containers
@@ -810,9 +800,23 @@ foldMapM act = Fold step begin done
810-- id . (x1 :) . (x2 :) . (x3 :) . ... . (xn :) $ []
800-- id . (x1 :) . (x2 :) . (x3 :) . ... . (xn :) $ []
811{-# INLINABLE toList #-}
801{-# INLINABLE toList #-}
812toList :: Monad m => Fold m a [a]
802toList :: Monad m => Fold m a [a]
813−toList = Fold (\f x -> return $ Partial $ f . (x :))
803+toList = mkAccum (\f x -> f . (x :)) id ($ [])
815− (return . ($ []))
805+-- $toListRevF
806+-- This is more efficient than 'Streamly.Internal.Data.Fold.toList'. toList is
807+-- exactly the same as reversing the list after 'toListRevF'.
809+-- | Buffers the input stream to a list in the reverse order of the input.
811+-- /Warning!/ working on large lists accumulated as buffers in memory could be
812+-- very inefficient, consider using "Streamly.Array" instead.
816+-- xn : ... : x2 : x1 : []
817+{-# INLINABLE toListRevF #-}
818+toListRevF :: Monad m => Fold m a [a]
819+toListRevF = mkAccum_ (flip (:)) []
817------------------------------------------------------------------------------
821------------------------------------------------------------------------------
818-- Partial Folds
822-- Partial Folds
@@ -833,15 +837,14 @@ drainN n = ltake n drain
833-- @since 0.7.0
837-- @since 0.7.0
834{-# INLINABLE genericIndex #-}
838{-# INLINABLE genericIndex #-}
835genericIndex :: (Integral i, Monad m) => i -> Fold m a (Maybe a)
839genericIndex :: (Integral i, Monad m) => i -> Fold m a (Maybe a)
836−genericIndex i = Fold step (return 0) (const (return Nothing))
840+genericIndex i = mkFold step (Partial 0) (const Nothing)
840 step j a =
844 step j a =
842− $ if i == j
845+ if i == j
843− then Done $ Just a
846+ then Done $ Just a
844− else Partial (j + 1)
847+ else Partial (j + 1)
846-- | Lookup the element at the given index.
849-- | Lookup the element at the given index.
@@ -869,15 +872,14 @@ head = _Fold1 const
869-- @since 0.7.0
872-- @since 0.7.0
870{-# INLINABLE find #-}
873{-# INLINABLE find #-}
871find :: Monad m => (a -> Bool) -> Fold m a (Maybe a)
874find :: Monad m => (a -> Bool) -> Fold m a (Maybe a)
872−find predicate = Fold step (return ()) (const (return Nothing))
875+find predicate = mkFold step (Partial ()) (const Nothing)
876 step () a =
879 step () a =
878− $ if predicate a
880+ if predicate a
879− then Done (Just a)
881+ then Done (Just a)
880− else Partial ()
882+ else Partial ()
882-- | In a stream of (key-value) pairs @(a, b)@, return the value @b@ of the
884-- | In a stream of (key-value) pairs @(a, b)@, return the value @b@ of the
883-- first pair where the key equals the given value @a@.
885-- first pair where the key equals the given value @a@.
@@ -887,30 +889,28 @@ find predicate = Fold step (return ()) (const (return Nothing))
887-- @since 0.7.0
889-- @since 0.7.0
888{-# INLINABLE lookup #-}
890{-# INLINABLE lookup #-}
889lookup :: (Eq a, Monad m) => a -> Fold m (a,b) (Maybe b)
891lookup :: (Eq a, Monad m) => a -> Fold m (a,b) (Maybe b)
890−lookup a0 = Fold step (return ()) (const (return Nothing))
892+lookup a0 = mkFold step (Partial ()) (const Nothing)
894 step () (a, b) =
896 step () (a, b) =
896− $ if a == a0
897+ if a == a0
897− then Done $ Just b
898+ then Done $ Just b
898− else Partial ()
899+ else Partial ()
900-- | Returns the first index that satisfies the given predicate.
901-- | Returns the first index that satisfies the given predicate.
902-- @since 0.7.0
903-- @since 0.7.0
903{-# INLINABLE findIndex #-}
904{-# INLINABLE findIndex #-}
904findIndex :: Monad m => (a -> Bool) -> Fold m a (Maybe Int)
905findIndex :: Monad m => (a -> Bool) -> Fold m a (Maybe Int)
905−findIndex predicate = Fold step (return 0) (const (return Nothing))
906+findIndex predicate = mkFold step (Partial 0) (const Nothing)
909 step i a =
910 step i a =
911− $ if predicate a
911+ if predicate a
912− then Done $ Just i
912+ then Done $ Just i
913− else Partial (i + 1)
913+ else Partial (i + 1)
915-- | Returns the first index where a given value is found in the stream.
915-- | Returns the first index where a given value is found in the stream.
@@ -932,7 +932,7 @@ elemIndex a = findIndex (a ==)
932-- @since 0.7.0
932-- @since 0.7.0
933{-# INLINABLE null #-}
933{-# INLINABLE null #-}
934null :: Monad m => Fold m a Bool
934null :: Monad m => Fold m a Bool
935−null = Fold (\() _ -> return $ Done False) (return ()) (\() -> return True)
935+null = mkFold (\() _ -> Done False) (Partial ()) (const True)
938-- > any p = lmap p or
938-- > any p = lmap p or
@@ -946,17 +946,16 @@ null = Fold (\() _ -> return $ Done False) (return ()) (\() -> return True)
946-- @since 0.7.0
946-- @since 0.7.0
947{-# INLINE any #-}
947{-# INLINE any #-}
948any :: Monad m => (a -> Bool) -> Fold m a Bool
948any :: Monad m => (a -> Bool) -> Fold m a Bool
949−any predicate = Fold step initial return
949+any predicate = mkFold_ step initial
953− initial = return False
953+ initial = Partial False
955 step _ a =
955 step _ a =
957− $ if predicate a
956+ if predicate a
958− then Done True
957+ then Done True
959− else Partial False
958+ else Partial False
961-- | Return 'True' if the given element is present in the stream.
960-- | Return 'True' if the given element is present in the stream.
@@ -979,17 +978,16 @@ elem a = any (a ==)
979-- @since 0.7.0
978-- @since 0.7.0
980{-# INLINABLE all #-}
979{-# INLINABLE all #-}
981all :: Monad m => (a -> Bool) -> Fold m a Bool
980all :: Monad m => (a -> Bool) -> Fold m a Bool
982−all predicate = Fold step initial return
981+all predicate = mkFold_ step initial
986− initial = return True
985+ initial = Partial True
988 step _ a =
987 step _ a =
990− $ if predicate a
988+ if predicate a
991− then Partial True
989+ then Partial True
992− else Done False
990+ else Done False
994-- | Returns 'True' if the given element is not present in the stream.
992-- | Returns 'True' if the given element is not present in the stream.
@@ -1199,18 +1197,18 @@ sliceEndWith predicate (Fold fstep finitial fextract) =
1200 initial = finitial
1198 initial = finitial
1202− step s a =
1200+ step s a = do
1203 if not (predicate a)
1202 if not (predicate a)
1204− then fstep s a
1203+ then return res
1207 case res of
1205 case res of
1208− Partial sres -> Done <$> fextract sres
1206+ Partial s1 -> Done <$> fextract s1
1209− Done bres -> return $ Done bres
1207+ Done b -> return $ Done b
1211data SpanByState a bl fl fr
1209data SpanByState a bl fl fr
1212− = SpanByLeft0 !fl !fr
1210+ = SpanByLeft0 !fl
1213− | SpanByLeft !a !fl !fr
1211+ | SpanByLeft !a !fl
1214 | SpanByRight !bl !fr
1212 | SpanByRight !bl !fr
1216-- | Break the input stream into two groups, the first group takes the input as
1214-- | Break the input stream into two groups, the first group takes the input as
@@ -1231,31 +1229,50 @@ spanBy cmp (Fold stepL initialL extractL) (Fold stepR initialR extractR) =
1234− initial = SpanByLeft0 <$> initialL <*> initialR
1232+ initial = do
1235+ Partial fl -> return $ Partial $ SpanByLeft0 fl
1240+ Partial fr -> Partial $ SpanByRight bl fr
1241+ Done br -> Done (bl, br)
1236− step (SpanByLeft0 fl fr) input = do
1243+ step (SpanByLeft0 fl) input = do
1237 sfl <- stepL fl input
1244 sfl <- stepL fl input
1240− $ case sfl of
1245+ case sfl of
1241− Partial fl1 -> SpanByLeft input fl1 fr
1246+ Partial fl1 -> return $ Partial $ SpanByLeft input fl1
1242− Done bl -> SpanByRight bl fr
1251+ Partial fr -> Partial $ SpanByRight bl fr
1252+ Done br -> Done (bl, br)
1243− step (SpanByLeft frst fl fr) input =
1253+ step (SpanByLeft frst fl) input =
1244 if cmp frst input
1254 if cmp frst input
1246 sfl <- stepL fl input
1256 sfl <- stepL fl input
1249− $ case sfl of
1257+ case sfl of
1250− Partial fl1 -> SpanByLeft frst fl1 fr
1258+ Partial fl1 -> return $ Partial $ SpanByLeft frst fl1
1251− Done bl -> SpanByRight bl fr
1263+ Partial fr -> Partial $ SpanByRight bl fr
1264+ Done br -> Done (bl, br)
1253 bl <- extractL fl
1266 bl <- extractL fl
1254− sfr <- stepR fr input
1270+ sfr <- stepR fr input
1256− $ case sfr of
1272+ $ case sfr of
1257− Partial fr1 -> Partial $ SpanByRight bl fr1
1273+ Partial fr1 -> Partial $ SpanByRight bl fr1
1274+ Done br -> Done (bl, br)
1258− Done br -> Done (bl, br)
1275+ Done br -> return $ Done (bl, br)
1259 step (SpanByRight bl fr) input = do
1276 step (SpanByRight bl fr) input = do
1260 sfr <- stepR fr input
1277 sfr <- stepR fr input
@@ -1263,12 +1280,22 @@ spanBy cmp (Fold stepL initialL extractL) (Fold stepR initialR extractR) =
1263 Partial fr1 -> Partial $ SpanByRight bl fr1
1280 Partial fr1 -> Partial $ SpanByRight bl fr1
1264 Done br -> Done (bl, br)
1281 Done br -> Done (bl, br)
1266− extract (SpanByLeft0 fl fr) = (,) <$> extractL fl <*> extractR fr
1283+ extract (SpanByLeft0 fl) = do
1287+ Partial fr -> (bl, ) <$> extractR fr
1288+ Done br -> return (bl, br)
1267− extract (SpanByLeft _ fl fr) = (,) <$> extractL fl <*> extractR fr
1289+ extract (SpanByLeft _ fl) = do
1293+ Partial fr -> (bl, ) <$> extractR fr
1294+ Done br -> return (bl, br)
1268 extract (SpanByRight bl fr) = (bl, ) <$> extractR fr
1295 extract (SpanByRight bl fr) = (bl, ) <$> extractR fr
1270data SpanState bl fl fr
1297data SpanState bl fl fr
1271− = SpanLeft !fl !fr
1298+ = SpanLeft !fl
1272 | SpanRight !bl !fr
1299 | SpanRight !bl !fr
1274-- | @span p f1 f2@ composes folds @f1@ and @f2@ such that @f1@ consumes the
1301-- | @span p f1 f2@ composes folds @f1@ and @f2@ such that @f1@ consumes the
@@ -1302,24 +1329,40 @@ span p (Fold stepL initialL extractL) (Fold stepR initialR extractR) =
1305− initial = SpanLeft <$> initialL <*> initialR
1332+ initial = do
1335+ Partial fl -> return $ Partial $ SpanLeft fl
1340+ Partial fr -> Partial $ SpanRight bl fr
1341+ Done br -> Done (bl, br)
1307− step (SpanLeft fl fr) input =
1343+ step (SpanLeft fl) input =
1308 if p input
1344 if p input
1310 sfl <- stepL fl input
1346 sfl <- stepL fl input
1313− $ case sfl of
1347+ case sfl of
1314− Partial fl1 -> SpanLeft fl1 fr
1348+ Partial fl1 -> return $ Partial $ SpanLeft fl1
1315− Done bl -> SpanRight bl fr
1353+ Partial fr -> Partial $ SpanRight bl fr
1354+ Done br -> Done (bl, br)
1317 bl <- extractL fl
1356 bl <- extractL fl
1318− sfr <- stepR fr input
1360+ sfr <- stepR fr input
1320− $ case sfr of
1362+ $ case sfr of
1321− Partial fr1 -> Partial $ SpanRight bl fr1
1363+ Partial fr1 -> Partial $ SpanRight bl fr1
1364+ Done br -> Done (bl, br)
1322− Done br -> Done (bl, br)
1365+ Done br -> return $ Done (bl, br)
1323 step (SpanRight bl fr) input = do
1366 step (SpanRight bl fr) input = do
1324 sfr <- stepR fr input
1367 sfr <- stepR fr input
@@ -1327,7 +1370,12 @@ span p (Fold stepL initialL extractL) (Fold stepR initialR extractR) =
1327 Partial fr1 -> Partial $ SpanRight bl fr1
1370 Partial fr1 -> Partial $ SpanRight bl fr1
1328 Done br -> Done (bl, br)
1371 Done br -> Done (bl, br)
1330− extract (SpanLeft fl fr) = (,) <$> extractL fl <*> extractR fr
1373+ extract (SpanLeft fl) = do
1377+ Partial fr -> (bl, ) <$> extractR fr
1378+ Done br -> return (bl, br)
1331 extract (SpanRight bl fr) = (bl, ) <$> extractR fr
1379 extract (SpanRight bl fr) = (bl, ) <$> extractR fr
@@ -1376,31 +1424,50 @@ spanByRolling cmp (Fold stepL initialL extractL) (Fold stepR initialR extractR)
1379− initial = SpanByLeft0 <$> initialL <*> initialR
1427+ initial = do
1430+ Partial fl -> return $ Partial $ SpanByLeft0 fl
1435+ Partial fr -> Partial $ SpanByRight bl fr
1436+ Done br -> Done (bl, br)
1381− step (SpanByLeft0 fl fr) input = do
1438+ step (SpanByLeft0 fl) input = do
1382 sfl <- stepL fl input
1439 sfl <- stepL fl input
1385− $ case sfl of
1440+ case sfl of
1386− Partial fl1 -> SpanByLeft input fl1 fr
1441+ Partial fl1 -> return $ Partial $ SpanByLeft input fl1
1387− Done bl -> SpanByRight bl fr
1446+ Partial fr -> Partial $ SpanByRight bl fr
1447+ Done br -> Done (bl, br)
1388− step (SpanByLeft frst fl fr) input =
1448+ step (SpanByLeft input0 fl) input =
1389− if cmp frst input
1449+ if cmp input0 input
1391 sfl <- stepL fl input
1451 sfl <- stepL fl input
1394− $ case sfl of
1452+ case sfl of
1395− Partial fl1 -> SpanByLeft input fl1 fr
1453+ Partial fl1 -> return $ Partial $ SpanByLeft input fl1
1396− Done bl -> SpanByRight bl fr
1458+ Partial fr -> Partial $ SpanByRight bl fr
1459+ Done br -> Done (bl, br)
1398 bl <- extractL fl
1461 bl <- extractL fl
1399− sfr <- stepR fr input
1465+ sfr <- stepR fr input
1401− $ case sfr of
1467+ $ case sfr of
1402− Partial fr1 -> Partial $ SpanByRight bl fr1
1468+ Partial fr1 -> Partial $ SpanByRight bl fr1
1469+ Done br -> Done (bl, br)
1403− Done br -> Done (bl, br)
1470+ Done br -> return $ Done (bl, br)
1404 step (SpanByRight bl fr) input = do
1471 step (SpanByRight bl fr) input = do
1405 sfr <- stepR fr input
1472 sfr <- stepR fr input
@@ -1408,8 +1475,18 @@ spanByRolling cmp (Fold stepL initialL extractL) (Fold stepR initialR extractR)
1408 Partial fr1 -> Partial $ SpanByRight bl fr1
1475 Partial fr1 -> Partial $ SpanByRight bl fr1
1409 Done br -> Done (bl, br)
1476 Done br -> Done (bl, br)
1411− extract (SpanByLeft0 fl fr) = (,) <$> extractL fl <*> extractR fr
1478+ extract (SpanByLeft0 fl) = do
1482+ Partial fr -> (bl, ) <$> extractR fr
1483+ Done br -> return (bl, br)
1412− extract (SpanByLeft _ fl fr) = (,) <$> extractL fl <*> extractR fr
1484+ extract (SpanByLeft _ fl) = do
1488+ Partial fr -> (bl, ) <$> extractR fr
1489+ Done br -> return (bl, br)
1413 extract (SpanByRight bl fr) = (bl, ) <$> extractR fr
1490 extract (SpanByRight bl fr) = (bl, ) <$> extractR fr
1415------------------------------------------------------------------------------
1492------------------------------------------------------------------------------
@@ -1451,17 +1528,6 @@ breakOn pat f m = undefined
1451tee :: Monad m => Fold m a b -> Fold m a c -> Fold m a (b,c)
1528tee :: Monad m => Fold m a b -> Fold m a c -> Fold m a (b,c)
1452tee = teeWith (,)
1529tee = teeWith (,)
1454−{-# INLINE foldNil #-}
1455−foldNil :: Monad m => Fold m a [b]
1456−foldNil = Fold step begin done where
1458− step _ _ = return $ Partial []
1461−{-# INLINE foldCons #-}
1462−foldCons :: Monad m => Fold m a b -> Fold m a [b] -> Fold m a [b]
1463−foldCons = teeWith (:)
1465-- XXX use "List" instead of "[]"?, use Array for output to scale it to a large
1531-- XXX use "List" instead of "[]"?, use Array for output to scale it to a large
1466-- number of consumers? For polymorphic case a vector could be helpful. For
1532-- number of consumers? For polymorphic case a vector could be helpful. For
1467-- Storables we can use arrays. Will need separate APIs for those.
1533-- Storables we can use arrays. Will need separate APIs for those.
@@ -1488,7 +1554,7 @@ foldCons = teeWith (:)
1488-- @since 0.7.0
1554-- @since 0.7.0
1489{-# INLINE distribute #-}
1555{-# INLINE distribute #-}
1490distribute :: Monad m => [Fold m a b] -> Fold m a [b]
1556distribute :: Monad m => [Fold m a b] -> Fold m a [b]
1491−distribute = foldr foldCons foldNil
1557+distribute = foldr (teeWith (:)) (yield [])
1493------------------------------------------------------------------------------
1559------------------------------------------------------------------------------
1494-- Partitioning
1560-- Partitioning
@@ -1549,7 +1615,20 @@ partitionByM f (Fold stepL beginL doneL) (Fold stepR beginR doneR) =
1552− begin = RunBoth <$> beginL <*> beginR
1618+ begin = do
1626+ Partial sR -> RunBoth sL sR
1627+ Done bR -> RunLeft sL bR
1630+ Partial sR -> Partial $ RunRight bL sR
1631+ Done bR -> Done (bL, bR)
1554 step (RunBoth sL sR) a = do
1633 step (RunBoth sL sR) a = do
1555 r <- f a
1634 r <- f a
@@ -1707,10 +1786,10 @@ demux :: (Monad m, Ord k)
1707 => Map k (Fold m a b) -> Fold m (k, a) (Map k b)
1786 => Map k (Fold m a b) -> Fold m (k, a) (Map k b)
1708demux = demuxWith id
1787demux = demuxWith id
1710−data DemuxState s b rMap kvMap =
1789+data DemuxState s b doneMap runMap =
1711− DemuxMapWithDefault !s !rMap !kvMap
1790+ DemuxMapAndDefault !s !doneMap !runMap
1712− | DemuxMap b !rMap !kvMap
1791+ | DemuxOnlyMap b !doneMap !runMap
1713− | DemuxDefault s !rMap
1792+ | DemuxOnlyDefault s !doneMap
1715-- | Like 'demuxWith' but uses a default catchall fold to handle inputs which
1794-- | Like 'demuxWith' but uses a default catchall fold to handle inputs which
1716-- do not have a specific fold in the map to handle them.
1795-- do not have a specific fold in the map to handle them.
@@ -1734,87 +1813,102 @@ demuxDefaultWith f kv (Fold dstep dinitial dextract) =
1737− initial =
1816+ initial = do
1738− DemuxMapWithDefault
1817+ let runInit (Fold step1 initial1 done1) = do
1739− <$> dinitial
1818+ r <- initial1
1740− <*> return Map.empty
1819+ return
1741− <*> Prelude.mapM initialize kv
1820+ $ case r of
1821+ Partial _ -> Right' (Fold step1 (return r) done1)
1743− step (DemuxMapWithDefault dacc results kvMap) a =
1824+ -- initialize folds in the kv map and separate the ones that are done
1825+ -- from running ones
1826+ kv1 <- Prelude.mapM runInit kv
1827+ let runMap = Map.map fromRight' $ Map.filter isRight' kv1
1828+ doneMap = Map.map fromLeft' $ Map.filter isLeft' kv1
1830+ -- Run the default fold, and decide the next state based on its result
1836+ $ if Map.size runMap > 0
1837+ then DemuxMapAndDefault s doneMap runMap
1838+ else DemuxOnlyDefault s doneMap
1840+ if Map.size runMap > 0
1841+ then Partial $ DemuxOnlyMap b doneMap runMap
1842+ else Done (doneMap, b)
1844+ {-# INLINE runFold #-}
1845+ runFold fPartial fDone doneMap runMap (Fold step1 initial1 done1) k a1 = do
1850+ return $ case res of
1852+ let fld = Fold step1 (return $ Partial s) done1
1853+ runMap1 = Map.insert k fld runMap
1854+ in Partial $ fPartial doneMap runMap1
1856+ let runMap1 = Map.delete k runMap
1857+ doneMap1 = Map.insert k b doneMap
1744− if Map.size kvMap > 0
1858+ if Map.size runMap1 == 0
1745− then do
1859+ then fDone doneMap1
1860+ else Partial $ fPartial doneMap1 runMap1
1861+ Done _ -> error "Bug: demuxDefaultWith: Done fold"
1863+ step (DemuxMapAndDefault dacc doneMap runMap) a = do
1746− let (k, a1) = f a
1864+ let (k, a1) = f a
1747− case Map.lookup k kvMap of
1865+ case Map.lookup k runMap of
1748− Nothing -> do
1866+ Nothing -> do
1749− res <- dstep dacc (k, a1)
1867+ res <- dstep dacc (k, a1)
1751− $ Partial
1869+ $ Partial
1752− $ case res of
1870+ $ case res of
1753− Partial s -> DemuxMapWithDefault s results kvMap
1871+ Partial s -> DemuxMapAndDefault s doneMap runMap
1754− Done b -> DemuxMap b results kvMap
1872+ Done b -> DemuxOnlyMap b doneMap runMap
1755− Just (Fold step1 initial1 extract1) -> do
1873+ Just fld ->
1756− !st <- initial1
1874+ runFold
1757− !res <- step1 st a1
1875+ (DemuxMapAndDefault dacc)
1760− Partial s ->
1876+ (Partial . DemuxOnlyDefault dacc)
1761− let fld = Fold step1 (return s) extract1
1877+ doneMap runMap fld k a1
1762− kvMap1 = Map.insert k fld kvMap
1878+
1763− in Partial
1879+ step (DemuxOnlyMap dval doneMap runMap) a = do
1764− $ DemuxMapWithDefault
1765− dacc results kvMap1
1767− let kvMap1 = Map.delete k kvMap
1768− results1 = Map.insert k b results
1770− $ if Map.size kvMap1 == 0
1771− then DemuxDefault dacc results1
1772− else DemuxMapWithDefault
1773− dacc results1 kvMap1
1774− -- XXX Remove this when we have Step in the initial value
1775− else error "demuxDefaultWith: empty key-value Map"
1776− step (DemuxMap dval results kvMap) a =
1777− if Map.size kvMap > 0
1779− let (k, a1) = f a
1880+ let (k, a1) = f a
1780− case Map.lookup k kvMap of
1881+ case Map.lookup k runMap of
1781− Nothing -> return $ Partial $ DemuxMap dval results kvMap
1882+ Nothing -> return $ Partial $ DemuxOnlyMap dval doneMap runMap
1782− Just (Fold step1 initial1 extract1) -> do
1883+ Just fld ->
1783− !st <- initial1
1884+ runFold
1784− !res <- step1 st a1
1885+ (DemuxOnlyMap dval)
1788− let fld = Fold step1 (return s) extract1
1789− kvMap1 = Map.insert k fld kvMap
1790− in Partial $ DemuxMap dval results kvMap1
1791− Done b ->
1886+ (Done . (, dval))
1792− let kvMap1 = Map.delete k kvMap
1887+ doneMap runMap fld k a1
1793− results1 = Map.insert k b results
1888+ step (DemuxOnlyDefault dacc doneMap) a = do
1794− in if Map.size kvMap1 == 0
1795− then Done (results1, dval)
1797− $ DemuxMap dval results1 kvMap1
1798− -- XXX Remove this when we have Step in the initial value
1799− else error "demuxDefaultWith: empty key-value Map"
1800− step (DemuxDefault dacc results) a = do
1801 let (k, a1) = f a
1889 let (k, a1) = f a
1802 res <- dstep dacc (k, a1)
1890 res <- dstep dacc (k, a1)
1804 $ case res of
1892 $ case res of
1805− Partial s -> Partial $ DemuxDefault s results
1893+ Partial s -> Partial $ DemuxOnlyDefault s doneMap
1806− Done b -> Done (results, b)
1894+ Done b -> Done (doneMap, b)
1808− extract (DemuxMapWithDefault dacc results kvMap) = do
1896+ runExtract (Fold _ initial1 done1) = do
1899+ Partial s -> done1 s
1902+ extract (DemuxMapAndDefault dacc doneMap runMap) = do
1809 b <- dextract dacc
1903 b <- dextract dacc
1810− kvMap1 <- Prelude.mapM (\(Fold _ i d) -> i >>= d) kvMap
1904+ runMap1 <- Prelude.mapM runExtract runMap
1811− return (results `Map.union` kvMap1, b)
1905+ return (doneMap `Map.union` runMap1, b)
1812− extract (DemuxMap dval results kvMap) = do
1906+ extract (DemuxOnlyMap dval doneMap runMap) = do
1813− kvMap1 <- Prelude.mapM (\(Fold _ i d) -> i >>= d) kvMap
1907+ runMap1 <- Prelude.mapM runExtract runMap
1814− return (results `Map.union` kvMap1, dval)
1908+ return (doneMap `Map.union` runMap1, dval)
1815− extract (DemuxDefault dacc results) = do
1909+ extract (DemuxOnlyDefault dacc doneMap) = do
1816 b <- dextract dacc
1910 b <- dextract dacc
1817− return (results, b)
1911+ return (doneMap, b)
1819{-# INLINE demuxDefault #-}
1913{-# INLINE demuxDefault #-}
1820demuxDefault :: (Monad m, Ord k)
1914demuxDefault :: (Monad m, Ord k)
@@ -1844,43 +1938,44 @@ demuxDefault = demuxDefaultWith id
1845{-# INLINE classifyWith #-}
1939{-# INLINE classifyWith #-}
1846classifyWith :: (Monad m, Ord k) => (a -> k) -> Fold m a b -> Fold m a (Map k b)
1940classifyWith :: (Monad m, Ord k) => (a -> k) -> Fold m a b -> Fold m a (Map k b)
1847−classifyWith f (Fold step initial extract) = Fold step' initial' extract'
1941+classifyWith f (Fold step1 initial1 extract1) = mkAccumM step initial extract
1851− initial' = return Map.empty
1945+ initial = return Map.empty
1853− step' kv a =
1947+ step kv a =
1854 case Map.lookup k kv of
1948 case Map.lookup k kv of
1855 Nothing -> do
1949 Nothing -> do
1856− x <- initial
1950+ x <- initial1
1857− r <- step x a
1951+ case x of
1860− $ flip (Map.insert k) kv
1955+ $ flip (Map.insert k) kv
1861− $ case r of
1956+ $ case r of
1862− Partial sr -> Left' sr
1957+ Partial s1 -> Left' s1
1863− Done br -> Right' br
1958+ Done b -> Right' b
1959+ Done b -> return $ Map.insert k (Right' b) kv
1864 Just x -> do
1960 Just x -> do
1865 case x of
1961 case x of
1866 Left' s -> do
1962 Left' s -> do
1867− r <- step s a
1963+ r <- step1 s a
1870 $ flip (Map.insert k) kv
1965 $ flip (Map.insert k) kv
1871 $ case r of
1966 $ case r of
1872− Partial sr -> Left' sr
1967+ Partial s1 -> Left' s1
1873− Done br -> Right' br
1968+ Done b -> Right' b
1874− Right' _ -> return $ Partial kv
1969+ Right' _ -> return kv
1880− extract' =
1975+ extract =
1881 Prelude.mapM
1976 Prelude.mapM
1883− Left' s -> extract s
1978+ Left' s -> extract1 s
1884 Right' b -> return b)
1979 Right' b -> return b)
1886-- | Given an input stream of key value pairs and a fold for values, fold all
1981-- | Given an input stream of key value pairs and a fold for values, fold all
@@ -1920,7 +2015,20 @@ unzipWithM f (Fold stepL beginL doneL) (Fold stepR beginR doneR) =
1923− begin = RunBoth <$> beginL <*> beginR
2018+ begin = do
2026+ Partial sR -> RunBoth sL sR
2027+ Done bR -> RunLeft sL bR
2030+ Partial sR -> Partial $ RunRight bL sR
2031+ Done bR -> Done (bL, bR)
1925 step (RunBoth sL sR) a = do
2033 step (RunBoth sL sR) a = do
1926 (b, c) <- f a
2034 (b, c) <- f a
@@ -2048,7 +2156,7 @@ toParallelSVar svar winfo = Fold step initial extract
2051− initial = return ()
2159+ initial = return $ Partial ()
2053 -- XXX we can have a separate fold for unlimited buffer case to avoid a
2161 -- XXX we can have a separate fold for unlimited buffer case to avoid a
2054 -- branch in the step here.
2162 -- branch in the step here.
@@ -2067,7 +2175,7 @@ toParallelSVarLimited svar winfo = Fold step initial extract
2070− initial = return True
2178+ initial = return $ Partial True
2072 step True x =
2180 step True x =
2073 liftIO $ do
2181 liftIO $ do