@@ -55,6 +55,9 @@ module Streamly.Internal.Data.Fold
59 , variance
62 , variance
@@ -268,6 +271,7 @@ import Streamly.Internal.Data.Pipe.Type (Pipe (..), PipeState(..))
268import Streamly.Internal.Data.Tuple.Strict (Tuple'(..), Tuple3'(..))
271import Streamly.Internal.Data.Tuple.Strict (Tuple'(..), Tuple3'(..))
269import Streamly.Internal.Data.Stream.Serial (SerialT(..))
272import Streamly.Internal.Data.Stream.Serial (SerialT(..))
274+import qualified Data.IntSet as IntSet
271import qualified Data.Map.Strict as Map
275import qualified Data.Map.Strict as Map
272import qualified Data.Set as Set
276import qualified Data.Set as Set
273import qualified Streamly.Internal.Data.Pipe.Type as Pipe
277import qualified Streamly.Internal.Data.Pipe.Type as Pipe
@@ -526,6 +530,56 @@ genericLength = foldl' (\n _ -> n + 1) 0
526length :: Monad m => Fold m a Int
530length :: Monad m => Fold m a Int
527length = genericLength
531length = genericLength
534+-- XXX Add a countDistinct window fold
535+-- XXX Add a bloom filter fold
537+-- | Count non-duplicate elements in the stream.
539+-- The memory used is proportional to the number of distinct elements in the
540+-- stream, to guard against using too much memory use it as a scan and
541+-- terminate if the count reaches more than a threshold.
543+-- /Space/: \(\mathcal{O}(n)\)
547+{-# INLINE countDistinct #-}
548+countDistinct :: (Monad m, Ord a) => Fold m a Int
549+countDistinct = fmap (\(Tuple' _ n) -> n) $ foldl' step initial
553+ initial = Tuple' Set.empty 0
555+ step (Tuple' set n) x = do
561+ in Tuple' (Set.insert x set) cnt
563+-- | Like 'countDistinct' but specialized to a stream of 'Int', for better
567+{-# INLINE countDistinctInt #-}
568+countDistinctInt :: Monad m => Fold m Int Int
569+countDistinctInt = fmap (\(Tuple' _ n) -> n) $ foldl' step initial
573+ initial = Tuple' IntSet.empty 0
575+ step (Tuple' set n) x = do
576+ if IntSet.member x set
581+ in Tuple' (IntSet.insert x set) cnt
529-- | Determine the sum of all elements of a stream of numbers. Returns additive
583-- | Determine the sum of all elements of a stream of numbers. Returns additive
530-- identity (@0@) when the stream is empty. Note that this is not numerically
584-- identity (@0@) when the stream is empty. Note that this is not numerically
531-- stable for floating point numbers.
585-- stable for floating point numbers.