@@ -79,13 +79,40 @@ module Streamly
7979 MonadAsync
8080
8181 -- * Stream transformers
82+ -- | A stream represents a sequence of pure or effectful actions. The
83+ -- `cons` and `consM` operations and the corresponding operators '.:' and
84+ -- '|:' can be used to join pure values or effectful actions in a sequence.
85+ -- The effects in the stream can be executed in many different ways
86+ -- depending on the type of stream. In other words, the behavior of 'consM'
87+ -- depends on the type of the stream.
88+ --
89+ -- There are three high level categories of streams, /spatially ordered/
90+ -- streams, /speculative/ streams and /time ordered/ streams. Spatially
91+ -- ordered streams, 'SerialT' and 'WSerialT', execute the effects in serial
92+ -- order i.e. one at a time and present the outputs of those effects to the
93+ -- consumer in the same order. Speculative streams, 'AheadT', may execute
94+ -- many effects concurrently but present the outputs to the consumer in the
95+ -- specified spatial order. Time ordered streams, 'AsyncT', 'WAsyncT' and
96+ -- 'ParallelT', may execute many effects concurrently and present the
97+ -- outputs of those effects to the consumer in time order i.e. as soon as
98+ -- the output is generated.
99+ --
100+ -- We described above how the effects in a sequence are executed for
101+ -- different types of streams. The behvavior of the 'Semigroup' and 'Monad'
102+ -- instances follow the behavior of 'consM'. Stream generation operations
103+ -- like 'repeatM' also execute the effects differently for different
104+ -- streams, providing a concurrent generation capability when used with
105+ -- stream types that execute effects concurrently. Similarly, effectful
106+ -- transformation operations like 'mapM' also execute the transforming
107+ -- effects differently for different types of streams.
108+
82109 -- ** Serial Streams
83110 -- $serial
84111 , SerialT
85112 , WSerialT
86113
87114 -- ** Speculative Streams
88− -- $lookahead
115+ -- $ahead
89116 , AheadT
90117
91118 -- ** Asynchronous Streams
@@ -415,21 +442,93 @@ forEachWith = P.forEachWith
415442
416443-- $serial
417444--
418−-- Serial streams compose serially or non-concurrently. In a composed stream,
419−-- each action is executed only after the previous action has finished. The two
420−-- serial stream types 'SerialT' and 'WSerialT' differ in how they traverse the
421−-- streams in a 'Semigroup' or 'Monad' composition.
445+-- When a stream consumer demands an element from a serial stream constructed
446+-- as @a \`consM` b \`consM` ... nil@, the action @a@ at the head of the stream
447+-- sequence is executed and the result is supplied to the consumer. When the
448+-- next element is demanded, the action @b@ is executed and its result is
449+-- supplied. Thus, the effects are performed and results are consumed strictly
450+-- in a serial order. Serial streams can be considered as /spatially ordered/
451+-- streams as the order of execution and consumption is the same as the spatial
452+-- order in which the actions are composed by the programmer.
453+--
454+-- Serial streams enforce the side effects as well as the results of the
455+-- actions to be in the same order in which the actions are added to the
456+-- stream. Therefore, the semigroup operation for serial streams is not
457+-- commutative:
458+--
459+-- @
460+-- a <> b is not the same as b <> a
461+-- @
462+--
463+-- There are two serial stream types 'SerialT' and 'WSerialT'. The stream
464+-- evaluation of both the variants works in the same way as described above,
465+-- they differ only in the 'Semigroup' and 'Monad' implementaitons.
466+
467+-- $ahead
468+--
469+-- When a stream consumer demands an element from a speculative stream
470+-- constructed as @a \`consM` b \`consM` ... nil@, the action @a@ at the head
471+-- of the stream is executed and the output of the action is supplied to the
472+-- consumer. However, in addition to the action at the head multiple actions
473+-- following it may also be executed concurrently and the results buffered.
474+-- When the next element is demanded it may be served from the buffer and we
475+-- may execute the next action in the sequence to keep the buffer adequately
476+-- filled. Thus, the actions are executed concurrently but results consumed in
477+-- serial order just like serial streams. `consM` can be used to fold an
478+-- infinite lazy container of effects, as the number of concurrent executions
479+-- is limited.
480+--
481+-- Similar to 'consM', the monadic stream generation (e.g. replicateM) and
482+-- transformation operations (e.g. mapM) on speculative streams can execute
483+-- multiple effects concurrently in a speculative manner.
484+--
485+-- How many effects can be executed concurrently and how many results can be
486+-- buffered are controlled by 'maxThreads' and 'maxBuffer' combinators
487+-- respectively. The actual number of concurrent threads is adjusted according
488+-- to the rate at which the consumer is consuming the stream. It may even
489+-- execute actions serially in a single thread if that is enough to match the
490+-- consumer's speed.
491+--
492+-- Speculative streams enforce ordering of the results of actions in the stream
493+-- but the side effects are only partially ordered. Therefore, the semigroup
494+-- operation for speculative streams is not commutative from the pure outputs
495+-- perspective but commutative from side effects perspective.
422496
423497-- $async
424498--
425−-- The async style streams execute actions asynchronously and consume the
426−-- outputs as well asynchronously. In a composed stream, at any point of time
427−-- more than one stream can run concurrently and yield elements. The elements
428−-- are yielded by the composed stream as they are generated by the constituent
429−-- streams on a first come first serve basis. Therefore, on each run the
430−-- stream may yield elements in a different sequence depending on the delays
431−-- introduced by scheduling. The two async types 'AsyncT' and 'WAsyncT' differ
432−-- in how they traverse streams in 'Semigroup' or 'Monad' compositions.
499+-- When a stream consumer demands an element from an asynchronous stream,
500+-- constructed as @a \`consM` b \`consM` ... nil@, the action @a@ along with
501+-- multiple following at the head of the stream sequence are executed
502+-- concurrently and the output of the one that completes first is supplied to
503+-- the consumer. As more actions complete, their results are buffered in the
504+-- order of completion. When the next element is demanded it may be served
505+-- from the buffer and we may initiate execution of more actions in the
506+-- sequence to keep the buffer adequately filled. Thus, the actions are
507+-- executed concurrently and their results are consumed in the order of
508+-- completion. `consM` can be used to fold an infinite lazy container of
509+-- effects, as the number of concurrent executions is limited.
510+--
511+-- Similar to 'consM', the monadic stream generation (e.g. replicateM) and
512+-- transformation operations (e.g. mapM) on asynchronous streams can execute
513+-- multiple effects concurrently in an asynchronous manner.
514+--
515+-- How many effects can be executed concurrently and how many results can be
516+-- buffered are controlled by 'maxThreads' and 'maxBuffer' combinators
517+-- respectively. The actual number of concurrent threads is adjusted according
518+-- to the rate at which the consumer is consuming the stream. It may even
519+-- execute actions serially in a single thread if that is enough to match the
520+-- consumer's speed.
521+--
522+-- Asynchronous streams do not enforce any spatial order on the side effects or
523+-- on the results of the actions. However there is a partial ordering as the
524+-- actions to be executed are picked from the head of stream. The results are
525+-- presented to the consumer in the completion time order. Therefore, the
526+-- semigroup operation for asynchronous streams is commutative i.e. the stream
527+-- is considered unordered.
528+--
529+-- There are two asynchronous stream types 'AsyncT' and 'WAsyncT'. The stream
530+-- evaluation of both the variants works in the same way as described above,
531+-- they differ only in the 'Semigroup' and 'Monad' implementaitons.
433532
434533-- $zipping
435534--