@@ -48,7 +48,7 @@
51−-- == Console Echo Program
51+-- == Console Echo Example
53-- In the following example, 'repeatM' generates an infinite stream of 'String'
53-- In the following example, 'repeatM' generates an infinite stream of 'String'
54-- by repeatedly performing the 'getLine' IO action. 'mapM' then applies
54-- by repeatedly performing the 'getLine' IO action. 'mapM' then applies
@@ -73,38 +73,11 @@
73-- Hopefully, this gives you an idea how we can program declaratively by
73-- Hopefully, this gives you an idea how we can program declaratively by
74-- representing loops using streams. In this module, you can find all
74-- representing loops using streams. In this module, you can find all
75-- "Data.List" like functions and many more powerful combinators to perform
75-- "Data.List" like functions and many more powerful combinators to perform
76−-- common programming tasks. Also see "Streamly.Internal.Data.Stream"
76+-- common programming tasks.
77−-- module for many more @Pre-release@ combinators. See the
78−-- <https://github.com/composewell/streamly-examples> repository for many more
79−-- real world examples of stream programming.
81−-- == Combining two streams
78+-- Also see "Streamly.Internal.Data.Stream" module for many more @Pre-release@
82−--
79+-- combinators. See the <https://github.com/composewell/streamly-examples>
83−-- Two streams can be combined to form a single stream in several ways.
80+-- repository for many more real world examples of stream programming.
84−-- 'append', 'interleave', 'zipWith', 'mergeBy', are some ways of combining two
87−-- == Combining many streams
89−-- The 'concatMapWith' combinator can be used to generalize the two stream
90−-- combining combinators to @n@ streams.
92−-- See the @streamly-examples@ repository for a full working example.
94−-- == Semigroup Instance
96−-- The 'Semigroup' operation '<>' has an appending behavior i.e. it executes
97−-- the actions from the second stream after executing actions from the first
100−-- >>> stream1 = Stream.sequence $ Stream.fromList [effect 1, effect 2]
101−-- >>> stream2 = Stream.sequence $ Stream.fromList [effect 3, effect 4]
102−-- >>> Stream.fold Fold.toList $ stream1 <> stream2
109module Streamly.Data.Stream
82module Streamly.Data.Stream
@@ -122,14 +95,9 @@ module Streamly.Data.Stream
122 -- versions provided in this module can be much more efficient in most
95 -- versions provided in this module can be much more efficient in most
123 -- cases. Users can create custom combinators using these primitives.
96 -- cases. Users can create custom combinators using these primitives.
127− -- , cons2 -- fused version
128− -- , consM2 -- fused version
130 -- ** Unfolding
99 -- ** Unfolding
131 -- | Generalized way of generating a stream efficiently.
100 -- | Generalized way of generating a stream efficiently.
132− , unfold -- XXX rename to fromUnfold?
133 , unfoldr
101 , unfoldr
134 , unfoldrM
102 , unfoldrM
@@ -169,19 +137,149 @@ module Streamly.Data.Stream
169 , fromList
137 , fromList
170 , fromFoldable
138 , fromFoldable
172− -- * Elimination
140+ -- ** From Unfolds
173− -- | Functions ending in the general shape @Stream m a -> m b@
141+ -- | Most of the above stream generation operations can also be expressed
142+ -- using the corresponding unfolds in the "Streamly.Data.Unfold" module.
143+ , unfold -- XXX rename to fromUnfold?
146+ -- | Operations that increase the size of a stream by adding one or more
175− -- See also: "Streamly.Internal.Data.Stream.Eliminate" for
149+ -- See also: "Streamly.Internal.Data.Stream.Expand" for
176 -- @Pre-release@ functions.
150 -- @Pre-release@ functions.
178− -- ** Deconstruction
152+ -- ** Consing Elements
179− -- | Functions ending in the general shape @Stream m a -> m (b, Stream m a)@
153+ , cons
180− , uncons
154+ , consM
181− -- , foldBreak
155+ -- , cons2 -- fused version
182− -- , parseBreak
156+ -- , consM2 -- fused version
158+ -- ** Inserting Elements
159+ -- | Inserting elements is a special case of interleaving/merging streams.
172+ , wSerial -- XXX rename to interleaveWeighted
175+ -- | Merging of @n@ streams can be performed by combining the streams pair
177+ -- 'Streamly.Internal.Data.Stream.IsStream.Expand.concatPairsWith' to give
178+ -- O(n * log n) time complexity.
179+ -- If used with 'concatMapWith' it will have O(n^2) performance.
186+ -- ** Nested Unfolds
191+ -- ** Nested Streams
192+ -- | Stream operations like map and filter represent loop processing in
193+ -- imperative programming terms. Similarly, the imperative concept of
194+ -- nested loops are represented by streams of streams. The 'concatMap'
195+ -- operation represents nested looping.
196+ -- A 'concatMap' operation loops over the input stream and then for each
197+ -- element of the input stream generates another stream and then loops over
198+ -- that inner stream as well producing effects and generating a single
200+ -- The 'Monad' instances of different stream types provide a more
201+ -- convenient way of writing nested loops. Note that the monad bind
202+ -- operation is just @flip concatMap@.
204+ -- One dimension loops are just a special case of nested loops. For
205+ -- example, 'concatMap' can degenerate to a simple map operation:
207+ -- > map f m = S.concatMap (\x -> S.fromPure (f x)) m
209+ -- Similarly, 'concatMap' can perform filtering by mapping an element to a
212+ -- > filter p m = S.concatMap (\x -> if p x then S.fromPure x else S.nil) m
220+ -- | One-to-one transformations not changing the size (almost) of the
223+ -- See also: "Streamly.Internal.Data.Stream.Transform" for
224+ -- @Pre-release@ functions.
227+ -- | Stateless one-to-one transformations. Use 'fmap' for mapping a pure
228+ -- function on a stream.
231+ -- In imperative terms a map operation can be considered as a loop over
232+ -- the stream that transforms the stream into another stream by performing
233+ -- an operation on each element of the stream.
235+ -- 'map' is the least powerful transformation operation with strictest
236+ -- guarantees. A map, (1) is a stateless loop which means that no state is
237+ -- allowed to be carried from one iteration to another, therefore,
238+ -- operations on different elements are guaranteed to not affect each
239+ -- other, (2) is a strictly one-to-one transformation of stream elements
240+ -- which means it guarantees that no elements can be added or removed from
241+ -- the stream, it can merely transform them.
245+ -- ** Mapping Side Effects
246+ -- , trace -- XXX Use "tracing" map instead?
251+ -- | Stateful one-to-one transformations.
254+ -- XXX postscan1 can be implemented using Monoids or Refolds.
257+ -- | Indexing can be considered as a special type of zipping where we zip a
258+ -- stream with an index stream.
262+ -- ** Reordering Elements
266+ -- | Zipping of @n@ streams can be performed by combining the streams pair
268+ -- 'Streamly.Internal.Data.Stream.IsStream.Expand.concatPairsWith' with
269+ -- O(n * log n) time complexity.
270+ -- If used with 'concatMapWith' it will have O(n^2) performance.
277+ -- | Operations that reduce the size of a stream by removing some or all
278+ -- elements from it.
280+ -- See also: "Streamly.Internal.Data.Stream.Reduce" and
281+ -- "Streamly.Internal.Data.Stream.Eliminate" for @Pre-release@ functions.
184− -- -- ** General Folds
185-- EXPLANATION: In imperative terms a fold can be considered as a loop over the stream
283-- EXPLANATION: In imperative terms a fold can be considered as a loop over the stream
186-- that reduces the stream to a single value.
284-- that reduces the stream to a single value.
187-- Left and right folds both use a fold function @f@ and an identity element
285-- Left and right folds both use a fold function @f@ and an identity element
@@ -249,90 +347,32 @@ module Streamly.Data.Stream
249-- the previous step. However, it is possible to fold parts of the stream in
347-- the previous step. However, it is possible to fold parts of the stream in
250-- parallel and then combine the results using a monoid.
348-- parallel and then combine the results using a monoid.
252− -- ** Left folds
350+ -- ** Unconsing
253− -- $runningfolds
351+ , uncons
254− , fold -- XXX rename to run? We can have a Stream.run and Fold.run.
255− -- XXX fold1 can be achieved using Monoids or Refolds.
262− -- ** Multi-Stream folds
268− -- trimming sequences
272− -- | See also: "Streamly.Internal.Data.Stream.Transform" for
273− -- @Pre-release@ functions.
275− -- ** Mapping
353+ -- ** Filter Map
276− -- | In imperative terms a map operation can be considered as a loop over
354+ -- | Stateless filters. Remove some elements from the stream based on a
277− -- the stream that transforms the stream into another stream by performing
355+ -- predicate.
278− -- an operation on each element of the stream. Use 'fmap' for mapping a
279− -- pure function on a stream.
281 -- EXPLANATION:
357 -- EXPLANATION:
282− -- 'map' is the least powerful transformation operation with strictest
283− -- guarantees. A map, (1) is a stateless loop which means that no state is
284− -- allowed to be carried from one iteration to another, therefore,
285− -- operations on different elements are guaranteed to not affect each
286− -- other, (2) is a strictly one-to-one transformation of stream elements
287− -- which means it guarantees that no elements can be added or removed from
288− -- the stream, it can merely transform them.
292− -- ** Mapping Side Effects
293− -- , trace -- XXX Use "tracing" map instead?
297− -- ** Scanning (Stateful Transformation)
300− -- XXX postscan1 can be implemented using Monoids or Refolds.
303− -- | Remove some elements from the stream based on a predicate. In
304− -- imperative terms a filter over a stream corresponds to a loop with a
358+ -- In imperative terms a filter over a stream corresponds to a loop with a
305 -- @continue@ clause for the cases when the predicate fails.
359 -- @continue@ clause for the cases when the predicate fails.
307− , deleteBy
361+ , mapMaybe
309 , filterM
364 , filterM
312− -- ** Trimming
366+ -- ** Filter Scans
313− -- | Take or remove elements from one or both ends of a stream.
367+ -- | Stateful filters.
315 , takeWhile
369 , takeWhile
316 , takeWhileM
370 , takeWhileM
318 , dropWhile
372 , dropWhile
319 , dropWhileM
373 , dropWhileM
321− -- ** Inserting Elements
375+ , uniq
322− -- | Inserting elements is a special case of interleaving/merging streams.
328− -- ** Reordering Elements
332− -- | Indexing can be considered as a special type of zipping where we zip a
333− -- stream with an index stream.
337 -- ** Searching
377 -- ** Searching
338 -- | Finding the presence or location of an element, a sequence of elements
378 -- | Finding the presence or location of an element, a sequence of elements
@@ -342,88 +382,54 @@ module Streamly.Data.Stream
342 , findIndices
382 , findIndices
343 , elemIndices
383 , elemIndices
345− -- ** Maybe Streams
385+ -- ** Splitting
346− , mapMaybe
386+ -- | Consuming a part of the stream and returning the rest. Functions
347− , mapMaybeM
387+ -- ending in the general shape @Stream m a -> m (b, Stream m a)@
349− -- * Combining Streams
389+ , parseBreak
350− -- | New streams can be constructed by appending, merging or zipping
351− -- existing streams.
353− -- See also: "Streamly.Internal.Data.Stream.Expand" for
354− -- @Pre-release@ functions.
360− -- ** Interleaving
391+ -- ** Elimination
361− -- , interleave
392+ -- | Functions ending in the general shape @Stream m a -> m b@
362− -- , interleave2
393+ -- Consuming the stream entirely or partially, discarding the rest.
363− , wSerial -- XXX rename to interleaveWeighted
366− -- | Merging of @n@ streams can be performed by combining the streams pair
368− -- 'Streamly.Internal.Data.Stream.IsStream.Expand.concatPairsWith' to give
369− -- O(n * log n) time complexity.
370− -- If used with 'concatMapWith' it will have O(n^2) performance.
378− -- | Zipping of @n@ streams can be performed by combining the streams pair
380− -- 'Streamly.Internal.Data.Stream.IsStream.Expand.concatPairsWith' with
381− -- O(n * log n) time complexity.
382− -- If used with 'concatMapWith' it will have O(n^2) performance.
394− -- | Stream operations like map and filter represent loop processing in
395− -- imperative programming terms. Similarly, the imperative concept of
396− -- nested loops are represented by streams of streams. The 'concatMap'
397− -- operation represents nested looping.
398− -- A 'concatMap' operation loops over the input stream and then for each
399− -- element of the input stream generates another stream and then loops over
400− -- that inner stream as well producing effects and generating a single
402− -- The 'Monad' instances of different stream types provide a more
403− -- convenient way of writing nested loops. Note that the monad bind
404− -- operation is just @flip concatMap@.
406− -- One dimension loops are just a special case of nested loops. For
407− -- example, 'concatMap' can degenerate to a simple map operation:
409− -- > map f m = S.concatMap (\x -> S.fromPure (f x)) m
411− -- Similarly, 'concatMap' can perform filtering by mapping an element to a
395+ -- Strict left folds consume a stream and build a left associated
412− -- 'nil' stream:
396+ -- expression, suitable for incremental/strict evaluation. Evaluation of
397+ -- the input happens when the fold runs, the fold output is fully
398+ -- evaluated. A fold can terminate without consuming the entire stream.
414− -- > filter p m = S.concatMap (\x -> if p x then S.fromPure x else S.nil) m
400+ -- This is suitable for reduction operations, for example, operations like
401+ -- summing the stream. See "Streamly.Data.Fold" for an overview of
402+ -- composable left folds. Parsers (See "Streamly.Internal.Data.Parser") are
403+ -- more powerful folds that add backtracking and error functionality to
404+ -- terminating folds.
406+ , fold -- XXX rename to run? We can have a Stream.run and Fold.run.
407+ -- XXX fold1 can be achieved using Monoids or Refolds.
417− , concatMapWith
410+ -- -- ** Lazy Right Folds
418− , concatMap
411+ -- Consuming a stream to build a right associated expression, suitable
419− , concatMapM
412+ -- for lazy evaluation. Evaluation of the input happens when the output of
413+ -- the fold is evaluated, the fold output is a lazy thunk.
415+ -- This is suitable for stream transformation operations, for example,
416+ -- operations like mapping a function over the stream.
421− -- * Nested Folds
420+ -- ** Nested Folds
423− -- See also: "Streamly.Internal.Data.Stream.Reduce" for
424− -- @Pre-release@ functions.
425 , foldMany
421 , foldMany
423+ -- ** Multi-Stream folds
424+ -- | Operations that consume multiple streams at the same time.
430+ -- trimming sequences
427 -- * Exceptions
433 -- * Exceptions
428 -- | Most of these combinators inhibit stream fusion, therefore, when
434 -- | Most of these combinators inhibit stream fusion, therefore, when
429 -- possible, they should be called in an outer loop to mitigate the cost.
435 -- possible, they should be called in an outer loop to mitigate the cost.