on master help sign in
Fix uniqBy and rollingMap

Fix hlint Fix review comments Add Functor contraint Fix review comments

commit4b493902860b79f84f4515bfe36b5bd0c96b6c5f authorRanjeet Kumar Ranjan <ranjeetr@composewell.com> dateThu 3 Mar 2022, 21:32 (5 years ago) parentf31f28c
4 files changed+44−24
benchmark/Streamly/Benchmark/Prelude/Serial/Transformation.hs+1−1 core/src/Streamly/Internal/Data/Stream/StreamD/Transform.hs+23−14 src/Streamly/Internal/Data/Stream/IsStream/Transform.hs+15−4 test/Streamly/Test/Prelude/Top.hs+5−5
benchmark/Streamly/Benchmark/Prelude/Serial/Transformation.hs+1−1
@@ -151,7 +151,7 @@ pollCounts n =
151151
152152 where
153153
154− f = Internal.rollingMap (-) . Internal.delayPost 1
154+ f = Internal.rollingMap2 (-) . Internal.delayPost 1
155155
156156{-# INLINE timestamped #-}
157157timestamped :: (S.MonadAsync m) => SerialT m Int -> m ()
core/src/Streamly/Internal/Data/Stream/StreamD/Transform.hs+23−14
@@ -113,6 +113,7 @@ module Streamly.Internal.Data.Stream.StreamD.Transform
113113 -- | Map using the previous element.
114114 , rollingMap
115115 , rollingMapM
116+ , rollingMap2
116117
117118 -- * Maybe Streams
118119 , mapMaybe
@@ -1200,32 +1201,36 @@ slicesBy p (Stream step1 state1) = Stream step (Just (state1, 0, 0))
12001201-- Rolling map
12011202------------------------------------------------------------------------------
12021203
1203−data RollingMapState s a = RollingMapInit s | RollingMapGo s a
1204+data RollingMapState s a = RollingMapGo s a
12041205
12051206{-# INLINE rollingMapM #-}
1206−rollingMapM :: Monad m => (a -> a -> m b) -> Stream m a -> Stream m b
1207−rollingMapM f (Stream step1 state1) = Stream step (RollingMapInit state1)
1207+rollingMapM :: Monad m => (Maybe a -> a -> m b) -> Stream m a -> Stream m b
1208+rollingMapM f (Stream step1 state1) = Stream step (RollingMapGo state1 Nothing)
1209+
12081210 where
1209− step gst (RollingMapInit st) = do
1210− r <- step1 (adaptState gst) st
1211− return $ case r of
1212− Yield x s -> Skip $ RollingMapGo s x
1213− Skip s -> Skip $ RollingMapInit s
1214− Stop -> Stop
12151211
1216− step gst (RollingMapGo s1 x1) = do
1212+ step gst (RollingMapGo s1 curr) = do
12171213 r <- step1 (adaptState gst) s1
12181214 case r of
12191215 Yield x s -> do
1220− !res <- f x x1
1221− return $ Yield res $ RollingMapGo s x
1222− Skip s -> return $ Skip $ RollingMapGo s x1
1216+ !res <- f curr x
1217+ return $ Yield res $ RollingMapGo s (Just x)
1218+ Skip s -> return $ Skip $ RollingMapGo s curr
12231219 Stop -> return Stop
12241220
12251221{-# INLINE rollingMap #-}
1226−rollingMap :: Monad m => (a -> a -> b) -> Stream m a -> Stream m b
1222+rollingMap :: Monad m => (Maybe a -> a -> b) -> Stream m a -> Stream m b
12271223rollingMap f = rollingMapM (\x y -> return $ f x y)
12281224
1225+{-# INLINE rollingMap2 #-}
1226+rollingMap2 :: Monad m => (a -> a -> b) -> Stream m a -> Stream m b
1227+rollingMap2 f = catMaybes . rollingMap g
1228+
1229+ where
1230+
1231+ g Nothing _ = Nothing
1232+ g (Just x) y = Just (f x y)
1233+
12291234------------------------------------------------------------------------------
12301235-- Maybe Streams
12311236------------------------------------------------------------------------------
@@ -1238,3 +1243,7 @@ mapMaybe f = fmap fromJust . filter isJust . map f
12381243{-# INLINE_NORMAL mapMaybeM #-}
12391244mapMaybeM :: Monad m => (a -> m (Maybe b)) -> Stream m a -> Stream m b
12401245mapMaybeM f = fmap fromJust . filter isJust . mapM f
1246+
1247+{-# INLINE catMaybes #-}
1248+catMaybes :: (Monad m) => Stream m (Maybe a) -> Stream m a
1249+catMaybes = fmap fromJust . filter isJust
src/Streamly/Internal/Data/Stream/IsStream/Transform.hs+15−4
@@ -156,6 +156,7 @@ module Streamly.Internal.Data.Stream.IsStream.Transform
156156 -- | Map using the previous element.
157157 , rollingMapM
158158 , rollingMap
159+ , rollingMap2
159160
160161 -- * Maybe Streams
161162 -- Move these to Streamly.Data.Maybe.Stream?
@@ -921,8 +922,14 @@ filterM p m = fromStreamD $ D.filterM p $ toStreamD m
921922{-# INLINE uniqBy #-}
922923uniqBy :: (IsStream t, Monad m, Functor (t m)) =>
923924 (a -> a -> Bool) -> t m a -> t m a
924−uniqBy eq =
925− catMaybes . rollingMap (\x y -> if x `eq` y then Nothing else Just y)
925+uniqBy eq = catMaybes . rollingMap f
926+
927+ where
928+
929+ f pre curr =
930+ case pre of
931+ Nothing -> Just curr
932+ Just x -> if x `eq` curr then Nothing else Just curr
926933
927934-- | Drop repeated elements that are adjacent to each other.
928935--
@@ -1519,7 +1526,7 @@ elemIndices a = findIndices (== a)
15191526-- /Pre-release/
15201527--
15211528{-# INLINE rollingMap #-}
1522−rollingMap :: (IsStream t, Monad m) => (a -> a -> b) -> t m a -> t m b
1529+rollingMap :: (IsStream t, Monad m) => (Maybe a -> a -> b) -> t m a -> t m b
15231530rollingMap f m = fromStreamD $ D.rollingMap f $ toStreamD m
15241531
15251532-- | Like 'rollingMap' but with an effectful map function.
@@ -1527,9 +1534,13 @@ rollingMap f m = fromStreamD $ D.rollingMap f $ toStreamD m
15271534-- /Pre-release/
15281535--
15291536{-# INLINE rollingMapM #-}
1530−rollingMapM :: (IsStream t, Monad m) => (a -> a -> m b) -> t m a -> t m b
1537+rollingMapM :: (IsStream t, Monad m) => (Maybe a -> a -> m b) -> t m a -> t m b
15311538rollingMapM f m = fromStreamD $ D.rollingMapM f $ toStreamD m
15321539
1540+{-# INLINE rollingMap2 #-}
1541+rollingMap2 :: (IsStream t, Monad m) => (a -> a -> b) -> t m a -> t m b
1542+rollingMap2 f m = fromStreamD $ D.rollingMap2 f $ toStreamD m
1543+
15331544------------------------------------------------------------------------------
15341545-- Maybe Streams
15351546------------------------------------------------------------------------------
test/Streamly/Test/Prelude/Top.hs+5−5
@@ -178,10 +178,10 @@ intersectBy ::
178178 )
179179 -> (Int -> Int -> a)
180180 -> Property
181−intersectBy _srt intersectFunc cmp =
181+intersectBy srt intersectFunc cmp =
182182 forAll (listOf (chooseInt (min_value, max_value))) $ \ls0 ->
183183 forAll (listOf (chooseInt (min_value, max_value))) $ \ls1 ->
184− monadicIO $ action (sort ls0) (sort ls1)
184+ monadicIO $ action (srt ls0) (srt ls1)
185185
186186 where
187187
@@ -194,7 +194,7 @@ intersectBy _srt intersectFunc cmp =
194194 (S.fromList ls0)
195195 (S.fromList ls1)
196196 let v2 = ls0 `intersect` ls1
197− assert (v1 == sort v2)
197+ assert (sort v1 == sort v2)
198198
199199-------------------------------------------------------------------------------
200200-- Main
@@ -215,7 +215,7 @@ main = hspec $ do
215215 prop "joinLeft" Main.joinLeft
216216 prop "joinLeftMap" Main.joinLeftMap
217217 -- intersect
218− -- XXX currently API is broken https://github.com/composewell/streamly/issues/1471
219− --prop "intersectBy" (intersectBy id Top.intersectBy (==))
218+ prop "intersectBy"
219+ (intersectBy id Top.intersectBy (==))
220220 prop "intersectBySorted"
221221 (intersectBy sort Top.intersectBySorted compare)