on master help sign in
Implement nub as Fold
commit8ac1ad15c2b07ff6f88826b04c56de3875637316 authorRanjeet Kumar Ranjan <ranjeetr@composewell.com> dateFri 3 Jun 2022, 21:34 (4 years ago) parent3e76123
3 files changed+35−1
benchmark/Streamly/Benchmark/Data/Fold.hs+1 core/src/Streamly/Internal/Data/Fold.hs+25−1 test/Streamly/Test/Data/Fold.hs+9
benchmark/Streamly/Benchmark/Data/Fold.hs+1
@@ -294,6 +294,7 @@ o_1_space_serial_elimination value =
294294 , benchIOSink value "drainBy" (S.fold (FL.drainBy return))
295295 , benchIOSink value "drainN" (S.fold (FL.drainN value))
296296 , benchIOSink value "last" (S.fold FL.last)
297+ , benchIOSink value "nub" (S.fold FL.nub)
297298 , benchIOSink value "length" (S.fold FL.length)
298299 , benchIOSink value "top" (S.fold $ FL.top 10)
299300 , benchIOSink value "bottom" (S.fold $ FL.bottom 10)
core/src/Streamly/Internal/Data/Fold.hs+25−1
@@ -280,6 +280,7 @@ module Streamly.Internal.Data.Fold
280280 , finish
281281 , top
282282 , bottom
283+ , nub
283284
284285 -- * Deprecated
285286 , sequence
@@ -335,7 +336,7 @@ import Streamly.Internal.Data.Fold.Type
335336-- >>> :set -package streamly
336337-- >>> import Prelude hiding (break, map, span, splitAt)
337338-- >>> import qualified Streamly.Prelude as Stream
338−-- >>> import qualified Streamly.Internal.Data.Stream.IsStream as Stream (parse, foldMany)
339+-- >>> import qualified Streamly.Internal.Data.Stream.IsStream as Stream (catMaybes, parse, foldMany)
339340-- >>> import qualified Streamly.Data.Fold as Fold
340341-- >>> import qualified Streamly.Internal.Data.Fold as Fold
341342-- >>> import qualified Streamly.Internal.Data.Fold.Type as Fold
@@ -2562,3 +2563,26 @@ top = topBy $ flip compare
25622563{-# INLINE bottom #-}
25632564bottom :: (MonadIO m, Storable a, Ord a) => Int -> Fold m a (MA.Array a)
25642565bottom = topBy compare
2566+
2567+-- | Delete the duplicate elements from the stream while scanning.
2568+-- It returns (Just a) for new element and Nothing for duplicates ones.
2569+--
2570+-- >>> stream = Stream.fromList [1::Int, 1, 2, 3, 4, 4, 5, 1, 5, 7]
2571+-- >>> Stream.toList $ Stream.catMaybes $ Stream.postscan Fold.nub stream
2572+-- [1,2,3,4,5,7]
2573+--
2574+-- /Pre-release/
2575+{-# INLINE nub #-}
2576+nub :: (MonadIO m, Ord a) => Fold m a (Maybe a)
2577+nub = Fold step initial extract
2578+
2579+ where
2580+
2581+ initial = return $ Partial (Set.empty, Nothing)
2582+
2583+ step (set, _) x = do
2584+ if Set.member x set
2585+ then return $ Partial (set, Nothing)
2586+ else return $ Partial (Set.insert x set, Just x)
2587+
2588+ extract = return . snd
test/Streamly/Test/Data/Fold.hs+9
@@ -670,6 +670,14 @@ top = topBy True
670670bottom :: Property
671671bottom = topBy False
672672
673+nub :: Property
674+nub = monadicIO $ do
675+ vals <- Stream.toList
676+ $ Stream.catMaybes
677+ $ Stream.postscan F.nub
678+ $ Stream.fromList [1::Int, 1, 2, 3, 4, 4, 5, 1, 5, 7]
679+ assert (vals == [1, 2, 3, 4, 5, 7])
680+
673681moduleName :: String
674682moduleName = "Data.Fold"
675683
@@ -720,6 +728,7 @@ main = hspec $ do
720728 prop "or" Main.or
721729 prop "top" Main.top
722730 prop "bottom" Main.bottom
731+ prop "nub" Main.nub
723732
724733 -- Combinators
725734