3-- Copyright : (c) 2017 Harendra Kumar
6-- Maintainer : harendra.kumar@gmail.com
7-- Stability : experimental
10-- The way a list represents a sequence of pure values, a stream represents a
11-- sequence of monadic actions. The monadic stream API offered by Streamly is
12-- very close to the Haskell "Prelude" pure lists' API, it can be considered as
13-- a natural extension of lists to monadic actions. Streamly streams provide
14-- concurrent composition and merging of streams. It can be considered as a
15-- concurrent list transformer. In contrast to the "Prelude" lists, merging or
16-- appending streams of arbitrary length is scalable and inexpensive.
18-- The basic stream type is 'Serial', it represents a sequence of IO actions,
19-- and is a 'Monad'. The type 'SerialT' is a monad transformer that can
20-- represent a sequence of actions in an arbitrary monad. The type 'Serial' is
21-- in fact a synonym for @SerialT IO@. There are a few more types similar to
22-- 'SerialT', all of them represent a stream and differ only in the
23-- 'Semigroup', 'Applicative' and 'Monad' compositions of the stream. 'Serial'
24-- and 'WSerial' types compose serially whereas 'Async' and 'WAsync'
25-- types compose concurrently. All these types can be freely inter-converted
26-- using type combinators without any cost. You can freely switch to any type
27-- of composition at any point in the program. When no type annotation or
28-- explicit stream type combinators are used, the default stream type is
29-- inferred as 'Serial'.
31-- Here is a simple console echo program example:
34-- > runStream $ S.repeatM getLine & S.mapM putStrLn
37-- For more details please see the "Streamly.Tutorial" module and the examples
38-- directory in this package.
40-- This module exports stream types, instances and some basic operations.
41-- Functionality exported by this module include:
43-- * Semigroup append ('<>') instances as well as explicit operations for merging streams
44-- * Monad and Applicative instances for looping over streams
45-- * Zip Applicatives for zipping streams
46-- * Stream type combinators to convert between different composition styles
47-- * Some basic utilities to run and fold streams
49-- See the "Streamly.Prelude" module for comprehensive APIs for construction,
50-- generation, elimination and transformation of streams.
52-- This module is designed to be imported unqualified:
60#if __GLASGOW_HASKELL__ >= 800
61{-# OPTIONS_GHC -Wno-orphans #-}
64#include "Streamly/Streams/inline.hs"
70 -- * Stream transformers
76 -- ** Concurrent Lookahead Streams
80 -- ** Concurrent Asynchronous Streams
94 -- * Parallel Function Application
111 -- * Concurrency Control
124 -- * Folding Containers of Streams
130 -- * Stream Type Adapters
176import Data.Semigroup (Semigroup(..))
177import Streamly.SVar (MonadAsync, Rate(..))
178import Streamly.Streams.Ahead
179import Streamly.Streams.Async
180import Streamly.Streams.Combinators
181import Streamly.Streams.Parallel
182import Streamly.Streams.Prelude
183import Streamly.Streams.Serial
184import Streamly.Streams.StreamK hiding (runStream, serial)
185import Streamly.Streams.Zip
187import qualified Streamly.Streams.StreamD as D
188import qualified Streamly.Streams.StreamK as K
190-- XXX This should perhaps be moved to Prelude.
192------------------------------------------------------------------------------
193-- Eliminating a stream
194------------------------------------------------------------------------------
196-- | Run a streaming composition, discard the results. By default it interprets
197-- the stream as 'SerialT', to run other types of streams use the type adapting
198-- combinators for example @runStream . 'asyncly'@.
201{-# INLINE_EARLY runStream #-}
202runStream :: Monad m => SerialT m a -> m ()
203runStream m = D.runStream $ D.fromStreamK (toStream m)
204{-# RULES "runStream fallback to CPS" [1]
205 forall a. D.runStream (D.fromStreamK a) = K.runStream a #-}
207-- | Same as 'runStream'
210{-# DEPRECATED runStreaming "Please use runStream instead." #-}
211runStreaming :: (Monad m, IsStream t) => t m a -> m ()
212runStreaming = runStream . K.adapt
214-- | Same as @runStream@.
217{-# DEPRECATED runStreamT "Please use runStream instead." #-}
218runStreamT :: Monad m => SerialT m a -> m ()
219runStreamT = runStream
221-- | Same as @runStream . wSerially@.
224{-# DEPRECATED runInterleavedT "Please use 'runStream . interleaving' instead." #-}
225runInterleavedT :: Monad m => WSerialT m a -> m ()
226runInterleavedT = runStream . K.adapt
228-- | Same as @runStream . parallely@.
231{-# DEPRECATED runParallelT "Please use 'runStream . parallely' instead." #-}
232runParallelT :: Monad m => ParallelT m a -> m ()
233runParallelT = runStream . K.adapt
235-- | Same as @runStream . asyncly@.
238{-# DEPRECATED runAsyncT "Please use 'runStream . asyncly' instead." #-}
239runAsyncT :: Monad m => AsyncT m a -> m ()
240runAsyncT = runStream . K.adapt
242-- | Same as @runStream . zipping@.
245{-# DEPRECATED runZipStream "Please use 'runStream . zipSerially instead." #-}
246runZipStream :: Monad m => ZipSerialM m a -> m ()
247runZipStream = runStream . K.adapt
249-- | Same as @runStream . zippingAsync@.
252{-# DEPRECATED runZipAsync "Please use 'runStream . zipAsyncly instead." #-}
253runZipAsync :: Monad m => ZipAsyncM m a -> m ()
254runZipAsync = runStream . K.adapt
256------------------------------------------------------------------------------
258------------------------------------------------------------------------------
262-- Serial streams compose serially or non-concurrently. In a composed stream,
263-- each action is executed only after the previous action has finished. The two
264-- serial stream types 'SerialT' and 'WSerialT' differ in how they traverse the
265-- streams in a 'Semigroup' or 'Monad' composition.
269-- The async style streams execute actions asynchronously and consume the
270-- outputs as well asynchronously. In a composed stream, at any point of time
271-- more than one stream can run concurrently and yield elements. The elements
272-- are yielded by the composed stream as they are generated by the constituent
273-- streams on a first come first serve basis. Therefore, on each run the
274-- stream may yield elements in a different sequence depending on the delays
275-- introduced by scheduling. The two async types 'AsyncT' and 'WAsyncT' differ
276-- in how they traverse streams in 'Semigroup' or 'Monad' compositions.
280-- 'ZipSerialM' and 'ZipAsyncM', provide 'Applicative' instances for zipping the
281-- corresponding elements of two streams together. Note that these types are
286-- Stream processing functions can be composed in a chain using function
287-- application with or without the '$' operator, or with reverse function
288-- application operator '&'. Streamly provides concurrent versions of these
289-- operators applying stream processing functions such that each stage of the
290-- stream can run in parallel. The operators start with a @|@; we can read '|$'
291-- as "@parallel dollar@" to remember that @|@ comes before '$'.
293-- Imports for the code snippets below:
297-- import qualified Streamly.Prelude as S
298-- import Control.Concurrent
302-- The 'Semigroup' operation '<>' of each stream type combines two streams in a
303-- type specific manner. This section provides polymorphic versions of '<>'
304-- which can be used to combine two streams in a predetermined way irrespective
307-- XXX An alternative design choice would be to let a control parameter affect
308-- the nearest SVar only and then it gets cleared. The benefit of the current
309-- choice is that it is simply just like global configuration, just like state
310-- behaves, so should be easy to comprehend. But it has the downside of leaking
311-- to undesired actions, that is we can forget to reset it.
315-- These combinators can be used at any point in a stream composition to set
316-- parameters to control the concurrency of the enclosed stream. A parameter
317-- set at any point remains effective for any concurrent combinators used
318-- downstream until it is reset. These control parameters have no effect on
319-- non-concurrent combinators in the stream, or on non-concurrent streams. They
320-- also do not affect 'Parallel' streams, as concurrency for 'Parallel' streams
321-- is always unbounded.
325-- You may want to use different stream composition styles at different points
326-- in your program. Stream types can be freely converted or adapted from one
327-- type to another. The 'IsStream' type class facilitates type conversion of
328-- one stream type to another. It is not used directly, instead the type
329-- combinators provided below are used for conversions.
331-- To adapt from one monomorphic type (e.g. 'AsyncT') to another monomorphic
332-- type (e.g. 'SerialT') use the 'adapt' combinator. To give a polymorphic code
333-- a specific interpretation or to adapt a specific type to a polymorphic type
334-- use the type specific combinators e.g. 'asyncly' or 'wSerially'. You
335-- cannot adapt polymorphic code to polymorphic code, as the compiler would not know
336-- which specific type you are converting from or to. If you see a an
337-- @ambiguous type variable@ error then most likely you are using 'adapt'
338-- unnecessarily on polymorphic code.
343-- These are variants of standard 'Foldable' fold functions that use a
344-- polymorphic stream sum operation (e.g. 'async' or 'wSerial') to fold a
345-- container of streams.
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list