@@ -1,3 +1,4 @@
2-- Module : Streamly.Data.Stream
3-- Module : Streamly.Data.Stream
3-- Copyright : (c) 2017 Composewell Technologies
4-- Copyright : (c) 2017 Composewell Technologies
@@ -7,87 +8,29 @@
7-- Stability : released
8-- Stability : released
8-- Portability : GHC
9-- Portability : GHC
10−-- To run examples in this module:
11+-- Fast, composable stream producers with ability to terminate, supporting
12−-- >>> import qualified Streamly.Data.Fold as Fold
14+-- Please refer to "Streamly.Internal.Data.Stream" for more functions that have
13−-- >>> import qualified Streamly.Data.Stream as Stream
15+-- not yet been released.
15−-- We will add some more imports in the examples as needed.
17−-- For effectful streams we will use the following IO action:
19−-- >>> effect n = print n >> return n
23−-- Streamly is a framework for modular data flow based programming and
24−-- declarative concurrency. Powerful stream fusion framework in streamly
25−-- allows high performance combinatorial programming even when using byte level
26−-- streams. Streamly API is similar to Haskell lists.
28−-- == Console Echo Example
30−-- In the following example, 'repeatM' generates an infinite stream of 'String'
31−-- by repeatedly performing the 'getLine' IO action. 'mapM' then applies
32−-- 'putStrLn' on each element in the stream converting it to stream of '()'.
33−-- Finally, 'drain' folds the stream to IO discarding the () values, thus
34−-- producing only effects.
36−-- >>> import Data.Function ((&))
40−-- Stream.repeatM getLine -- Stream IO String
41−-- & Stream.mapM putStrLn -- Stream IO ()
42−-- & Stream.fold Fold.drain -- IO ()
45−-- This is a console echo program. It is an example of a declarative loop
46−-- written using streaming combinators. Compare it with an imperative @while@
49−-- Hopefully, this gives you an idea how we can program declaratively by
50−-- representing loops using streams. In this module, you can find all
51−-- "Data.List" like functions and many more powerful combinators to perform
52−-- common programming tasks.
54−-- == Performance Notes
56−-- The 'Stream' type represents a stream by composing state as data which
57−-- enables stream fusion. Stream fusion generates a tight loop without any
58−-- constructor allocations between the stages, providing C like performance for
59−-- the loop. Stream fusion works when multiple functions are combined in a
60−-- pipeline statically. Therefore, the operations in this module must be
61−-- inlined and must not be used recursively to allow for stream fusion.
63−-- Using the 'Stream' type binary stream construction operations like 'cons',
64−-- 'append' etc. degrade quadratically (O(n^2)) when combined many times. If
65−-- you need to combine these operations, say more than 50 times in a single
66−-- loop, then you should use the continuation style stream type 'StreamK'
67−-- instead. Also, if you need to use these operations in a recursive loop you
68−-- should use 'StreamK' instead.
70−-- The 'StreamK' type represents a stream by composing function calls,
71−-- therefore, a function call overhead is incurred at each composition. It is
72−-- quite fast in general but may be a few times slower than a fused stream.
73−-- However, it allows for scalable dynamic composition and control flow
74−-- manipulation. Using the 'StreamK' type binary operations like 'cons' and
75−-- 'append' provide linear (O(n)) performance.
77−-- 'Stream' and 'StreamK' types can be interconverted.
81−-- >>> fromListM = Stream.sequence . Stream.fromList
82−-- >>> fromIndices f = fmap f $ Stream.enumerateFrom 0
84−-- Also see "Streamly.Internal.Data.Stream" module for many more @Pre-release@
85−-- combinators. See the <https://github.com/composewell/streamly-examples>
17+-- Checkout the <https://github.com/composewell/streamly-examples>
86-- repository for many more real world examples of stream programming.
18-- repository for many more real world examples of stream programming.
88module Streamly.Data.Stream
20module Streamly.Data.Stream
23+ -- | To execute the code examples provided in this module in ghci, please
24+ -- run the following commands first.
91 -- * Construction
34 -- * Construction
92 -- | Functions ending in the general shape @b -> Stream m a@.
35 -- | Functions ending in the general shape @b -> Stream m a@.
@@ -522,3 +465,68 @@ import Prelude
522 notElem, maximum, minimum, head, last, tail, length, null,
465 notElem, maximum, minimum, head, last, tail, length, null,
523 reverse, iterate, init, and, or, lookup, foldr1, (!!),
466 reverse, iterate, init, and, or, lookup, foldr1, (!!),
524 scanl, scanl1, repeat, replicate, concatMap, span)
467 scanl, scanl1, repeat, replicate, concatMap, span)
469+#include "DocTestDataStream.hs"
473+-- Streamly is a framework for modular data flow based programming and
474+-- declarative concurrency. Powerful stream fusion framework in streamly
475+-- allows high performance combinatorial programming even when using byte level
476+-- streams. Streamly API is similar to Haskell lists.
478+-- == Console Echo Example
480+-- In the following example, 'repeatM' generates an infinite stream of 'String'
481+-- by repeatedly performing the 'getLine' IO action. 'mapM' then applies
482+-- 'putStrLn' on each element in the stream converting it to stream of '()'.
483+-- Finally, 'drain' folds the stream to IO discarding the () values, thus
484+-- producing only effects.
486+-- >>> import Data.Function ((&))
490+-- Stream.repeatM getLine -- Stream IO String
491+-- & Stream.mapM putStrLn -- Stream IO ()
492+-- & Stream.fold Fold.drain -- IO ()
495+-- This is a console echo program. It is an example of a declarative loop
496+-- written using streaming combinators. Compare it with an imperative @while@
499+-- Hopefully, this gives you an idea how we can program declaratively by
500+-- representing loops using streams. In this module, you can find all
501+-- "Data.List" like functions and many more powerful combinators to perform
502+-- common programming tasks.
504+-- == Performance Notes
506+-- The 'Stream' type represents a stream by composing state as data which
507+-- enables stream fusion. Stream fusion generates a tight loop without any
508+-- constructor allocations between the stages, providing C like performance for
509+-- the loop. Stream fusion works when multiple functions are combined in a
510+-- pipeline statically. Therefore, the operations in this module must be
511+-- inlined and must not be used recursively to allow for stream fusion.
513+-- Using the 'Stream' type binary stream construction operations like 'cons',
514+-- 'append' etc. degrade quadratically (O(n^2)) when combined many times. If
515+-- you need to combine these operations, say more than 50 times in a single
516+-- loop, then you should use the continuation style stream type 'StreamK'
517+-- instead. Also, if you need to use these operations in a recursive loop you
518+-- should use 'StreamK' instead.
520+-- The 'StreamK' type represents a stream by composing function calls,
521+-- therefore, a function call overhead is incurred at each composition. It is
522+-- quite fast in general but may be a few times slower than a fused stream.
523+-- However, it allows for scalable dynamic composition and control flow
524+-- manipulation. Using the 'StreamK' type binary operations like 'cons' and
525+-- 'append' provide linear (O(n)) performance.
527+-- 'Stream' and 'StreamK' types can be interconverted.
531+-- >>> fromListM = Stream.sequence . Stream.fromList
532+-- >>> fromIndices f = fmap f $ Stream.enumerateFrom 0