on master help sign in
Implementation added for grouping, spanning Fold functions (#193)

* Implementation added for grouping, spanning Fold functions Added grouped, span functions implementations which are undefined before. * Removed spanned function, commented out spanBy and spanRollingBy functions and added support for span function without depending on spanBy Previously span was impelmented using spanBy, but seems like spanBy was not completely done and lot of edge cases like one element in the stream are not handled, so implemented span without any dependency and commented out the spanBy, spanRollingBy functions Deleted spanned functions, as doesn't seem much useful cases invovled with it

commitf310bedfd5567ac5eabab430f861fae5fe17f896 authorACreed <aravindgopal.ag@gmail.com> dateSun 19 May 2019, 16:55 (7 years ago) parent3c84a03
2 files changed+131−30
src/Streamly/Fold.hs+74−30 src/Streamly/Streams/StreamD.hs+57
src/Streamly/Fold.hs+74−30
@@ -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 (==)
src/Streamly/Streams/StreamD.hs+57
@@ -133,6 +133,7 @@ module Streamly.Streams.StreamD
133133 , groupsOf
134134 , grouped
135135 , groupsBy
136+ , groupsRollingBy
136137
137138 -- ** Splitting
138139 , splitBy
@@ -1014,6 +1015,62 @@ groupsBy cmp f (Stream step state) = Stream (stepOuter f) (Just state, Nothing)
10141015
10151016 stepOuter _ _ (Nothing,_) = return Stop
10161017
1018+{-# INLINE_NORMAL groupsRollingBy #-}
1019+groupsRollingBy :: Monad m
1020+ => (a -> a -> Bool)
1021+ -> Fold m a b
1022+ -> Stream m a
1023+ -> Stream m b
1024+groupsRollingBy cmp f (Stream step state) =
1025+ Stream (stepOuter f) (Just state, Nothing)
1026+ where
1027+
1028+ {-# INLINE_LATE stepOuter #-}
1029+ stepOuter (Fold fstep initial done) gst (Just st, Nothing) = do
1030+ res <- step (adaptState gst) st
1031+ case res of
1032+ Yield x s -> do
1033+ acc <- initial
1034+ acc' <- fstep acc x
1035+ go SPEC x s acc'
1036+
1037+ Skip s -> return $ Skip $ (Just s, Nothing)
1038+ Stop -> return Stop
1039+
1040+ where
1041+ go !_ prev stt !acc = do
1042+ res <- step (adaptState gst) stt
1043+ case res of
1044+ Yield x s -> do
1045+ if cmp x prev
1046+ then do
1047+ acc' <- fstep acc x
1048+ go SPEC x s acc'
1049+ else
1050+ done acc >>= \r -> return $ Yield r (Just s, Just x)
1051+ Skip s -> go SPEC prev s acc
1052+ Stop -> done acc >>= \r -> return $ Yield r (Nothing, Nothing)
1053+
1054+ stepOuter (Fold fstep initial done) gst (Just st, Just prev') = do
1055+ acc <- initial
1056+ acc' <- fstep acc prev'
1057+ go SPEC prev' st acc'
1058+
1059+ where
1060+ go !_ prevv stt !acc = do
1061+ res <- step (adaptState gst) stt
1062+ case res of
1063+ Yield x s -> do
1064+ if cmp x prevv
1065+ then do
1066+ acc' <- fstep acc x
1067+ go SPEC x s acc'
1068+ else done acc >>= \r -> return $ Yield r (Just s, Just x)
1069+ Skip s -> go SPEC prevv s acc
1070+ Stop -> done acc >>= \r -> return $ Yield r (Nothing, Nothing)
1071+
1072+ stepOuter _ _ (Nothing, _) = return Stop
1073+
10171074{-# INLINE_EARLY splitSuffixBy' #-}
10181075splitSuffixBy' :: Monad m
10191076 => (a -> Bool) -> Fold m a b -> Stream m a -> Stream m b