on master help sign in
Udate docs, reorganize exports
711ca32Harendra Kumar
src/Streamly/Data/Fold.hs+56−67
@@ -6,61 +6,55 @@
6-- Stability : experimental
6-- Stability : experimental
7-- Portability : GHC
7-- Portability : GHC
8--
8--
9−-- 'Fold' type represents an effectful action that consumes a value from an
9+-- The 'Fold' type represents an effectful action that absorbs a value into an
10−-- input stream and combines it with a single final value often called an
10+-- accumulator. For example, a 'sum' 'Fold' represents adding the input to the
11−-- accumulator, returning the resulting output accumulator. Values from a
11+-- accumulated sum. A fold driver e.g. 'Streamly.Prelude.fold' pushes values
12−-- stream can be /pushed/ to the fold and consumed one at a time. It can also
12+-- from a stream to the 'Fold' one at a time, reducing the stream to a single
13−-- be called a consumer of stream or a sink. It is a data representation of
13+-- value. Therefore, a fold can also be thought of as a sink or a stream
14−-- the standard 'Streamly.Prelude.foldl'' function. A 'Fold' can be turned
14+-- consumer.
15−-- into an effect (@m b@) using 'Streamly.Prelude.fold' by supplying it the
16−-- input stream.
17--
15--
18−-- Using this representation multiple folds can be combined efficiently using
16+-- A 'Fold' is in fact a data representation of a standard left fold ('foldl').
19−-- combinators; a stream can then be supplied to the combined fold and it would
17+-- Unlike the standard left folds, 'Fold's can terminate at any point e.g. the
20−-- distribute the input to constituent folds according to the composition. For
18+-- 'head' fold would terminate immediately after returning the head element.
21−-- example, an applicative composition distributes the same input to the
22−-- constituent folds and then combines the resulting fold outputs. Similarly,
23−-- a partitioning combinator divides the input among constituent folds.
24--
19--
25−-- = Monoids
20+-- 'Fold's can be combined efficiently using combinators provided in this
21+-- module; a stream supplied to the combined fold is provided to the
22+-- constituent folds according to the behavior of the combinator. For example,
23+-- the 'tee' combinator distributes the input stream to two folds and then
24+-- combines the resulting fold outputs. Similarly, a 'partition' combinator
25+-- divides the input among constituent folds.
26--
26--
27−-- Monoids allow modular folding in general. Most of the folds in this module
27+-- = Accumulators and Terminating Folds
28−-- can be expressed using 'mconcat' and a suitable 'Monoid'. Instead of writing
29−-- folds we can write Monoids instead and turn them into folds.
30--
28--
31−-- = Performance Notes
29+-- Folds in this module can be classified in two categories viz. accumulators
30+-- and terminating folds. Accumulators do not have a terminating condition,
31+-- they run forever and consume the entire stream, for example the 'length'
32+-- fold. Terminating folds have a terminating condition and can terminate
33+-- without consuming the entire stream, for example, the 'head' fold.
32--
34--
33−-- 'Fold' representation is more efficient than using streams when splitting
35+-- = Monoids
34−-- streams. @Fold m a b@ can be considered roughly equivalent to a fold action
35−-- @m b -> t m a -> m b@ (where @t@ is a stream type and @m@ is a 'Monad').
36−-- Instead of using a 'Fold' type one could just use a fold action of the shape
37−-- @m b -> t m a -> m b@ for folding streams. However, multiple such actions
38−-- cannot be composed into a single fold function in an efficient manner.
39−-- Using the 'Fold' type we can efficiently split the stream across mutliple
40−-- folds because it allows the compiler to perform stream fusion optimizations.
41--
36--
42−-- On the other hand, transformation operations (e.g. 'Streamly.Prelude.map')
37+-- Monoids allow generalized, modular folding. The accumulators in this module
43−-- on stream types can be as efficient as transformations on 'Fold' (e.g.
38+-- can be expressed using 'mconcat' and a suitable 'Monoid'. Instead of
44−-- 'Streamly.Internal.Data.Fold.lmap').
39+-- writing folds we can write Monoids and turn them into folds.
45--
40--
46−-- = Left folds vs Right Folds
41+-- = Performance Notes
47--
42--
48−-- The folds in this module are left folds, therefore, even partial folds, e.g.
43+-- 'Streamly.Prelude' module provides fold functions to directly fold streams
49−-- @head@ in this module, would drain the whole stream. On the other hand, the
44+-- e.g. Streamly.Prelude/'Streamly.Prelude.sum' serves the same purpose as
50−-- partial folds in "Streamly.Prelude" module are lazy right folds and would
45+-- Fold/'sum'. However, the functions in Streamly.Prelude cannot be
51−-- terminate as soon as the result is determined. However, the folds in this
46+-- efficiently combined together e.g. we cannot drive the input stream through
52−-- module can be composed but the folds in "Streamly.Prelude" cannot be
47+-- @sum@ and @length@ fold functions simultaneously. Using the 'Fold' type we
53−-- composed.
48+-- can efficiently split the stream across mutliple folds because it allows the
49+-- compiler to perform stream fusion optimizations.
54--
50--
55-- = Programmer Notes
51-- = Programmer Notes
56--
52--
57−-- > import qualified Streamly.Data.Fold as FL
53+-- > import qualified Streamly.Data.Fold as Fold
58--
54--
59-- More, not yet exposed, fold combinators can be found in
55-- More, not yet exposed, fold combinators can be found in
60-- "Streamly.Internal.Data.Fold".
56-- "Streamly.Internal.Data.Fold".
61
57
62−-- IMPORTANT: keep the signatures consistent with the folds in Streamly.Prelude
63−
64module Streamly.Data.Fold
58module Streamly.Data.Fold
65 (
59 (
66 -- * Fold Type
60 -- * Fold Type
@@ -73,10 +67,13 @@ module Streamly.Data.Fold
73
67
74 Fold -- (..)
68 Fold -- (..)
75
69
76− -- , tail
70+ -- * Accumulators
77− -- , init
71+ -- ** Monoids
72+ , mconcat
73+ , foldMap
74+ , foldMapM
78
75
79− -- ** Full Folds
76+ -- ** Reducers
80 , drain
77 , drain
81 , drainBy
78 , drainBy
82 , last
79 , last
@@ -87,24 +84,18 @@ module Streamly.Data.Fold
87 , maximum
84 , maximum
88 , minimumBy
85 , minimumBy
89 , minimum
86 , minimum
90− -- , the
91 , mean
87 , mean
92 , variance
88 , variance
93 , stdDev
89 , stdDev
94
90
95− -- ** Full Folds (Monoidal)
91+ -- ** Collectors
96− , mconcat
97− , foldMap
98− , foldMapM
99−
100− -- ** Full Folds (To Containers)
101 -- | Avoid using these folds in scalable or performance critical
92 -- | Avoid using these folds in scalable or performance critical
102 -- applications, they buffer all the input in GC memory which can be
93 -- applications, they buffer all the input in GC memory which can be
103 -- detrimental to performance if the input is large.
94 -- detrimental to performance if the input is large.
104
95
105 , toList
96 , toList
106
97
107− -- ** Partial Folds
98+ -- * Terminating Folds
108 -- , drainN
99 -- , drainN
109 -- , drainWhile
100 -- , drainWhile
110 -- , lastN
101 -- , lastN
@@ -120,13 +111,12 @@ module Streamly.Data.Fold
120 , null
111 , null
121 , elem
112 , elem
122 , notElem
113 , notElem
123− -- XXX these are slower than right folds even when full input is used
124 , all
114 , all
125 , any
115 , any
126 , and
116 , and
127 , or
117 , or
128
118
129− -- * Transformations
119+ -- * Output Transformations
130 -- | Unlike stream producer types (e.g. @SerialT m a@) which have only
120 -- | Unlike stream producer types (e.g. @SerialT m a@) which have only
131 -- output side, folds have an input side as well as an output side. In the
121 -- output side, folds have an input side as well as an output side. In the
132 -- type @Fold m a b@, the input type is @a@ and the output type is @b@.
122 -- type @Fold m a b@, the input type is @a@ and the output type is @b@.
@@ -136,19 +126,21 @@ module Streamly.Data.Fold
136 -- >>> S.fold (fmap show FL.sum) (S.enumerateFromTo 1 100)
126 -- >>> S.fold (fmap show FL.sum) (S.enumerateFromTo 1 100)
137 -- "5050"
127 -- "5050"
138 --
128 --
139− -- However, the input side or contravariant transformations are more
129+ -- Note: Output transformations are also known as covariant
140− -- interesting for folds. The following sections describe the input
130+ -- transformations.
141− -- transformation operations on a fold. The names of the operations are
142− -- consistent with their covariant counterparts in "Streamly.Prelude", the
143− -- only difference is that they are prefixed with 'l' which stands for
144− -- 'left' assuming left side is the input side, notice that in @Fold m a b@
145− -- the type variable @a@ is on the left side.
146−
147− -- ** Covariant Operations
148 , sequence
131 , sequence
149 , mapM
132 , mapM
150
133
151 {-
134 {-
135+ -- * Input Transformations
136+ -- The input side transformations are more interesting for folds. The
137+ -- following sections describe the input transformation operations on a
138+ -- fold. The names and signatures of the operations are consistent with
139+ -- corresponding operations in "Streamly.Prelude".
140+ --
141+ -- Note: Input transformations are also known as contravariant
142+ -- transformations.
143+
152 -- ** Mapping
144 -- ** Mapping
153 --, transform
145 --, transform
154 -- , lmap
146 -- , lmap
@@ -180,12 +172,9 @@ module Streamly.Data.Fold
180 -}
172 -}
181
173
182 {-
174 {-
183− -- * Parsing
184 -- ** Trimming
175 -- ** Trimming
185 , ltake
176 , ltake
186− -- , lrunFor -- time
177+ -- takeByTime
187− , ltakeWhile
188− , ltakeWhileM
189 , ldrop
178 , ldrop
190 , ldropWhile
179 , ldropWhile
191 , ldropWhileM
180 , ldropWhileM
@@ -258,7 +247,7 @@ module Streamly.Data.Fold
258 -- , unzipWith
247 -- , unzipWith
259 -- , unzipWithM
248 -- , unzipWithM
260
249
261− -- -- * Nested Folds
250+ -- -- * Nesting
262 -- , concatMap
251 -- , concatMap
263 -- , chunksOf
252 -- , chunksOf
264 -- , duplicate -- experimental
253 -- , duplicate -- experimental