@@ -172,21 +172,18 @@ module Streamly.Fold
172172 -}
173173
174174 -- * Stream Splitting Operations
175− {-
176175 -- ** Spanning
177176 -- | Spanning splits the input into two groups and applies two different
178177 -- folds on each group.
179178
180179 -- Element unaware spanning
181− -- , splitAt
180+ , splitAt
182181
183182 -- Element aware spanning
184183 , span
185184 , break
186− , spanBy
187− , spanRollingBy
188− , spanned
189− -}
185+ -- , spanBy
186+ -- , spanRollingBy
190187
191188 -- ** Grouping
192189 -- | Grouping splits the stream into groups and applies the supplied fold
@@ -212,7 +209,7 @@ module Streamly.Fold
212209 -- Element aware grouping
213210 , groups
214211 , groupsBy
215− -- , groupsRollingBy
212+ , groupsRollingBy
216213 , grouped -- XXX experimental
217214
218215 -- ** Splitting by an Element
@@ -952,14 +949,25 @@ ltakeWhile predicate (Fold step initial done) = Fold step' initial' done'
952949-- prefix of length @n@ and the second group consisting of the rest of the
953950-- stream.
954951--
952+-}
953+{-# INLINE splitAt #-}
955954splitAt
956955 :: Monad m
957956 => Int
958957 -> Fold m a b
959958 -> Fold m a c
960959 -> Fold m a (b, c)
961−splitAt n = undefined
962−-}
960+splitAt n (Fold stepL initialL extractL) (Fold stepR initialR extractR) =
961+ Fold step init extract
962+ where
963+ init = Tuple3' <$> return n <*> initialL <*> initialR
964+
965+ step (Tuple3' i xL xR) input =
966+ if i > 0
967+ then stepL xL input >>= (\a -> return (Tuple3' (i - 1) a xR))
968+ else stepR xR input >>= (\b -> return (Tuple3' i xL b))
969+
970+ extract (Tuple3' _ a b) = (,) <$> extractL a <*> extractR b
963971
964972------------------------------------------------------------------------------
965973-- N-ary APIs
@@ -1010,45 +1018,64 @@ intervalsOf n f m = grouped (lcatMaybes f) s
10101018-- Binary APIs
10111019------------------------------------------------------------------------------
10121020
1013−{-
1014−-- | Break the input stream of type (a,Bool) into two groups, the first group
1015−-- takes input as long as the boolean is True, the second group takes the rest
1016−-- of the input.
1017−--
1018−-- This is the most general spanning combinator, all others can be implemented
1019−-- in terms of this.
1020−--
1021−spanned
1022− :: Monad m
1023− => Fold m a b
1024− -> Fold m a c
1025− -> Fold m (a, Bool) (b, c)
1026−spanned f m = undefined
1027−
10281021-- | Break the input stream into two groups, the first group takes the input as
10291022-- long as the predicate applied to the first element of the stream and next
10301023-- input element holds 'True', the second group takes the rest of the input.
1024+--
1025+{-
10311026spanBy
10321027 :: Monad m
10331028 => (a -> a -> Bool)
10341029 -> Fold m a b
10351030 -> Fold m a c
10361031 -> Fold m a (b, c)
1037−spanBy cmp f1 f2 = undefined
1032+spanBy cmp (Fold stepL initialL extractL) (Fold stepR initialR extractR) =
1033+ Fold step init extract
1034+
1035+ where
1036+ init = Tuple3' <$> initialL <*> initialR <*> return (Tuple' Nothing True)
1037+
1038+ step (Tuple3' a b (Tuple' (Just frst) isFirstG)) input =
1039+ if cmp frst input && isFirstG
1040+ then stepL a input
1041+ >>= (\a' -> return (Tuple3' a' b (Tuple' (Just frst) isFirstG)))
1042+ else stepR b input
1043+ >>= (\a' -> return (Tuple3' a a' (Tuple' Nothing False)))
1044+
1045+ step (Tuple3' a b (Tuple' Nothing isFirstG)) input =
1046+ if isFirstG
1047+ then stepL a input
1048+ >>= (\a' -> return (Tuple3' a' b (Tuple' (Just input) isFirstG)))
1049+ else stepR b input
1050+ >>= (\a' -> return (Tuple3' a a' (Tuple' Nothing False)))
1051+
1052+ extract (Tuple3' a b _) = (,) <$> extractL a <*> extractR b
1053+-}
10381054
10391055-- |
1040−-- > span p = spanBy (\_ x -> p x)
10411056--
10421057-- Break the input stream into two groups, the first group takes the input as
10431058-- long as the predicate is 'True', the second group takes the rest of the
10441059-- input.
1060+{-# INLINE span #-}
10451061span
10461062 :: Monad m
10471063 => (a -> Bool)
10481064 -> Fold m a b
10491065 -> Fold m a c
10501066 -> Fold m a (b, c)
1051−span p = spanBy (\_ x -> p x)
1067+span p (Fold stepL initialL extractL) (Fold stepR initialR extractR) =
1068+ Fold step init extract
1069+
1070+ where
1071+ init = Tuple3' <$> initialL <*> initialR <*> return True
1072+
1073+ step (Tuple3' a b isFirstG) input =
1074+ if isFirstG && p input
1075+ then stepL a input >>= (\a' -> return (Tuple3' a' b True))
1076+ else stepR b input >>= (\a' -> return (Tuple3' a a' False))
1077+
1078+ extract (Tuple3' a b _) = (,) <$> extractL a <*> extractR b
10521079
10531080-- |
10541081-- > break p = span (not . p)
@@ -1056,6 +1083,7 @@ span p = spanBy (\_ x -> p x)
10561083-- Break the input stream into two groups, the first group takes the input as
10571084-- long as the predicate is 'False', the second group takes the rest of the
10581085-- input.
1086+{-# INLINE break #-}
10591087break
10601088 :: Monad m
10611089 => (a -> Bool)
@@ -1064,15 +1092,31 @@ break
10641092 -> Fold m a (b, c)
10651093break p = span (not . p)
10661094
1095+{-
10671096-- | Like 'spanBy' but applies the predicate in a rolling fashion i.e.
10681097-- predicate is applied to the previous and the next input elements.
1098+{-# INLINE spanRollingBy #-}
10691099spanRollingBy
10701100 :: Monad m
10711101 => (a -> a -> Bool)
10721102 -> Fold m a b
10731103 -> Fold m a c
10741104 -> Fold m a (b, c)
1075−spanRollingBy cmp f1 f2 = undefined
1105+spanRollingBy cmp (Fold stepL initialL extractL) (Fold stepR initialR extractR) =
1106+ Fold step init extract
1107+
1108+ where
1109+ init = Tuple3' <$> initialL <*> initialR <*> return Nothing
1110+
1111+ step (Tuple3' a b (Just frst)) input =
1112+ if cmp input frst
1113+ then stepL a input >>= (\a' -> return (Tuple3' a' b (Just input)))
1114+ else stepR b input >>= (\b' -> return (Tuple3' a b' (Just input)))
1115+
1116+ step (Tuple3' a b Nothing) input =
1117+ stepL a input >>= (\a' -> return (Tuple3' a' b (Just input)))
1118+
1119+ extract (Tuple3' a b _) = (,) <$> extractL a <*> extractR b
10761120-}
10771121
10781122------------------------------------------------------------------------------
@@ -1123,14 +1167,14 @@ groupsBy cmp f m = D.fromStreamD $ D.groupsBy cmp f (D.toStreamD m)
11231167-- between two successive elements in the stream. The new element is considered
11241168-- part of the current group if the predicate succeeds otherwise a new group
11251169-- starts.
1170+-}
11261171groupsRollingBy
11271172 :: (IsStream t, Monad m)
11281173 => (a -> a -> Bool)
11291174 -> Fold m a b
11301175 -> t m a
11311176 -> t m b
1132−groupsRollingBy cmp f m = undefined
1133−-}
1177+groupsRollingBy cmp f m = D.fromStreamD $ D.groupsRollingBy cmp f (D.toStreamD m)
11341178
11351179-- |
11361180-- > groups = groupsBy (==)