on master help sign in
Refactor "the", "nub", add nubInt
71b0c0dHarendra Kumar
core/src/Streamly/Internal/Data/Fold.hs+67−43
@@ -52,6 +52,7 @@ module Streamly.Internal.Data.Fold
52 , drain
52 , drain
53 , drainBy
53 , drainBy
54 , last
54 , last
55+ , the
55 , length
56 , length
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
152 , nub
153 , nub
154+ , nubInt
153
155
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)
592
594
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+
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)
623
662
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+
624------------------------------------------------------------------------------
681------------------------------------------------------------------------------
625-- To Summary
682-- To Summary
626------------------------------------------------------------------------------
683------------------------------------------------------------------------------
@@ -651,6 +708,8 @@ length = genericLength
651--
708--
652-- Equivalent to using 'nub' followed by 'length' on a stream.
709-- Equivalent to using 'nub' followed by 'length' on a stream.
653--
710--
711+-- >>> countDistinct = Fold.postscan Fold.nub $ Fold.catMaybes $ Fold.length
712+--
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
661--
720--
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
724+{-
664countDistinct = fmap (\(Tuple' _ n) -> n) $ foldl' step initial
725countDistinct = fmap (\(Tuple' _ n) -> n) $ foldl' step initial
665
726
666 where
727 where
@@ -674,13 +735,18 @@ countDistinct = fmap (\(Tuple' _ n) -> n) $ foldl' step initial
674 else
735 else
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
738+-}
677
739
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.
680--
742--
743+-- >>> countDistinctInt = Fold.postscan Fold.nubInt $ Fold.catMaybes $ Fold.length
744+--
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
749+{-
684countDistinctInt = fmap (\(Tuple' _ n) -> n) $ foldl' step initial
750countDistinctInt = fmap (\(Tuple' _ n) -> n) $ foldl' step initial
685
751
686 where
752 where
@@ -694,6 +760,7 @@ countDistinctInt = fmap (\(Tuple' _ n) -> n) $ foldl' step initial
694 else
760 else
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
763+ -}
697
764
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
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