on master help sign in
update fold and unfold documentation
f254008Harendra Kumar
src/Streamly/Data/Fold.hs+41−28
@@ -2,45 +2,58 @@
2-- Module : Streamly.Data.Fold
2-- Module : Streamly.Data.Fold
3-- Copyright : (c) 2019 Composewell Technologies
3-- Copyright : (c) 2019 Composewell Technologies
4-- License : BSD3
4-- License : BSD3
5−-- Maintainer : harendra@composewell.com
5+-- Maintainer : streamly@composewell.com
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−-- A left fold consumes a stream and reduces it to a single value. The fold
10+-- input stream and combines it with a single final value often called an
10−-- operations in "Streamly.Prelude" cannot be combined such that multiple of
11+-- accumulator, returning the resulting output accumulator. Values from a
11−-- them can run on the same stream. This module provides a 'Fold' type that
12+-- stream can be /pushed/ to the fold and consumed one at a time. It can also
12−-- represents a left fold. Multiple such folds can be combined using
13+-- be called a consumer of stream or a sink. It is a data representation of
14+-- the standard 'Streamly.Prelude.foldl'' function. A 'Fold' can be turned
15+-- into an effect (@m b@) using 'Streamly.Prelude.fold' by supplying it the
16+-- input stream.
17+--
18+-- Using this representation multiple folds can be combined efficiently using
13-- combinators; a stream can then be supplied to the combined fold and it would
19-- combinators; a stream can then be supplied to the combined fold and it would
14−-- distribute the input to constituent folds according to the composition.
20+-- distribute the input to constituent folds according to the composition. For
15−-- For example, an applicative composition distributes the same input to
21+-- example, an applicative composition distributes the same input to the
16−-- the constituent folds and then combines the fold outputs. Similarly, a
22+-- constituent folds and then combines the resulting fold outputs. Similarly,
17−-- partitioning combinator can divide the input among constituent folds.
23+-- a partitioning combinator divides the input among constituent folds.
18−-- All the combinators in this module are of true streaming nature, stream
19−-- elements are not unnecessarily buffered in memory, guaranteeing a constant
20−-- memory consumption.
21--
24--
22−-- Consider this module as the consumer side dual of the "Streamly.Prelude"
25+-- = Performance Notes
23−-- module. "Streamly.Prelude" provides combinators that can combine stream
24−-- sources in interesting ways whereas this module provides combinators that
25−-- combine stream consumers in interesting ways. In other words,
26−-- "Streamly.Prelude" provides stream merging capabilities while
27−-- "Streamly.Internal.Data.Fold" provides stream splitting capabilities.
28--
26--
29−-- > import qualified Streamly.Internal.Data.Fold as FL
27+-- 'Fold' representation is more efficient than using streams when splitting
30−
28+-- streams. @Fold m a b@ can be considered roughly equivalent to a fold action
31−-- Also see the "Streamly.Internal.Data.Sink" module that provides specialized left folds
29+-- @m b -> t m a -> m b@ (where @t@ is a stream type and @m@ is a 'Monad').
32−-- that discard the outputs.
30+-- Instead of using a 'Fold' type one could just use a fold action of the shape
31+-- @m b -> t m a -> m b@ for folding streams. However, multiple such actions
32+-- cannot be composed into a single fold function in an efficient manner.
33+-- Using the 'Fold' type we can efficiently split the stream across mutliple
34+-- folds because it allows the compiler to perform stream fusion optimizations.
35+--
36+-- On the other hand, transformation operations (e.g. 'Streamly.Prelude.map')
37+-- on stream types can be as efficient as transformations on 'Fold' (e.g.
38+-- 'Streamly.Internal.Data.Fold.lmap').
33--
39--
40+-- = Programmer Notes
41+--
42+-- > import qualified Streamly.Data.Fold as FL
43+--
44+-- More, not yet exposed, fold combinators can be found in
45+-- "Streamly.Internal.Data.Fold".
46+
34-- IMPORTANT: keep the signatures consistent with the folds in Streamly.Prelude
47-- IMPORTANT: keep the signatures consistent with the folds in Streamly.Prelude
35
48
36module Streamly.Data.Fold
49module Streamly.Data.Fold
37 (
50 (
38 -- * Fold Type
51 -- * Fold Type
39 -- |
52 -- |
40− -- A 'Fold' can be run over a stream using the 'runFold' combinator in
53+ -- A 'Fold' can be run over a stream using the 'Streamly.Prelude.fold'
41− -- "Streamly.Prelude":
54+ -- combinator:
42 --
55 --
43− -- >>> S.runFold FL.sum (S.enumerateFromTo 1 100)
56+ -- >>> S.fold FL.sum (S.enumerateFromTo 1 100)
44 -- 5050
57 -- 5050
45
58
46 Fold -- (..)
59 Fold -- (..)
@@ -105,7 +118,7 @@ module Streamly.Data.Fold
105 -- Transformations can be applied either on the input side or on the output
118 -- Transformations can be applied either on the input side or on the output
106 -- side. The 'Functor' instance of a fold maps on the output of the fold:
119 -- side. The 'Functor' instance of a fold maps on the output of the fold:
107 --
120 --
108− -- >>> S.runFold (fmap show FL.sum) (S.enumerateFromTo 1 100)
121+ -- >>> S.fold (fmap show FL.sum) (S.enumerateFromTo 1 100)
109 -- "5050"
122 -- "5050"
110 --
123 --
111 -- However, the input side or contravariant transformations are more
124 -- However, the input side or contravariant transformations are more
@@ -181,7 +194,7 @@ module Streamly.Data.Fold
181 -- stream twice:
194 -- stream twice:
182 --
195 --
183 -- >>> let avg = (/) <$> FL.sum <*> fmap fromIntegral FL.length
196 -- >>> let avg = (/) <$> FL.sum <*> fmap fromIntegral FL.length
184− -- >>> S.runFold avg (S.enumerateFromTo 1.0 100.0)
197+ -- >>> S.fold avg (S.enumerateFromTo 1.0 100.0)
185 -- 50.5
198 -- 50.5
186 --
199 --
187 -- The 'Semigroup' and 'Monoid' instances of a distributing fold distribute
200 -- The 'Semigroup' and 'Monoid' instances of a distributing fold distribute
@@ -189,7 +202,7 @@ module Streamly.Data.Fold
189 -- Semigroup instances of the output types:
202 -- Semigroup instances of the output types:
190 --
203 --
191 -- >>> import Data.Monoid (Sum)
204 -- >>> import Data.Monoid (Sum)
192− -- >>> S.runFold (FL.head <> FL.last) (fmap Sum $ S.enumerateFromTo 1.0 100.0)
205+ -- >>> S.fold (FL.head <> FL.last) (fmap Sum $ S.enumerateFromTo 1.0 100.0)
193 -- Just (Sum {getSum = 101.0})
206 -- Just (Sum {getSum = 101.0})
194 --
207 --
195 -- The 'Num', 'Floating', and 'Fractional' instances work in the same way.
208 -- The 'Num', 'Floating', and 'Fractional' instances work in the same way.
src/Streamly/Data/Unfold.hs+9−10
@@ -19,16 +19,18 @@
19-- Portability : GHC
19-- Portability : GHC
20--
20--
21-- 'Unfold' type represents an effectful action that generates a stream of
21-- 'Unfold' type represents an effectful action that generates a stream of
22−-- values from a single starting value often called a seed value. It can also
22+-- values from a single starting value often called a seed value. Values can be
23+-- generated and /pulled/ from the 'Unfold' one at a time. It can also be
23−-- be called a producer or a source of stream. It is a data representation of
24+-- called a producer or a source of stream. It is a data representation of the
24−-- the standard 'S.unfoldr' function. An 'Unfold' can be converted into a
25+-- standard 'S.unfoldr' function. An 'Unfold' can be converted into a stream
25−-- stream using 'S.unfold' by supplying the seed.
26+-- type using 'S.unfold' by supplying the seed.
26--
27--
27-- = Performance Notes
28-- = Performance Notes
28--
29--
30+-- 'Unfold' representation is more efficient than using streams when combining
29−-- 'Unfold' type allows multiple unfold actions to be composed into a single
31+-- streams. 'Unfold' type allows multiple unfold actions to be composed into a
30−-- unfold function in an efficient manner by enabling the compiler to perform
32+-- single unfold function in an efficient manner by enabling the compiler to
31−-- stream fusion optimization.
33+-- perform stream fusion optimization.
32-- @Unfold m a b@ can be considered roughly equivalent to an action @a -> t m
34-- @Unfold m a b@ can be considered roughly equivalent to an action @a -> t m
33-- b@ (where @t@ is a stream type). Instead of using an 'Unfold' one could just
35-- b@ (where @t@ is a stream type). Instead of using an 'Unfold' one could just
34-- use a function of the shape @a -> t m b@. However, working with stream types
36-- use a function of the shape @a -> t m b@. However, working with stream types
@@ -68,6 +70,3 @@ where
68
70
69import Prelude hiding (concat, map, takeWhile, take, filter, const)
71import Prelude hiding (concat, map, takeWhile, take, filter, const)
70import Streamly.Internal.Data.Unfold
72import Streamly.Internal.Data.Unfold
71−
72−-- imported for documentation links
73−import qualified Streamly.Prelude as S