@@ -76,10 +76,13 @@ module Streamly.Fold
76 , foldMapM
76 , foldMapM
78 -- ** Full Folds (To Containers)
78 -- ** Full Folds (To Containers)
79+ -- | Avoid using these folds in scalable or performance critical
80+ -- applications, they buffer all the input in memory.
79− -- , toStream -- experimental
82+ , toStream -- experimental
80 , toStreamRev -- experimental
83 , toStreamRev -- experimental
82− -- , toList
85+ , toList
83 , toListRev -- experimental
86 , toListRev -- experimental
85 -- ** Partial Folds
88 -- ** Partial Folds
@@ -646,9 +649,9 @@ foldMapM act = Fold step begin done
646-- @since 0.7.0
649-- @since 0.7.0
648-- id . (x1 :) . (x2 :) . (x3 :) . ... . (xn :) $ []
651-- id . (x1 :) . (x2 :) . (x3 :) . ... . (xn :) $ []
649−{-# INLINABLE _toList #-}
652+{-# INLINABLE toList #-}
650−_toList :: Monad m => Fold m a [a]
653+toList :: Monad m => Fold m a [a]
651−_toList = Fold (\f x -> return $ f . (x :))
654+toList = Fold (\f x -> return $ f . (x :))
652 (return id)
655 (return id)
653 (return . ($ []))
656 (return . ($ []))
@@ -673,9 +676,9 @@ toListRev = Fold (\xs x -> return $ x:xs) (return []) return
673-- be very inefficient, consider using "Streamly.Array" instead.
676-- be very inefficient, consider using "Streamly.Array" instead.
675-- @since 0.7.0
678-- @since 0.7.0
676−{-# INLINABLE _toStream #-}
679+{-# INLINABLE toStream #-}
677−_toStream :: Monad m => Fold m a (SerialT Identity a)
680+toStream :: Monad m => Fold m a (SerialT Identity a)
678−_toStream = Fold (\f x -> return $ f . (x `K.cons`))
681+toStream = Fold (\f x -> return $ f . (x `K.cons`))
679 (return id)
682 (return id)
680 (return . ($ K.nil))
683 (return . ($ K.nil))
@@ -943,13 +946,31 @@ ltakeWhile predicate (Fold step initial done) = Fold step' initial' done'
943------------------------------------------------------------------------------
946------------------------------------------------------------------------------
946−{-
949+-- | @splitAt n f1 f2@ composes folds @f1@ and @f2@ such that first @n@
947−-- | Split the input stream into two groups at index @n@, the first group
950+-- elements of its input are sent to fold @f1@ and the rest of the stream is
948−-- consisting of elements from index @0@ to index @n - 1@ i.e. the stream
951+-- sent to fold @f2@.
949−-- prefix of length @n@ and the second group consisting of the rest of the
952−-}
953+-- > let splitAt_ n xs = FL.foldl' (FL.splitAt n FL.toList FL.toList) $ S.fromList xs
955+-- >>> splitAt_ 6 "Hello World!"
956+-- > ("Hello ","World!")
958+-- >>> splitAt_ (-1) [1,2,3]
961+-- >>> splitAt_ 0 [1,2,3]
964+-- >>> splitAt_ 1 [1,2,3]
967+-- >>> splitAt_ 3 [1,2,3]
970+-- >>> splitAt_ 4 [1,2,3]
953{-# INLINE splitAt #-}
974{-# INLINE splitAt #-}
955 :: Monad m
976 :: Monad m
@@ -1018,11 +1039,11 @@ intervalsOf n f m = grouped (lcatMaybes f) s
1018-- Binary APIs
1039-- Binary APIs
1019------------------------------------------------------------------------------
1040------------------------------------------------------------------------------
1021-- | Break the input stream into two groups, the first group takes the input as
1043-- | Break the input stream into two groups, the first group takes the input as
1022-- long as the predicate applied to the first element of the stream and next
1044-- long as the predicate applied to the first element of the stream and next
1023-- input element holds 'True', the second group takes the rest of the input.
1045-- input element holds 'True', the second group takes the rest of the input.
1027 :: Monad m
1048 :: Monad m
1028 => (a -> a -> Bool)
1049 => (a -> a -> Bool)
@@ -1052,11 +1073,23 @@ spanBy cmp (Fold stepL initialL extractL) (Fold stepR initialR extractR) =
1052 extract (Tuple3' a b _) = (,) <$> extractL a <*> extractR b
1073 extract (Tuple3' a b _) = (,) <$> extractL a <*> extractR b
1055−-- |
1076+-- | Span as long as the predicate is 'True'. @span p f1 f2@ composes folds
1077+-- @f1@ and @f2@ such that the composed fold continues sending the input to
1078+-- @f1@ as long as the predicate @p@ is 'True'. The rest of the input is sent
1057−-- Break the input stream into two groups, the first group takes the input as
1081+-- > let span_ p xs = FL.foldl' (FL.span p FL.toList FL.toList) $ S.fromList xs
1058−-- long as the predicate is 'True', the second group takes the rest of the
1082+--
1059−-- input.
1083+-- >>> span_ (< 1) [1,2,3]
1086+-- >>> span_ (< 2) [1,2,3]
1089+-- >>> span_ (< 4) [1,2,3]
1060{-# INLINE span #-}
1093{-# INLINE span #-}
1062 :: Monad m
1095 :: Monad m
@@ -1080,9 +1113,22 @@ span p (Fold stepL initialL extractL) (Fold stepR initialR extractR) =
1081-- > break p = span (not . p)
1114-- > break p = span (not . p)
1083−-- Break the input stream into two groups, the first group takes the input as
1116+-- Break as soon as the predicate becomes 'True'. @break p f1 f2@ composes
1084−-- long as the predicate is 'False', the second group takes the rest of the
1117+-- folds @f1@ and @f2@ such that @f1@ stops receiving input as soon as the
1085−-- input.
1118+-- predicate @p@ becomes 'True'. The rest of the input is sent to @f2@.
1120+-- > let break_ p xs = FL.foldl' (FL.break p FL.toList FL.toList) $ S.fromList xs
1122+-- >>> break_ (< 1) [3,2,1]
1125+-- >>> break_ (< 2) [3,2,1]
1128+-- >>> break_ (< 4) [3,2,1]
1086{-# INLINE break #-}
1132{-# INLINE break #-}
1088 :: Monad m
1134 :: Monad m
@@ -1144,13 +1190,14 @@ _newline m = S.foldrS (\x xs ->
1144 then (x,True) `K.cons` xs
1190 then (x,True) `K.cons` xs
1145 else (x,False) `K.cons` xs) K.nil m
1191 else (x,False) `K.cons` xs) K.nil m
1147−-- | Group by applying a predicate to the first element of the current group
1193+-- | @groupsBy cmp f $ S.fromList [a,b,c,...]@ assigns the element @a@ to the
1148−-- and the next element in the input stream. The next element is considered
1194+-- first group, if @a \`cmp` b@ is 'True' then @b@ is also assigned to the same
1149−-- part of the current group if the predicate succeeds otherwise a new group
1195+-- group. If @a \`cmp` c@ is 'True' then @c@ is also assigned to the same
1150−-- starts.
1196+-- group and so on. When the comparison fails a new group is started. Each
1197+-- group is folded using the fold @f@.
1152−-- >>> S.toList $ FL.groupsBy (==) FL.toList $ S.fromList [1,1,2,2]
1199+-- >>> S.toList $ FL.groupsBy (>) FL.toList $ S.fromList [1,3,7,0,2,5]
1153−-- > [[1,1],[2,2]]
1200+-- > [[1,3,7],[0,2,5]]
1155-- @since 0.7.0
1202-- @since 0.7.0
@@ -1161,13 +1208,18 @@ groupsBy
1161 -> t m b
1208 -> t m b
1162groupsBy cmp f m = D.fromStreamD $ D.groupsBy cmp f (D.toStreamD m)
1209groupsBy cmp f m = D.fromStreamD $ D.groupsBy cmp f (D.toStreamD m)
1164−{-
1211+-- | Unlike @groupsBy@ this function performs a rolling comparison of two
1165−-- | Apply a predicate to each new element in the input stream and the last
1166−-- element of the current group. In other words, perform a rolling comparison
1167−-- between two successive elements in the stream. The new element is considered
1212+-- successive elements in the input stream. @groupsRollingBy cmp f $ S.fromList
1168−-- part of the current group if the predicate succeeds otherwise a new group
1213+-- [a,b,c,...]@ assigns the element @a@ to the first group, if @a \`cmp` b@ is
1169−-- starts.
1214+-- 'True' then @b@ is also assigned to the same group. If @b \`cmp` c@ is
1170−-}
1215+-- 'True' then @c@ is also assigned to the same group and so on. When the
1216+-- comparison fails a new group is started. Each group is folded using the fold
1219+-- >>> S.toList $ FL.groupsRollingBy (\a b -> a + 1 == b) FL.toList $ S.fromList [1,2,3,7,8,9]
1220+-- > [[1,2,3],[7,8,9]]
1171groupsRollingBy
1223groupsRollingBy
1172 :: (IsStream t, Monad m)
1224 :: (IsStream t, Monad m)
1173 => (a -> a -> Bool)
1225 => (a -> a -> Bool)
@@ -1178,6 +1230,9 @@ groupsRollingBy cmp f m = D.fromStreamD $ D.groupsRollingBy cmp f (D.toStreamD
1180-- > groups = groupsBy (==)
1232-- > groups = groupsBy (==)
1233+-- > groups = groupsRollingBy (==)
1235+-- Groups a contiguous span of equal elements together in one group.
1182-- >>> S.toList $ FL.groups FL.toList $ S.fromList [1,1,2,2]
1237-- >>> S.toList $ FL.groups FL.toList $ S.fromList [1,1,2,2]
1183-- > [[1,1],[2,2]]
1238-- > [[1,1],[2,2]]