@@ -1,3 +1,4 @@
1+{-# LANGUAGE CPP #-}
12-- |
23-- Module : Streamly.Data.Stream
34-- Copyright : (c) 2017 Composewell Technologies
@@ -7,87 +8,29 @@
78-- Stability : released
89-- Portability : GHC
910--
10−-- To run examples in this module:
11+-- Fast, composable stream producers with ability to terminate, supporting
12+-- stream fusion.
1113--
12−-- >>> import qualified Streamly.Data.Fold as Fold
13−-- >>> import qualified Streamly.Data.Stream as Stream
14+-- Please refer to "Streamly.Internal.Data.Stream" for more functions that have
15+-- not yet been released.
1416--
15−-- We will add some more imports in the examples as needed.
16−--
17−-- For effectful streams we will use the following IO action:
18−--
19−-- >>> effect n = print n >> return n
20−--
21−-- = Overview
22−--
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.
27−--
28−-- == Console Echo Example
29−--
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.
35−--
36−-- >>> import Data.Function ((&))
37−--
38−-- >>> :{
39−-- echo =
40−-- Stream.repeatM getLine -- Stream IO String
41−-- & Stream.mapM putStrLn -- Stream IO ()
42−-- & Stream.fold Fold.drain -- IO ()
43−-- :}
44−--
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@
47−-- loop.
48−--
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.
53−--
54−-- == Performance Notes
55−--
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.
62−--
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.
69−--
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.
76−--
77−-- 'Stream' and 'StreamK' types can be interconverted.
78−--
79−-- == Useful Idioms
80−--
81−-- >>> fromListM = Stream.sequence . Stream.fromList
82−-- >>> fromIndices f = fmap f $ Stream.enumerateFrom 0
83−--
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>
8618-- repository for many more real world examples of stream programming.
87−--
19+
8820module Streamly.Data.Stream
8921 (
22+ -- * Setup
23+ -- | To execute the code examples provided in this module in ghci, please
24+ -- run the following commands first.
25+ --
26+ -- $setup
27+
28+ -- * Overview
29+ -- $overview
30+
31+ -- * The Stream Type
9032 Stream
33+
9134 -- * Construction
9235 -- | Functions ending in the general shape @b -> Stream m a@.
9336 --
@@ -522,3 +465,68 @@ import Prelude
522465 notElem, maximum, minimum, head, last, tail, length, null,
523466 reverse, iterate, init, and, or, lookup, foldr1, (!!),
524467 scanl, scanl1, repeat, replicate, concatMap, span)
468+
469+#include "DocTestDataStream.hs"
470+
471+-- $overview
472+--
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.
477+--
478+-- == Console Echo Example
479+--
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.
485+--
486+-- >>> import Data.Function ((&))
487+--
488+-- >>> :{
489+-- echo =
490+-- Stream.repeatM getLine -- Stream IO String
491+-- & Stream.mapM putStrLn -- Stream IO ()
492+-- & Stream.fold Fold.drain -- IO ()
493+-- :}
494+--
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@
497+-- loop.
498+--
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.
503+--
504+-- == Performance Notes
505+--
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.
512+--
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.
519+--
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.
526+--
527+-- 'Stream' and 'StreamK' types can be interconverted.
528+--
529+-- == Useful Idioms
530+--
531+-- >>> fromListM = Stream.sequence . Stream.fromList
532+-- >>> fromIndices f = fmap f $ Stream.enumerateFrom 0