on master help sign in
Fix the argument order of Stream.groupsBy
commitaa023809e6a3242a3f306f52e4064a6649a4c921 authorAdithya Kumar <adithya@composewell.com> dateWed 19 Jul 2023, 14:02 (3 years ago) parentdef5297
2 files changed+58−22
benchmark/Streamly/Benchmark/Data/Stream/Reduce.hs+33−14 core/src/Streamly/Internal/Data/Stream/StreamD/Nesting.hs+25−8
benchmark/Streamly/Benchmark/Data/Stream/Reduce.hs+33−14
@@ -107,30 +107,50 @@ iterateSource g count len n = f count (sourceUnfoldrM len n)
107107-- Grouping transformations
108108-------------------------------------------------------------------------------
109109
110−#ifdef USE_PRELUDE
111110{-# INLINE groups #-}
112111groups :: MonadIO m => Stream m Int -> m ()
113−groups = Common.drain . S.groups FL.drain
112+groups =
113+#ifdef USE_PRELUDE
114+ Common.drain . S.groups FL.drain
115+#else
116+ Common.drain . S.groupsWhile (==) FL.drain
117+#endif
114118
115−-- XXX Change this test when the order of comparison is later changed
116−{-# INLINE groupsByGT #-}
117−groupsByGT :: MonadIO m => Stream m Int -> m ()
118−groupsByGT = Common.drain . S.groupsBy (>) FL.drain
119+{-# INLINE groupsWhileLT #-}
120+groupsWhileLT :: MonadIO m => Stream m Int -> m ()
121+groupsWhileLT =
122+#ifdef USE_PRELUDE
123+ Common.drain . S.groupsBy (>) FL.drain
124+#else
125+ Common.drain . S.groupsWhile (<) FL.drain
126+#endif
127+
128+{-# INLINE groupsWhileEq #-}
129+groupsWhileEq :: MonadIO m => Stream m Int -> m ()
130+groupsWhileEq =
131+#ifdef USE_PRELUDE
132+ Common.drain . S.groupsBy (==) FL.drain
133+#else
134+ Common.drain . S.groupsWhile (==) FL.drain
135+#endif
119136
120−{-# INLINE groupsByEq #-}
121−groupsByEq :: MonadIO m => Stream m Int -> m ()
122−groupsByEq = Common.drain . S.groupsBy (==) FL.drain
123137
124−-- XXX Change this test when the order of comparison is later changed
125138{-# INLINE groupsByRollingLT #-}
126139groupsByRollingLT :: MonadIO m => Stream m Int -> m ()
127140groupsByRollingLT =
141+#ifdef USE_PRELUDE
128142 Common.drain . S.groupsByRolling (<) FL.drain
143+#else
144+ Common.drain . S.groupsRollingBy (<) FL.drain
145+#endif
129146
130147{-# INLINE groupsByRollingEq #-}
131148groupsByRollingEq :: MonadIO m => Stream m Int -> m ()
132149groupsByRollingEq =
150+#ifdef USE_PRELUDE
133151 Common.drain . S.groupsByRolling (==) FL.drain
152+#else
153+ Common.drain . S.groupsRollingBy (==) FL.drain
134154#endif
135155
136156{-# INLINE foldMany #-}
@@ -190,14 +210,13 @@ o_1_space_grouping value =
190210 -- Buffering operations using heap proportional to group/window sizes.
191211 [ bgroup "grouping"
192212 [
193−#ifdef USE_PRELUDE
194213 benchIOSink value "groups" groups
195− , benchIOSink value "groupsByGT" groupsByGT
196− , benchIOSink value "groupsByEq" groupsByEq
214+ , benchIOSink value "groupsWhileLT" groupsWhileLT
215+ , benchIOSink value "groupsWhileEq" groupsWhileEq
197216 , benchIOSink value "groupsByRollingLT" groupsByRollingLT
198217 , benchIOSink value "groupsByRollingEq" groupsByRollingEq
199218 ,
200−#endif
219+
201220 -- XXX parseMany/parseIterate benchmarks are in the Parser/ParserD
202221 -- modules we can bring those here. chunksOf benchmarks are in
203222 -- Parser/ParserD/Array.Stream/FileSystem.Handle.
core/src/Streamly/Internal/Data/Stream/StreamD/Nesting.hs+25−8
@@ -141,6 +141,7 @@ module Streamly.Internal.Data.Stream.StreamD.Nesting
141141 -- | Group segments of a stream and fold. Special case of parsing.
142142 , groupsOf
143143 , groupsBy
144+ , groupsWhile
144145 , groupsRollingBy
145146
146147 -- ** Splitting
@@ -1896,16 +1897,23 @@ data GroupByState st fs a b
18961897 | GroupingYield !b (GroupByState st fs a b)
18971898 | GroupingDone
18981899
1899−{-# INLINE_NORMAL groupsBy #-}
1900−groupsBy :: Monad m
1900+-- | The argument order of the comparison function in `groupsWhile` is
1901+-- different than that of `groupsBy`.
1902+--
1903+-- In `groupsBy` the comparison function takes the next element as the first
1904+-- argument and the previous element as the second argument. In `groupsWhile`
1905+-- the first argument is the previous element and second argument is the next
1906+-- element.
1907+{-# INLINE_NORMAL groupsWhile #-}
1908+groupsWhile :: Monad m
19011909 => (a -> a -> Bool)
19021910 -> Fold m a b
19031911 -> Stream m a
19041912 -> Stream m b
19051913{-
1906−groupsBy eq fld = parseMany (PRD.groupBy eq fld)
1914+groupsWhile eq fld = parseMany (PRD.groupBy eq fld)
19071915-}
1908−groupsBy cmp (Fold fstep initial done) (Stream step state) =
1916+groupsWhile cmp (Fold fstep initial done) (Stream step state) =
19091917 Stream stepOuter (GroupingInit state)
19101918
19111919 where
@@ -1936,7 +1944,7 @@ groupsBy cmp (Fold fstep initial done) (Stream step state) =
19361944 res <- step (adaptState gst) stt
19371945 case res of
19381946 Yield x s -> do
1939− if cmp x prev
1947+ if cmp prev x
19401948 then do
19411949 r <- fstep acc x
19421950 case r of
@@ -1966,7 +1974,7 @@ groupsBy cmp (Fold fstep initial done) (Stream step state) =
19661974 res <- step (adaptState gst) stt
19671975 case res of
19681976 Yield x s -> do
1969− if cmp x prev
1977+ if cmp prev x
19701978 then do
19711979 r <- fstep acc x
19721980 case r of
@@ -1977,9 +1985,18 @@ groupsBy cmp (Fold fstep initial done) (Stream step state) =
19771985 return $ Yield r (GroupingInitWith s x)
19781986 Skip s -> go SPEC s acc
19791987 Stop -> done acc >>= \r -> return $ Yield r GroupingDone
1980− stepOuter _ (GroupingYield _ _) = error "groupsBy: Unreachable"
1988+ stepOuter _ (GroupingYield _ _) = error "groupsWhile: Unreachable"
19811989 stepOuter _ GroupingDone = return Stop
19821990
1991+{-# DEPRECATED groupsBy "Please use groupsWhile instead. Please note the change in the argument order of the comparison function." #-}
1992+{-# INLINE_NORMAL groupsBy #-}
1993+groupsBy :: Monad m
1994+ => (a -> a -> Bool)
1995+ -> Fold m a b
1996+ -> Stream m a
1997+ -> Stream m b
1998+groupsBy cmp = groupsWhile (flip cmp)
1999+
19832000{-# INLINE_NORMAL groupsRollingBy #-}
19842001groupsRollingBy :: Monad m
19852002 => (a -> a -> Bool)
@@ -2045,7 +2062,7 @@ groupsRollingBy cmp (Fold fstep initial done) (Stream step state) =
20452062
20462063 where
20472064
2048− -- XXX GHC: groupsBy has one less parameter in this go loop and it
2065+ -- XXX GHC: groupsWhile has one less parameter in this go loop and it
20492066 -- fuses. However, groupsRollingBy does not fuse, removing the prev
20502067 -- parameter makes it fuse. Something needs to be fixed in GHC. The
20512068 -- workaround for this is noted in the comments below.