@@ -45,7 +45,10 @@ Why use streamly?
4545 * _Generality_: Unifies functionality provided by several disparate packages
4646 (streaming, concurrency, list transformer, logic programming, reactive
4747 programming) in a concise API.
48− * _Performance_: Streamly is designed for high performance. See
48+ * _Performance_: Streamly is designed for high performance. It employs stream
49+ fusion optimizations for best possible performance. Serial peformance is
50+ equivalent to the venerable `vector` library in most cases and even better
51+ in some cases. Concurrent performance is unbeatable. See
4952 [streaming-benchmarks](https://github.com/composewell/streaming-benchmarks)
5053 for a comparison of popular streaming libraries on micro-benchmarks.
5154
@@ -63,16 +66,17 @@ For more information on streamly, see:
6366
6467## Streaming Pipelines
6568
66−Unlike `pipes` or `conduit` and like `vector` and `streaming` `streamly`
69+Unlike `pipes` or `conduit` and like `vector` and `streaming`, `streamly`
6770composes stream data instead of stream processors (functions). A stream is
6871just like a list and is explicitly passed around to functions that process the
6972stream. Therefore, no special operator is needed to join stages in a streaming
70−pipeline, just the standard forward (`$`) or reverse (`&`) function application
71−operator is enough. Combinators are provided in `Streamly.Prelude` to
72−transform or fold streams.
73+pipeline, just the standard function application (`$`) or reverse function
74+application (`&`) operator is enough. Combinators are provided in
75+`Streamly.Prelude` to transform or fold streams.
7376
74−This snippet reads numbers from stdin, prints the squares of even numbers and
75−exits if an even number more than 9 is entered.
77+The following snippet provides a simple stream composition example that reads
78+numbers from stdin, prints the squares of even numbers and exits if an even
79+number more than 9 is entered.
7680
7781```haskell
7882import Streamly
@@ -92,7 +96,8 @@ main = runStream $
9296
9397Monadic construction and generation functions e.g. `consM`, `unfoldrM`,
9498`replicateM`, `repeatM`, `iterateM` and `fromFoldableM` etc. work concurrently
95−when used with appropriate stream type combinator.
99+when used with appropriate stream type combinator (e.g. `asyncly`, `aheadly` or
100+`parallely`).
96101
97102The following code finishes in 3 seconds (6 seconds when serial):
98103
@@ -113,8 +118,8 @@ runStream $ asyncly $ S.replicateM 10 $ p 10
113118
114119## Concurrent Streaming Pipelines
115120
116−Use `|&` or `|$` to apply stream processing functions concurrently. In the
117−following example "hello" is printed every second, if you use `&` instead of
121+Use `|&` or `|$` to apply stream processing functions concurrently. The
122+following example prints a "hello" every second; if you use `&` instead of
118123`|&` you will see that the delay doubles to 2 seconds instead because of serial
119124application.
120125
@@ -126,7 +131,7 @@ main = runStream $
126131
127132## Mapping Concurrently
128133
129−We can use `mapM` or `sequence` concurrently on a stream.
134+We can use `mapM` or `sequence` functions concurrently on a stream.
130135
131136```
132137> let p n = threadDelay (n * 1000000) >> return n
@@ -136,8 +141,8 @@ We can use `mapM` or `sequence` concurrently on a stream.
136141## Serial and Concurrent Merging
137142
138143Semigroup and Monoid instances can be used to fold streams serially or
139−concurrently. In the following example we are composing ten actions in the
140−stream each with a delay of 1 to 10 seconds, respectively. Since all the
144+concurrently. In the following example we compose ten actions in the
145+stream, each with a delay of 1 to 10 seconds, respectively. Since all the
141146actions are concurrent we see one output printed every second:
142147
143148``` haskell
@@ -146,11 +151,11 @@ import qualified Streamly.Prelude as S
146151import Control.Concurrent (threadDelay)
147152
148153main = S.toList $ parallely $ foldMap delay [1..10]
149− where delay n = S.once $ threadDelay (n * 1000000) >> print n
154+ where delay n = S.yieldM $ threadDelay (n * 1000000) >> print n
150155```
151156
152−Streams can be combined together in many ways. We are providing some examples
153−below, see the tutorial for more ways. We will use the following `delay`
157+Streams can be combined together in many ways. We provide some examples
158+below, see the tutorial for more ways. We use the following `delay`
154159function in the examples to demonstrate the concurrency aspects:
155160
156161``` haskell
@@ -158,7 +163,7 @@ import Streamly
158163import qualified Streamly.Prelude as S
159164import Control.Concurrent
160165
161−delay n = S.once $ do
166+delay n = S.yieldM $ do
162167 threadDelay (n * 1000000)
163168 tid <- myThreadId
164169 putStrLn (show tid ++ ": Delay " ++ show n)
@@ -196,7 +201,7 @@ import qualified Streamly.Prelude as S
196201loops = do
197202 x <- S.fromFoldable [1,2]
198203 y <- S.fromFoldable [3,4]
199− S.once $ putStrLn $ show (x, y)
204+ S.yieldM $ putStrLn $ show (x, y)
200205
201206main = runStream loops
202207```
@@ -209,20 +214,32 @@ main = runStream loops
209214
210215## Concurrent Nested Loops
211216
212−To run the above code with demand-driven depth first concurrency i.e. each
213−iteration in the loops can run concurrently depending on the consumer rate:
217+To run the above code with, lookahead style concurrency i.e. each iteration in
218+the loop can run run concurrently by but the results are presented in the same
219+order as serial execution:
220+
221+``` haskell
222+main = runStream $ aheadly $ loops
223+```
224+
225+To run it with depth first concurrency yielding results asynchronously in the
226+same order as they become available (deep async composition):
214227
215228``` haskell
216229main = runStream $ asyncly $ loops
217230```
218231
219−To run it with demand driven breadth first concurrency:
232+To run it with breadth first concurrency and yeilding results asynchronously
233+(wide async composition):
220234
221235``` haskell
222236main = runStream $ wAsyncly $ loops
223237```
224238
225−To run it with strict concurrency irrespective of demand:
239+The above streams provide lazy/demand-driven concurrency which is automatically
240+scaled as per demand and is controlled/bounded so that it can be used on
241+infinite streams. The following combinator provides strict, unbounded
242+concurrency irrespective of demand:
226243
227244``` haskell
228245main = runStream $ parallely $ loops
@@ -266,8 +283,8 @@ import qualified Streamly.Prelude as S
266283
267284main = runStream $ aheadly $ getCurrentDir >>= readdir
268285 where readdir d = do
269− (dirs, files) <- S.once $ listDir d
270− S.once $ mapM_ putStrLn $ map show files
286+ (dirs, files) <- S.yieldM $ listDir d
287+ S.yieldM $ mapM_ putStrLn $ map show files
271288 -- read the subdirs concurrently, (<>) is concurrent
272289 foldMap readdir dirs
273290```