on master help sign in
Add foldl' and sconcat consumers
6006084Harendra Kumar
src/Streamly/Internal/Data/Consumer/Type.hs+60−4
@@ -23,22 +23,36 @@ module Streamly.Internal.Data.Consumer.Type
23 -- * Types
23 -- * Types
24 Consumer (..)
24 Consumer (..)
25
25
26− -- Combinators
26+ -- * Constructors
27− , lmapM
27+ , foldl'
28− , rmapM
29
28
30− -- Consumers
29+ -- * Consumers
30+ -- ** Accumulators
31+ , sconcat
31 , drainBy
32 , drainBy
33+
34+ -- * Combinators
35+ , lmapM
36+ , rmapM
32 , take
37 , take
33 )
38 )
34where
39where
35
40
36import Control.Monad ((>=>))
41import Control.Monad ((>=>))
42+#if __GLASGOW_HASKELL__ < 804
43+import Data.Semigroup (Semigroup((<>)))
44+#endif
37import Fusion.Plugin.Types (Fuse(..))
45import Fusion.Plugin.Types (Fuse(..))
38import Streamly.Internal.Data.Fold.Step (Step(..), mapMStep)
46import Streamly.Internal.Data.Fold.Step (Step(..), mapMStep)
39
47
40import Prelude hiding (take)
48import Prelude hiding (take)
41
49
50+-- $setup
51+-- >>> :m
52+-- >>> import qualified Streamly.Internal.Data.Consumer.Type as Consumer
53+-- >>> import qualified Streamly.Internal.Data.Fold.Type as Fold
54+-- >>> import qualified Streamly.Internal.Data.Stream.IsStream as Stream
55+
42-- All folds in the Fold module should be implemented using Consumers.
56-- All folds in the Fold module should be implemented using Consumers.
43--
57--
44-- | Like 'Fold' except that the initial state of the accmulator can be
58-- | Like 'Fold' except that the initial state of the accmulator can be
@@ -51,6 +65,27 @@ data Consumer m c a b =
51 -- | @Fold @ @ step @ @ inject @ @ extract@
65 -- | @Fold @ @ step @ @ inject @ @ extract@
52 forall s. Consumer (s -> a -> m (Step s b)) (c -> m (Step s b)) (s -> m b)
66 forall s. Consumer (s -> a -> m (Step s b)) (c -> m (Step s b)) (s -> m b)
53
67
68+------------------------------------------------------------------------------
69+-- Left fold constructors
70+------------------------------------------------------------------------------
71+
72+-- | Make a consumer from a left fold style pure step function.
73+--
74+-- If your 'Fold' returns only 'Partial' (i.e. never returns a 'Done') then you
75+-- can use @foldl'*@ constructors.
76+--
77+-- See also: @Streamly.Prelude.foldl'@
78+--
79+-- /Internal/
80+--
81+{-# INLINE foldl' #-}
82+foldl' :: Monad m => (b -> a -> b) -> Consumer m b a b
83+foldl' step =
84+ Consumer
85+ (\s a -> return $ Partial $ step s a)
86+ (return . Partial)
87+ return
88+
54------------------------------------------------------------------------------
89------------------------------------------------------------------------------
55-- Mapping on input
90-- Mapping on input
56------------------------------------------------------------------------------
91------------------------------------------------------------------------------
@@ -101,6 +136,27 @@ drainBy f = Consumer step inject extract
101
136
102 extract _ = return ()
137 extract _ = return ()
103
138
139+------------------------------------------------------------------------------
140+-- Semigroup
141+------------------------------------------------------------------------------
142+
143+-- | Append the elements of an input stream to a provided starting value.
144+--
145+-- >>> stream = Stream.map Data.Monoid.Sum $ Stream.enumerateFromTo 1 10
146+-- >>> Stream.fold (Fold.fromConsumer Consumer.sconcat 10) stream
147+-- Sum {getSum = 65}
148+--
149+-- >>> sconcat = Consumer.foldl' (<>)
150+--
151+-- /Internal/
152+{-# INLINE sconcat #-}
153+sconcat :: (Monad m, Semigroup a) => Consumer m a a a
154+sconcat = foldl' (<>)
155+
156+------------------------------------------------------------------------------
157+-- Transformation
158+------------------------------------------------------------------------------
159+
104-- Required to fuse "take" with "many" in "chunksOf", for ghc-9.x
160-- Required to fuse "take" with "many" in "chunksOf", for ghc-9.x
105{-# ANN type Tuple'Fused Fuse #-}
161{-# ANN type Tuple'Fused Fuse #-}
106data Tuple'Fused a b = Tuple'Fused !a !b deriving Show
162data Tuple'Fused a b = Tuple'Fused !a !b deriving Show