@@ -52,6 +52,7 @@ module Streamly.Internal.Data.Fold
56 , genericLength
57 , genericLength
57 , countDistinct
58 , countDistinct
@@ -150,6 +151,7 @@ module Streamly.Internal.Data.Fold
150 -- , ldeleteBy
151 -- , ldeleteBy
151 -- , luniq
152 -- , luniq
154 -- ** Mapping Filters
156 -- ** Mapping Filters
155 , catMaybes
157 , catMaybes
@@ -590,6 +592,43 @@ satisfy f = Fold step (return $ Partial ()) (const (return Nothing))
590foldFilter :: Monad m => Fold m a (Maybe b) -> Fold m b c -> Fold m a c
592foldFilter :: Monad m => Fold m a (Maybe b) -> Fold m b c -> Fold m a c
591foldFilter f1 f2 = many f1 (catMaybes f2)
593foldFilter f1 f2 = many f1 (catMaybes f2)
595+-- | Used as a scan. Returns 'Just' for the first occurrence of an element,
596+-- returns 'Nothing' for any other occurrences.
598+-- >>> stream = Stream.fromList [1::Int,1,2,3,4,4,5,1,5,7]
599+-- >>> Stream.toList $ Stream.catMaybes $ Stream.postscan Fold.nub stream
604+nub :: (Monad m, Ord a) => Fold m a (Maybe a)
605+nub = fmap (\(Tuple' _ x) -> x) $ foldl' step initial
609+ initial = Tuple' Set.empty Nothing
611+ step (Tuple' set _) x =
613+ then Tuple' set Nothing
614+ else Tuple' (Set.insert x set) (Just x)
616+-- | Like 'nub' but specialized to a stream of 'Int', for better performance.
619+{-# INLINE nubInt #-}
620+nubInt :: Monad m => Fold m Int (Maybe Int)
621+nubInt = fmap (\(Tuple' _ x) -> x) $ foldl' step initial
625+ initial = Tuple' IntSet.empty Nothing
627+ step (Tuple' set _) x =
628+ if IntSet.member x set
629+ then Tuple' set Nothing
630+ else Tuple' (IntSet.insert x set) (Just x)
593------------------------------------------------------------------------------
632------------------------------------------------------------------------------
594-- Left folds
633-- Left folds
595------------------------------------------------------------------------------
634------------------------------------------------------------------------------
@@ -621,6 +660,24 @@ drainBy f = lmapM f drain
621last :: Monad m => Fold m a (Maybe a)
660last :: Monad m => Fold m a (Maybe a)
622last = foldl1' (\_ x -> x)
661last = foldl1' (\_ x -> x)
663+-- | If the stream consists of one or more occurences of the same element
664+-- then returns that element else terminates and returns 'Nothing'.
668+the :: (Monad m, Eq a) => Fold m a (Maybe a)
669+the = foldt' step initial id
673+ initial = Partial Nothing
675+ step Nothing x = Partial (Just x)
676+ step old@(Just x0) x =
624------------------------------------------------------------------------------
681------------------------------------------------------------------------------
625-- To Summary
682-- To Summary
626------------------------------------------------------------------------------
683------------------------------------------------------------------------------
@@ -651,6 +708,8 @@ length = genericLength
652-- Equivalent to using 'nub' followed by 'length' on a stream.
709-- Equivalent to using 'nub' followed by 'length' on a stream.
711+-- >>> countDistinct = Fold.postscan Fold.nub $ Fold.catMaybes $ Fold.length
654-- The memory used is proportional to the number of distinct elements in the
713-- The memory used is proportional to the number of distinct elements in the
655-- stream, to guard against using too much memory use it as a scan and
714-- stream, to guard against using too much memory use it as a scan and
656-- terminate if the count reaches more than a threshold.
715-- terminate if the count reaches more than a threshold.
@@ -661,6 +720,8 @@ length = genericLength
662{-# INLINE countDistinct #-}
721{-# INLINE countDistinct #-}
663countDistinct :: (Monad m, Ord a) => Fold m a Int
722countDistinct :: (Monad m, Ord a) => Fold m a Int
723+countDistinct = postscan nub $ catMaybes $ length
664countDistinct = fmap (\(Tuple' _ n) -> n) $ foldl' step initial
725countDistinct = fmap (\(Tuple' _ n) -> n) $ foldl' step initial
@@ -674,13 +735,18 @@ countDistinct = fmap (\(Tuple' _ n) -> n) $ foldl' step initial
675 let cnt = n + 1
736 let cnt = n + 1
676 in Tuple' (Set.insert x set) cnt
737 in Tuple' (Set.insert x set) cnt
678-- | Like 'countDistinct' but specialized to a stream of 'Int', for better
740-- | Like 'countDistinct' but specialized to a stream of 'Int', for better
679-- performance.
741-- performance.
743+-- >>> countDistinctInt = Fold.postscan Fold.nubInt $ Fold.catMaybes $ Fold.length
681-- /Pre-release/
745-- /Pre-release/
682{-# INLINE countDistinctInt #-}
746{-# INLINE countDistinctInt #-}
683countDistinctInt :: Monad m => Fold m Int Int
747countDistinctInt :: Monad m => Fold m Int Int
748+countDistinctInt = postscan nubInt $ catMaybes $ length
684countDistinctInt = fmap (\(Tuple' _ n) -> n) $ foldl' step initial
750countDistinctInt = fmap (\(Tuple' _ n) -> n) $ foldl' step initial
@@ -694,6 +760,7 @@ countDistinctInt = fmap (\(Tuple' _ n) -> n) $ foldl' step initial
695 let cnt = n + 1
761 let cnt = n + 1
696 in Tuple' (IntSet.insert x set) cnt
762 in Tuple' (IntSet.insert x set) cnt
698-- | Determine the sum of all elements of a stream of numbers. Returns additive
765-- | Determine the sum of all elements of a stream of numbers. Returns additive
699-- identity (@0@) when the stream is empty. Note that this is not numerically
766-- identity (@0@) when the stream is empty. Note that this is not numerically
@@ -2573,46 +2640,3 @@ top = topBy $ flip compare
2573{-# INLINE bottom #-}
2640{-# INLINE bottom #-}
2574bottom :: (MonadIO m, Storable a, Ord a) => Int -> Fold m a (MA.Array a)
2641bottom :: (MonadIO m, Storable a, Ord a) => Int -> Fold m a (MA.Array a)
2575bottom = topBy compare
2642bottom = topBy compare
2577−-- | Delete the duplicate elements from the stream while scanning.
2578−-- It returns (Just a) for new element and Nothing for duplicates ones.
2580−-- >>> stream = Stream.fromList [1::Int, 1, 2, 3, 4, 4, 5, 1, 5, 7]
2581−-- >>> Stream.toList $ Stream.catMaybes $ Stream.postscan Fold.nub stream
2586−nub :: (MonadIO m, Ord a) => Fold m a (Maybe a)
2587−nub = Fold step initial extract
2591− initial = return $ Partial (Set.empty, Nothing)
2593− step (set, _) x = do
2594− if Set.member x set
2595− then return $ Partial (set, Nothing)
2596− else return $ Partial (Set.insert x set, Just x)
2598− extract = return . snd
2601−the :: (Eq a, Monad m) => Fold m a (Maybe a)
2602−the = Fold step initial extract
2607− return $ Partial Nothing
2610− return $ Partial (Just x)
2612− step old@(Just x0) x =