@@ -52,6 +52,7 @@ module Streamly.Internal.Data.Fold
5252 , drain
5353 , drainBy
5454 , last
55+ , the
5556 , length
5657 , genericLength
5758 , countDistinct
@@ -150,6 +151,7 @@ module Streamly.Internal.Data.Fold
150151 -- , ldeleteBy
151152 -- , luniq
152153 , nub
154+ , nubInt
153155
154156 -- ** Mapping Filters
155157 , catMaybes
@@ -590,6 +592,43 @@ satisfy f = Fold step (return $ Partial ()) (const (return Nothing))
590592foldFilter :: Monad m => Fold m a (Maybe b) -> Fold m b c -> Fold m a c
591593foldFilter f1 f2 = many f1 (catMaybes f2)
592594
595+-- | Used as a scan. Returns 'Just' for the first occurrence of an element,
596+-- returns 'Nothing' for any other occurrences.
597+--
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
600+-- [1,2,3,4,5,7]
601+--
602+-- /Pre-release/
603+{-# INLINE nub #-}
604+nub :: (Monad m, Ord a) => Fold m a (Maybe a)
605+nub = fmap (\(Tuple' _ x) -> x) $ foldl' step initial
606+
607+ where
608+
609+ initial = Tuple' Set.empty Nothing
610+
611+ step (Tuple' set _) x =
612+ if Set.member x set
613+ then Tuple' set Nothing
614+ else Tuple' (Set.insert x set) (Just x)
615+
616+-- | Like 'nub' but specialized to a stream of 'Int', for better performance.
617+--
618+-- /Pre-release/
619+{-# INLINE nubInt #-}
620+nubInt :: Monad m => Fold m Int (Maybe Int)
621+nubInt = fmap (\(Tuple' _ x) -> x) $ foldl' step initial
622+
623+ where
624+
625+ initial = Tuple' IntSet.empty Nothing
626+
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)
631+
593632------------------------------------------------------------------------------
594633-- Left folds
595634------------------------------------------------------------------------------
@@ -621,6 +660,24 @@ drainBy f = lmapM f drain
621660last :: Monad m => Fold m a (Maybe a)
622661last = foldl1' (\_ x -> x)
623662
663+-- | If the stream consists of one or more occurences of the same element
664+-- then returns that element else terminates and returns 'Nothing'.
665+--
666+-- /Pre-release/
667+{-# INLINE the #-}
668+the :: (Monad m, Eq a) => Fold m a (Maybe a)
669+the = foldt' step initial id
670+
671+ where
672+
673+ initial = Partial Nothing
674+
675+ step Nothing x = Partial (Just x)
676+ step old@(Just x0) x =
677+ if x0 == x
678+ then Partial old
679+ else Done Nothing
680+
624681------------------------------------------------------------------------------
625682-- To Summary
626683------------------------------------------------------------------------------
@@ -651,6 +708,8 @@ length = genericLength
651708--
652709-- Equivalent to using 'nub' followed by 'length' on a stream.
653710--
711+-- >>> countDistinct = Fold.postscan Fold.nub $ Fold.catMaybes $ Fold.length
712+--
654713-- The memory used is proportional to the number of distinct elements in the
655714-- stream, to guard against using too much memory use it as a scan and
656715-- terminate if the count reaches more than a threshold.
@@ -661,6 +720,8 @@ length = genericLength
661720--
662721{-# INLINE countDistinct #-}
663722countDistinct :: (Monad m, Ord a) => Fold m a Int
723+countDistinct = postscan nub $ catMaybes $ length
724+{-
664725countDistinct = fmap (\(Tuple' _ n) -> n) $ foldl' step initial
665726
666727 where
@@ -674,13 +735,18 @@ countDistinct = fmap (\(Tuple' _ n) -> n) $ foldl' step initial
674735 else
675736 let cnt = n + 1
676737 in Tuple' (Set.insert x set) cnt
738+-}
677739
678740-- | Like 'countDistinct' but specialized to a stream of 'Int', for better
679741-- performance.
680742--
743+-- >>> countDistinctInt = Fold.postscan Fold.nubInt $ Fold.catMaybes $ Fold.length
744+--
681745-- /Pre-release/
682746{-# INLINE countDistinctInt #-}
683747countDistinctInt :: Monad m => Fold m Int Int
748+countDistinctInt = postscan nubInt $ catMaybes $ length
749+{-
684750countDistinctInt = fmap (\(Tuple' _ n) -> n) $ foldl' step initial
685751
686752 where
@@ -694,6 +760,7 @@ countDistinctInt = fmap (\(Tuple' _ n) -> n) $ foldl' step initial
694760 else
695761 let cnt = n + 1
696762 in Tuple' (IntSet.insert x set) cnt
763+ -}
697764
698765-- | Determine the sum of all elements of a stream of numbers. Returns additive
699766-- identity (@0@) when the stream is empty. Note that this is not numerically
@@ -2573,46 +2640,3 @@ top = topBy $ flip compare
25732640{-# INLINE bottom #-}
25742641bottom :: (MonadIO m, Storable a, Ord a) => Int -> Fold m a (MA.Array a)
25752642bottom = topBy compare
2576−
2577−-- | Delete the duplicate elements from the stream while scanning.
2578−-- It returns (Just a) for new element and Nothing for duplicates ones.
2579−--
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
2582−-- [1,2,3,4,5,7]
2583−--
2584−-- /Pre-release/
2585−{-# INLINE nub #-}
2586−nub :: (MonadIO m, Ord a) => Fold m a (Maybe a)
2587−nub = Fold step initial extract
2588−
2589− where
2590−
2591− initial = return $ Partial (Set.empty, Nothing)
2592−
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)
2597−
2598− extract = return . snd
2599−
2600−{-# INLINE the #-}
2601−the :: (Eq a, Monad m) => Fold m a (Maybe a)
2602−the = Fold step initial extract
2603−
2604− where
2605−
2606− initial =
2607− return $ Partial Nothing
2608−
2609− step Nothing x =
2610− return $ Partial (Just x)
2611−
2612− step old@(Just x0) x =
2613− return $
2614− if x0 == x
2615− then Partial old
2616− else Done Nothing
2617−
2618− extract = return