on master help sign in
Remove obselete files and fix documentation and dev module imports
commit128ac005dfe6a350b3d68854280c78930f624192 authorAdithya Kumar <adithya@composewell.com> dateThu 27 Jul 2023, 18:35 (3 years ago) parent5f4ba50
23 files changed+90−6250
benchmark/Streamly/Benchmark/Data/Stream/StreamDK.hs+1−1 core/src/Streamly/Data/Stream.hs+4−4 core/src/Streamly/Data/Stream/StreamDK.hs−505 core/src/Streamly/Data/Stream/Zip.hs−16 core/src/Streamly/Data/Unfold.hs+1−1 core/src/Streamly/Internal/Data/List.hs+82−16 core/src/Streamly/Internal/Data/Stream/Bottom.hs−670 core/src/Streamly/Internal/Data/Stream/Cross.hs−143 core/src/Streamly/Internal/Data/Stream/Eliminate.hs−377 core/src/Streamly/Internal/Data/Stream/Enumerate.hs−560 core/src/Streamly/Internal/Data/Stream/Exception.hs−222 core/src/Streamly/Internal/Data/Stream/Expand.hs−893 core/src/Streamly/Internal/Data/Stream/Generate.hs−460 core/src/Streamly/Internal/Data/Stream/Lift.hs−95 core/src/Streamly/Internal/Data/Stream/Reduce.hs−444 core/src/Streamly/Internal/Data/Stream/StreamD/Eliminate.hs+1−1 core/src/Streamly/Internal/Data/Stream/StreamDK.hs−52 core/src/Streamly/Internal/Data/Stream/Transform.hs−1056 core/src/Streamly/Internal/Data/Stream/Transformer.hs−135 core/src/Streamly/Internal/Data/Stream/Type.hs−491 core/src/Streamly/Internal/Data/Stream/Zip.hs−91 core/src/Streamly/Internal/Data/Unfold.hs+1−1 core/streamly-core.cabal−16
benchmark/Streamly/Benchmark/Data/Stream/StreamDK.hs+1−1
@@ -18,7 +18,7 @@ import Prelude hiding ()
1818-- import qualified Prelude as P
1919-- import qualified Data.List as List
2020
21−import qualified Streamly.Internal.Data.Stream.StreamDK as S
21+import qualified Streamly.Internal.Data.Stream.StreamK.Alt as S
2222-- import qualified Streamly.Internal.Data.Stream.Common as SP
2323-- import qualified Streamly.Internal.Data.SVar as S
2424
core/src/Streamly/Data/Stream.hs+4−4
@@ -37,7 +37,7 @@ module Streamly.Data.Stream
3737 -- * Construction
3838 -- | Functions ending in the general shape @b -> Stream m a@.
3939 --
40− -- See also: "Streamly.Internal.Data.Stream.Generate" for
40+ -- See also: "Streamly.Internal.Data.Stream.StreamD.Generate" for
4141 -- @Pre-release@ functions.
4242 --
4343 -- Useful Idioms:
@@ -111,7 +111,7 @@ module Streamly.Data.Stream
111111 -- | Functions ending in the general shape @Stream m a -> m b@ or @Stream m
112112 -- a -> m (b, Stream m a)@
113113 --
114− -- See also: "Streamly.Internal.Data.Stream.Eliminate" for @Pre-release@
114+ -- See also: "Streamly.Internal.Data.Stream.StreamD.Eliminate" for @Pre-release@
115115 -- functions.
116116
117117-- EXPLANATION: In imperative terms a fold can be considered as a loop over the stream
@@ -253,7 +253,7 @@ module Streamly.Data.Stream
253253 -- * Scanning
254254 -- | Stateful one-to-one transformations.
255255 --
256− -- See also: "Streamly.Internal.Data.Stream.Transform" for
256+ -- See also: "Streamly.Internal.Data.Stream.StreamD.Transform" for
257257 -- @Pre-release@ functions.
258258
259259 {-
@@ -471,7 +471,7 @@ module Streamly.Data.Stream
471471 -- For example, instead of calling them on a stream of chars call them on a
472472 -- stream of arrays before flattening it to a stream of chars.
473473 --
474− -- See also: "Streamly.Internal.Data.Stream.Exception" for
474+ -- See also: "Streamly.Internal.Data.Stream.StreamD.Exception" for
475475 -- @Pre-release@ functions.
476476
477477 , onException
core/src/Streamly/Data/Stream/StreamDK.hsdeleted−505
@@ -1,505 +0,0 @@
1−-- |
2−-- Module : Streamly.Data.Stream.StreamDK
3−-- Copyright : (c) 2017 Composewell Technologies
4−--
5−-- License : BSD3
6−-- Maintainer : streamly@composewell.com
7−-- Stability : released
8−-- Portability : GHC
9−--
10−-- To run examples in this module:
11−--
12−-- >>> import qualified Streamly.Data.Fold as Fold
13−-- >>> import qualified Streamly.Data.Stream.StreamDK as Stream
14−--
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−-- Streams can be constructed like lists, except that they use 'nil' instead of
29−-- '[]' and 'cons' instead of ':'.
30−--
31−-- `cons` adds a pure value at the head of the stream:
32−--
33−-- >>> import Streamly.Data.Stream.StreamDK (Stream, cons, consM, nil)
34−-- >>> stream = 1 `cons` 2 `cons` nil :: Stream IO Int
35−-- >>> Stream.fold Fold.toList stream -- IO [Int]
36−-- [1,2]
37−--
38−-- `consM` adds an effect at the head of the stream:
39−--
40−-- >>> stream = effect 1 `consM` effect 2 `consM` nil
41−-- >>> Stream.fold Fold.toList stream
42−-- 1
43−-- 2
44−-- [1,2]
45−--
46−-- == Console Echo Example
47−--
48−-- In the following example, 'repeatM' generates an infinite stream of 'String'
49−-- by repeatedly performing the 'getLine' IO action. 'mapM' then applies
50−-- 'putStrLn' on each element in the stream converting it to stream of '()'.
51−-- Finally, 'drain' folds the stream to IO discarding the () values, thus
52−-- producing only effects.
53−--
54−-- >>> import Data.Function ((&))
55−--
56−-- >>> :{
57−-- echo =
58−-- Stream.repeatM getLine -- Stream IO String
59−-- & Stream.mapM putStrLn -- Stream IO ()
60−-- & Stream.fold Fold.drain -- IO ()
61−-- :}
62−--
63−-- This is a console echo program. It is an example of a declarative loop
64−-- written using streaming combinators. Compare it with an imperative @while@
65−-- loop.
66−--
67−-- Hopefully, this gives you an idea how we can program declaratively by
68−-- representing loops using streams. In this module, you can find all
69−-- "Data.List" like functions and many more powerful combinators to perform
70−-- common programming tasks.
71−--
72−-- == Useful Idioms
73−--
74−-- >>> fromListM = Stream.sequence . Stream.fromList
75−-- >>> fromFoldableM = Stream.sequence . Stream.fromFoldable
76−-- >>> fromIndices f = fmap f $ Stream.enumerateFrom 0
77−--
78−-- Also see "Streamly.Internal.Data.Stream.StreamDK" module for many more @Pre-release@
79−-- combinators. See the <https://github.com/composewell/streamly-examples>
80−-- repository for many more real world examples of stream programming.
81−--
82−-- == Performance Notes
83−--
84−-- Operations annotated as /CPS/ force the use of continuation passing style
85−-- streams. Therefore, such operations are not subjected to stream fusion.
86−-- However, for some of these operations you can find fusible alternatives in
87−-- the internal modules, which are perfectly fine to use but you need to
88−-- understand the implications especially the O(n^2) nature of those
89−-- operations..
90−--
91−module Streamly.Data.Stream.StreamDK
92− (
93− Stream
94− -- * Construction
95− -- | Functions ending in the general shape @b -> Stream m a@.
96− --
97− -- See also: "Streamly.Internal.Data.Stream.Generate" for
98− -- @Pre-release@ functions.
99−
100− -- ** Primitives
101− -- | Primitives to construct a stream from pure values or monadic actions.
102− -- All other stream construction and generation combinators described later
103− -- can be expressed in terms of these primitives. However, the special
104− -- versions provided in this module can be much more efficient in most
105− -- cases. Users can create custom combinators using these primitives.
106− , nil
107− , nilM
108− , cons
109− , consM
110− -- , cons2 -- fused version
111− -- , consM2 -- fused version
112−
113− -- ** Unfolding
114− -- | 'unfoldrM' is the most general way of generating a stream efficiently.
115− -- All other generation operations can be expressed using it.
116− , unfoldr
117− , unfoldrM
118−
119− -- ** From Values
120− -- | Generate a monadic stream from a seed value or values.
121− , fromPure
122− , fromEffect
123− , repeat
124− , repeatM
125− , replicate
126− , replicateM
127−
128− -- Note: Using enumeration functions e.g. 'Prelude.enumFromThen' turns out
129− -- to be slightly faster than the idioms like @[from, then..]@.
130− --
131− -- ** Enumeration
132− -- | We can use the 'Enum' type class to enumerate a type producing a list
133− -- and then convert it to a stream:
134− --
135− -- @
136− -- 'fromList' $ 'Prelude.enumFromThen' from then
137− -- @
138− --
139− -- However, this is not particularly efficient.
140− -- The 'Enumerable' type class provides corresponding functions that
141− -- generate a stream instead of a list, efficiently.
142−
143− , Enumerable (..)
144− , enumerate
145− , enumerateTo
146−
147− -- ** Iteration
148− , iterate
149− , iterateM
150−
151− -- ** From Containers
152− -- | Convert an input structure, container or source into a stream. All of
153− -- these can be expressed in terms of primitives.
154− , fromList
155− , fromFoldable
156−
157− -- ** From Unfolds
158− -- | Most of the above stream generation operations can also be expressed
159− -- using the corresponding unfolds in the "Streamly.Data.Unfold" module.
160− , unfold -- XXX rename to fromUnfold?
161−
162− -- * Elimination
163− -- | Functions ending in the general shape @Stream m a -> m b@ or @Stream m
164− -- a -> m (b, Stream m a)@
165− --
166− -- See also: "Streamly.Internal.Data.Stream.Eliminate" for @Pre-release@
167− -- functions.
168−
169−-- EXPLANATION: In imperative terms a fold can be considered as a loop over the stream
170−-- that reduces the stream to a single value.
171−-- Left and right folds both use a fold function @f@ and an identity element
172−-- @z@ (@zero@) to deconstruct a recursive data structure and reconstruct a
173−-- new data structure. The new structure may be a recursive construction (a
174−-- container) or a non-recursive single value reduction of the original
175−-- structure.
176−--
177−-- Both right and left folds are mathematical duals of each other, they are
178−-- functionally equivalent. Operationally, a left fold on a left associated
179−-- structure behaves exactly in the same way as a right fold on a right
180−-- associated structure. Similarly, a left fold on a right associated structure
181−-- behaves in the same way as a right fold on a left associated structure.
182−-- However, the behavior of a right fold on a right associated structure is
183−-- operationally different (even though functionally equivalent) than a left
184−-- fold on the same structure.
185−--
186−-- On right associated structures like Haskell @cons@ lists or Streamly
187−-- streams, a lazy right fold is naturally suitable for lazy recursive
188−-- reconstruction of a new structure, while a strict left fold is naturally
189−-- suitable for efficient reduction. In right folds control is in the hand of
190−-- the @puller@ whereas in left folds the control is in the hand of the
191−-- @pusher@.
192−--
193−-- The behavior of right and left folds are described in detail in the
194−-- individual fold's documentation. To illustrate the two folds for right
195−-- associated @cons@ lists:
196−--
197−-- > foldr :: (a -> b -> b) -> b -> [a] -> b
198−-- > foldr f z [] = z
199−-- > foldr f z (x:xs) = x `f` foldr f z xs
200−-- >
201−-- > foldl :: (b -> a -> b) -> b -> [a] -> b
202−-- > foldl f z [] = z
203−-- > foldl f z (x:xs) = foldl f (z `f` x) xs
204−--
205−-- @foldr@ is conceptually equivalent to:
206−--
207−-- > foldr f z [] = z
208−-- > foldr f z [x] = f x z
209−-- > foldr f z xs = foldr f (foldr f z (tail xs)) [head xs]
210−--
211−-- @foldl@ is conceptually equivalent to:
212−--
213−-- > foldl f z [] = z
214−-- > foldl f z [x] = f z x
215−-- > foldl f z xs = foldl f (foldl f z (init xs)) [last xs]
216−--
217−-- Left and right folds are duals of each other.
218−--
219−-- @
220−-- foldr f z xs = foldl (flip f) z (reverse xs)
221−-- foldl f z xs = foldr (flip f) z (reverse xs)
222−-- @
223−--
224−-- More generally:
225−--
226−-- @
227−-- foldr f z xs = foldl g id xs z where g k x = k . f x
228−-- foldl f z xs = foldr g id xs z where g x k = k . flip f x
229−-- @
230−--
231−
232−-- NOTE: Folds are inherently serial as each step needs to use the result of
233−-- the previous step. However, it is possible to fold parts of the stream in
234−-- parallel and then combine the results using a monoid.
235−
236− -- ** Primitives
237− -- Consuming a part of the stream and returning the rest. Functions
238− -- ending in the general shape @Stream m a -> m (b, Stream m a)@
239− , uncons
240−
241− -- ** Folding
242− -- XXX Need to have a general parse operation here which can be used to
243− -- express all others.
244− , fold -- XXX rename to run? We can have a Stream.run and Fold.run.
245− -- XXX fold1 can be achieved using Monoids or Refolds.
246− -- XXX We can call this just "break" and parseBreak as "munch"
247− , foldBreak
248−
249− -- XXX should we have a Fold returning function in stream module?
250− -- , foldAdd
251− -- , buildl
252−
253− -- ** Parsing
254− , parse
255− , parseBreak
256−
257− -- -- ** Lazy Right Folds
258− -- Consuming a stream to build a right associated expression, suitable
259− -- for lazy evaluation. Evaluation of the input happens when the output of
260− -- the fold is evaluated, the fold output is a lazy thunk.
261− --
262− -- This is suitable for stream transformation operations, for example,
263− -- operations like mapping a function over the stream.
264− -- , foldrM
265− -- , foldr
266−
267− -- * Mapping
268− -- | Stateless one-to-one transformations. Use 'fmap' for mapping a pure
269− -- function on a stream.
270−
271− -- EXPLANATION:
272− -- In imperative terms a map operation can be considered as a loop over
273− -- the stream that transforms the stream into another stream by performing
274− -- an operation on each element of the stream.
275− --
276− -- 'map' is the least powerful transformation operation with strictest
277− -- guarantees. A map, (1) is a stateless loop which means that no state is
278− -- allowed to be carried from one iteration to another, therefore,
279− -- operations on different elements are guaranteed to not affect each
280− -- other, (2) is a strictly one-to-one transformation of stream elements
281− -- which means it guarantees that no elements can be added or removed from
282− -- the stream, it can merely transform them.
283− , sequence
284− , mapM
285− -- , trace -- XXX Use "tracing" map instead?
286− , tap
287− , delay
288−
289− -- * Scanning
290− -- | Stateful one-to-one transformations.
291− --
292− -- See also: "Streamly.Internal.Data.Stream.Transform" for
293− -- @Pre-release@ functions.
294− , scan
295− , postscan
296− -- XXX postscan1 can be implemented using Monoids or Refolds.
297− -- Indexing can be considered as a special type of zipping where we zip a
298− -- stream with an index stream.
299− , indexed
300−
301− -- * Insertion
302− -- | Add elements to the stream.
303−
304− -- Inserting elements is a special case of interleaving/merging streams.
305− , insertBy
306− , intersperseM
307− , intersperseM_
308− , intersperse
309−
310− -- * Filtering
311− -- | Remove elements from the stream.
312−
313− -- ** Stateless Filters
314− -- | 'mapMaybeM' is the most general stateless filtering operation. All
315− -- other filtering operations can be expressed using it.
316−
317− -- EXPLANATION:
318− -- In imperative terms a filter over a stream corresponds to a loop with a
319− -- @continue@ clause for the cases when the predicate fails.
320−
321− , mapMaybe
322− , mapMaybeM
323− , filter
324− , filterM
325−
326− -- Filter and concat
327− , catMaybes
328− , catLefts
329− , catRights
330− , catEithers
331−
332− -- ** Stateful Filters
333− -- | 'scanMaybe' is the most general stateful filtering operation. The
334− -- filtering folds (folds returning a 'Maybe' type) in
335− -- "Streamly.Internal.Data.Fold" can be used along with 'scanMaybe' to
336− -- perform stateful filtering operations in general.
337− , scanMaybe
338− , take
339− , takeWhile
340− , takeWhileM
341− , drop
342− , dropWhile
343− , dropWhileM
344−
345− -- XXX These are available as scans in folds. We need to check the
346− -- performance though. If these are common and we need convenient stream
347− -- ops then we can expose these.
348−
349− -- , deleteBy
350− -- , uniq
351− -- , uniqBy
352−
353− -- -- ** Sampling
354− -- , strideFromThen
355−
356− -- -- ** Searching
357− -- Finding the presence or location of an element, a sequence of elements
358− -- or another stream within a stream.
359−
360− -- -- ** Searching Elements
361− -- , findIndices
362− -- , elemIndices
363−
364− -- * Combining Two Streams
365− -- ** Appending
366− , append
367−
368− -- ** Interleaving
369− , interleave
370− -- , interleave2
371−
372− -- ** Merging
373− -- | Merging of @n@ streams can be performed by combining the streams pair
374− -- wise using 'mergeMapWith' to give O(n * log n) time complexity. If used
375− -- with 'concatMapWith' it will have O(n^2) performance.
376−
377− , mergeBy
378− , mergeByM
379− -- , mergeBy2
380− -- , mergeByM2
381−
382− -- ** Zipping
383− -- | Zipping of @n@ streams can be performed by combining the streams pair
384− -- wise using 'mergeMapWith' with O(n * log n) time complexity. If used
385− -- with 'concatMapWith' it will have O(n^2) performance.
386− , zipWith
387− , zipWithM
388− -- , zipWith2
389− -- , zipWithM2
390− , ZipStream (..)
391−
392− -- ** Cross Product
393− -- XXX The argument order in this operation is such that it seems we are
394− -- transforming the first stream using the second stream because the second
395− -- stream is evaluated many times or buffered and better be finite, first
396− -- stream could potentially be infinite. In the tradition of using the
397− -- transformed stream at the end we can have a flipped version called
398− -- "crossMap" or "nestWith".
399− , crossWith
400− -- , cross
401− -- , joinInner
402− , CrossStream (..)
403−
404− -- * Unfold Each
405− , unfoldMany
406− , intercalate
407− , intercalateSuffix
408−
409− -- * Stream of streams
410− -- | Stream operations like map and filter represent loop processing in
411− -- imperative programming terms. Similarly, the imperative concept of
412− -- nested loops are represented by streams of streams. The 'concatMap'
413− -- operation represents nested looping.
414− -- A 'concatMap' operation loops over the input stream and then for each
415− -- element of the input stream generates another stream and then loops over
416− -- that inner stream as well producing effects and generating a single
417− -- output stream.
418− --
419− -- One dimension loops are just a special case of nested loops. For
420− -- example, 'concatMap' can degenerate to a simple map operation:
421− --
422− -- > map f m = S.concatMap (\x -> S.fromPure (f x)) m
423− --
424− -- Similarly, 'concatMap' can perform filtering by mapping an element to a
425− -- 'nil' stream:
426− --
427− -- > filter p m = S.concatMap (\x -> if p x then S.fromPure x else S.nil) m
428− --
429−
430− , concatEffect
431− , concatMapWith
432− , concatMap
433− , concatMapM
434− , mergeMapWith
435−
436− -- * Repeated Fold
437− , foldMany -- XXX Rename to foldRepeat
438− , parseMany
439− , chunksOf
440−
441− -- * Buffered Operations
442− -- | Operations that require buffering of the stream.
443− -- Reverse is essentially a left fold followed by an unfold.
444− , reverse
445− , sortBy
446−
447− -- * Multi-Stream folds
448− -- | Operations that consume multiple streams at the same time.
449− , eqBy
450− , cmpBy
451− , isPrefixOf
452− , isSubsequenceOf
453−
454− -- trimming sequences
455− , stripPrefix
456−
457− -- Exceptions and resource management depend on the "exceptions" package
458− -- XXX We can have IO Stream operations not depending on "exceptions"
459− -- in Exception.Base
460−
461− -- * Exceptions
462− -- | Most of these combinators inhibit stream fusion, therefore, when
463− -- possible, they should be called in an outer loop to mitigate the cost.
464− -- For example, instead of calling them on a stream of chars call them on a
465− -- stream of arrays before flattening it to a stream of chars.
466− --
467− -- See also: "Streamly.Internal.Data.Stream.Exception" for
468− -- @Pre-release@ functions.
469−
470− , onException
471− , handle
472−
473− -- * Resource Management
474− -- | 'bracket' is the most general resource management operation, all other
475− -- operations can be expressed using it. These functions have IO suffix
476− -- because the allocation and cleanup functions are IO actions. For
477− -- generalized allocation and cleanup functions see the functions without
478− -- the IO suffix in the "streamly" package.
479− , before
480− , afterIO
481− , finallyIO
482− , bracketIO
483− , bracketIO3
484−
485− -- * Transforming Inner Monad
486−
487− , morphInner
488− , liftInner
489− , runReaderT
490− , runStateT
491−
492− -- -- * Stream Types
493− -- $serial
494− -- , Interleave
495− -- , Zip
496− )
497−where
498−
499−import Streamly.Internal.Data.Stream.StreamDK
500−import Prelude
501− hiding (filter, drop, dropWhile, take, takeWhile, zipWith, foldr,
502− foldl, map, mapM, mapM_, sequence, all, any, sum, product, elem,
503− notElem, maximum, minimum, head, last, tail, length, null,
504− reverse, iterate, init, and, or, lookup, foldr1, (!!),
505− scanl, scanl1, repeat, replicate, concatMap, span)
core/src/Streamly/Data/Stream/Zip.hsdeleted−16
@@ -1,16 +0,0 @@
1−-- |
2−-- Module : Streamly.Data.Stream.Zip
3−-- Copyright : (c) 2017 Composewell Technologies
4−--
5−-- License : BSD3
6−-- Maintainer : streamly@composewell.com
7−-- Stability : released
8−-- Portability : GHC
9−--
10−module Streamly.Data.Stream.Zip
11− (
12− ZipStream (..)
13− )
14−where
15−
16−import Streamly.Internal.Data.Stream.Zip
core/src/Streamly/Data/Unfold.hs+1−1
@@ -39,7 +39,7 @@ module Streamly.Data.Unfold
3939
4040 -- * Unfolds
4141 -- One to one correspondence with
42− -- "Streamly.Internal.Data.Stream.Generate"
42+ -- "Streamly.Internal.Data.Stream.StreamD.Generate"
4343
4444 -- ** Basic Constructors
4545 , unfoldrM
core/src/Streamly/Internal/Data/List.hs+82−16
@@ -66,13 +66,19 @@ where
6666import Control.Arrow (second)
6767import Data.Functor.Identity (Identity, runIdentity)
6868import GHC.Exts (IsList(..), IsString(..))
69−import Streamly.Internal.Data.Stream.Cross (CrossStream(..))
70−import Streamly.Internal.Data.Stream.Type (Stream)
71−import Streamly.Internal.Data.Stream.Zip (ZipStream(..))
72−import Text.Read (readPrec)
69+import Streamly.Internal.Data.Stream.StreamD.Type
70+ ( CrossStream
71+ , mkCross
72+ , unCross
73+ )
74+import Streamly.Internal.Data.Stream.StreamD.Type (Stream)
75+import Text.Read
76+ ( Lexeme(Ident), lexP, parens, prec, readPrec, readListPrec
77+ , readListPrecDefault)
7378
7479import qualified Streamly.Internal.Data.Stream.StreamK.Type as K
75−import qualified Streamly.Internal.Data.Stream.Type as Stream
80+import qualified Streamly.Internal.Data.Stream.StreamD.Type as Stream
81+import qualified Streamly.Internal.Data.Stream.StreamD.Generate as Stream
7682
7783-- XXX Rename to PureStream.
7884
@@ -82,21 +88,21 @@ import qualified Streamly.Internal.Data.Stream.Type as Stream
8288newtype List a = List { toCrossStream :: CrossStream Identity a }
8389 deriving
8490 ( Eq, Ord
85− , Semigroup, Monoid, Functor, Foldable
86− , Applicative, Traversable, Monad, IsList)
91+ , Functor, Foldable
92+ , Applicative, Monad, IsList)
8793
8894toStream :: List a -> Stream Identity a
89−toStream = unCrossStream . toCrossStream
95+toStream = unCross . toCrossStream
9096
9197fromStream :: Stream Identity a -> List a
92−fromStream xs = List (CrossStream xs)
98+fromStream xs = List (mkCross xs)
9399
94100instance (a ~ Char) => IsString (List a) where
95101 {-# INLINE fromString #-}
96102 fromString = List . fromList
97103
98104instance Show a => Show (List a) where
99− show (List x) = show $ unCrossStream x
105+ show (List x) = show $ unCross x
100106
101107instance Read a => Read (List a) where
102108 readPrec = fromStream <$> readPrec
@@ -119,7 +125,7 @@ pattern Nil <- (runIdentity . K.null . Stream.toStreamK . toStream -> True)
119125
120126 where
121127
122− Nil = List $ CrossStream (Stream.fromStreamK K.nil)
128+ Nil = List $ mkCross (Stream.fromStreamK K.nil)
123129
124130infixr 5 `Cons`
125131
@@ -128,17 +134,77 @@ infixr 5 `Cons`
128134--
129135pattern Cons :: a -> List a -> List a
130136pattern Cons x xs <-
131− (fmap (second (List . CrossStream . Stream.fromStreamK))
137+ (fmap (second (List . mkCross . Stream.fromStreamK))
132138 . runIdentity . K.uncons . Stream.toStreamK . toStream
133139 -> Just (x, xs)
134140 )
135141
136142 where
137143
138− Cons x xs = List $ CrossStream $ Stream.cons x (toStream xs)
144+ Cons x xs = List $ mkCross $ Stream.cons x (toStream xs)
139145
140146{-# COMPLETE Nil, Cons #-}
141147
148+------------------------------------------------------------------------------
149+-- ZipStream
150+------------------------------------------------------------------------------
151+
152+-- $setup
153+-- >>> import qualified Streamly.Data.Fold as Fold
154+-- >>> import qualified Streamly.Data.Stream as Stream
155+-- >>> import qualified Streamly.Internal.Data.Stream.Zip as Stream
156+
157+------------------------------------------------------------------------------
158+-- Serially Zipping Streams
159+------------------------------------------------------------------------------
160+
161+-- | For 'ZipStream':
162+--
163+-- @
164+-- (<>) = 'Streamly.Data.Stream.append'
165+-- (\<*>) = 'Streamly.Data.Stream.zipWith' id
166+-- @
167+--
168+-- Applicative evaluates the streams being zipped serially:
169+--
170+-- >>> s1 = Stream.ZipStream $ Stream.fromFoldable [1, 2]
171+-- >>> s2 = Stream.ZipStream $ Stream.fromFoldable [3, 4]
172+-- >>> s3 = Stream.ZipStream $ Stream.fromFoldable [5, 6]
173+-- >>> s = (,,) <$> s1 <*> s2 <*> s3
174+-- >>> Stream.fold Fold.toList (Stream.unZipStream s)
175+-- [(1,3,5),(2,4,6)]
176+--
177+newtype ZipStream m a = ZipStream {unZipStream :: Stream m a}
178+ deriving (Functor)
179+
180+deriving instance IsList (ZipStream Identity a)
181+deriving instance (a ~ Char) => IsString (ZipStream Identity a)
182+deriving instance Eq a => Eq (ZipStream Identity a)
183+deriving instance Ord a => Ord (ZipStream Identity a)
184+deriving instance (Foldable m, Monad m) => Foldable (ZipStream m)
185+
186+instance Show a => Show (ZipStream Identity a) where
187+ showsPrec p dl = showParen (p > 10) $
188+ showString "fromList " . shows (toList dl)
189+
190+instance Read a => Read (ZipStream Identity a) where
191+ readPrec = parens $ prec 10 $ do
192+ Ident "fromList" <- lexP
193+ fromList <$> readPrec
194+ readListPrec = readListPrecDefault
195+
196+type ZipSerialM = ZipStream
197+
198+-- | An IO stream whose applicative instance zips streams serially.
199+--
200+type ZipSerial = ZipSerialM IO
201+
202+instance Monad m => Applicative (ZipStream m) where
203+ pure = ZipStream . Stream.repeat
204+
205+ {-# INLINE (<*>) #-}
206+ ZipStream m1 <*> ZipStream m2 = ZipStream $ Stream.zipWith id m1 m2
207+
142208------------------------------------------------------------------------------
143209-- ZipList
144210------------------------------------------------------------------------------
@@ -149,8 +215,8 @@ pattern Cons x xs <-
149215newtype ZipList a = ZipList { toZipStream :: ZipStream Identity a }
150216 deriving
151217 ( Show, Read, Eq, Ord
152− , Semigroup, Monoid, Functor, Foldable
153− , Applicative, Traversable, IsList
218+ , Functor, Foldable
219+ , Applicative, IsList
154220 )
155221
156222instance (a ~ Char) => IsString (ZipList a) where
@@ -160,7 +226,7 @@ instance (a ~ Char) => IsString (ZipList a) where
160226-- | Convert a 'ZipList' to a regular 'List'
161227--
162228fromZipList :: ZipList a -> List a
163−fromZipList (ZipList zs) = List $ CrossStream (unZipStream zs)
229+fromZipList (ZipList zs) = List $ mkCross (unZipStream zs)
164230
165231-- | Convert a regular 'List' to a 'ZipList'
166232--
core/src/Streamly/Internal/Data/Stream/Bottom.hsdeleted−670
@@ -1,670 +0,0 @@
1−-- |
2−-- Module : Streamly.Internal.Data.Stream.Bottom
3−-- Copyright : (c) 2017 Composewell Technologies
4−-- License : BSD-3-Clause
5−-- Maintainer : streamly@composewell.com
6−-- Stability : experimental
7−-- Portability : GHC
8−--
9−-- Bottom level Stream module that can be used by all other upper level
10−-- Stream modules.
11−
12−module Streamly.Internal.Data.Stream.Bottom
13− (
14− -- * Generation
15− fromPure
16− , fromEffect
17− , fromList
18− , timesWith
19− , absTimesWith
20− , relTimesWith
21−
22− -- * Folds
23− , fold
24− , foldBreak
25− , foldBreak2
26− , foldEither
27− , foldEither2
28− , foldConcat
29−
30− -- * Builders
31− , foldAdd
32− , foldAddLazy
33−
34− -- * Scans
35− , smapM
36− -- $smapM_Notes
37− , postscan
38− , catMaybes
39− , scanMaybe
40−
41− , take
42− , takeWhile
43− , takeEndBy
44− , drop
45− , findIndices
46−
47− -- * Merge
48− , intersperseM
49−
50− -- * Fold and Unfold
51− , reverse
52− , reverse'
53−
54− -- * Expand
55− , concatEffect
56− , concatEffect2
57− , concatMapM
58− , concatMap
59−
60− -- * Reduce
61− , foldManyPost
62−
63− -- * Zipping
64− , zipWithM
65− , zipWith
66− )
67−where
68−
69−#include "inline.hs"
70−
71−import Control.Monad.IO.Class (MonadIO(..))
72−import GHC.Types (SPEC(..))
73−import Streamly.Internal.Data.Fold.Type (Fold (..))
74−import Streamly.Internal.Data.Time.Units (AbsTime, RelTime64, addToAbsTime64)
75−import Streamly.Internal.Data.Unbox (Unbox)
76−import Streamly.Internal.Data.Producer.Type (Producer(..))
77−import Streamly.Internal.System.IO (defaultChunkSize)
78−import Streamly.Internal.Data.SVar.Type (defState)
79−
80−import qualified Streamly.Internal.Data.Array.Type as A
81−import qualified Streamly.Internal.Data.Fold as Fold
82−import qualified Streamly.Internal.Data.StreamK as K
83−import qualified Streamly.Internal.Data.Stream as D
84−
85−import Prelude hiding (take, takeWhile, drop, reverse, concatMap, map, zipWith)
86−
87−import Streamly.Internal.Data.Stream.Type
88−
89−--
90−-- $setup
91−-- >>> :m
92−-- >>> import Control.Monad (join, (>=>), (<=<))
93−-- >>> import Data.Function (fix, (&))
94−-- >>> import Data.Functor.Identity (Identity)
95−-- >>> import Data.Maybe (fromJust, isJust)
96−-- >>> import Prelude hiding (take, takeWhile, drop, reverse)
97−-- >>> import Streamly.Data.Array (Array)
98−-- >>> import Streamly.Data.Fold (Fold)
99−-- >>> import Streamly.Data.Stream (Stream)
100−-- >>> import System.IO.Unsafe (unsafePerformIO)
101−-- >>> import qualified Streamly.Data.Array as Array
102−-- >>> import qualified Streamly.Data.MutArray as MArray
103−-- >>> import qualified Streamly.Data.Fold as Fold
104−-- >>> import qualified Streamly.Data.Parser as Parser
105−-- >>> import qualified Streamly.Data.Unfold as Unfold
106−-- >>> import qualified Streamly.Internal.Data.Fold as Fold (toStream)
107−-- >>> import Streamly.Internal.Data.Stream as Stream
108−
109−------------------------------------------------------------------------------
110−-- Generation - Time related
111−------------------------------------------------------------------------------
112−
113−-- | @timesWith g@ returns a stream of time value tuples. The first component
114−-- of the tuple is an absolute time reference (epoch) denoting the start of the
115−-- stream and the second component is a time relative to the reference.
116−--
117−-- The argument @g@ specifies the granularity of the relative time in seconds.
118−-- A lower granularity clock gives higher precision but is more expensive in
119−-- terms of CPU usage. Any granularity lower than 1 ms is treated as 1 ms.
120−--
121−-- >>> import Control.Concurrent (threadDelay)
122−-- >>> f = Fold.drainMapM (\x -> print x >> threadDelay 1000000)
123−-- >>> Stream.fold f $ Stream.take 3 $ Stream.timesWith 0.01
124−-- (AbsTime (TimeSpec {sec = ..., nsec = ...}),RelTime64 (NanoSecond64 ...))
125−-- (AbsTime (TimeSpec {sec = ..., nsec = ...}),RelTime64 (NanoSecond64 ...))
126−-- (AbsTime (TimeSpec {sec = ..., nsec = ...}),RelTime64 (NanoSecond64 ...))
127−--
128−-- Note: This API is not safe on 32-bit machines.
129−--
130−-- /Pre-release/
131−--
132−{-# INLINE timesWith #-}
133−timesWith :: MonadIO m => Double -> Stream m (AbsTime, RelTime64)
134−timesWith g = fromStreamD $ D.timesWith g
135−
136−-- | @absTimesWith g@ returns a stream of absolute timestamps using a clock of
137−-- granularity @g@ specified in seconds. A low granularity clock is more
138−-- expensive in terms of CPU usage. Any granularity lower than 1 ms is treated
139−-- as 1 ms.
140−--
141−-- >>> f = Fold.drainMapM print
142−-- >>> Stream.fold f $ Stream.delayPre 1 $ Stream.take 3 $ Stream.absTimesWith 0.01
143−-- AbsTime (TimeSpec {sec = ..., nsec = ...})
144−-- AbsTime (TimeSpec {sec = ..., nsec = ...})
145−-- AbsTime (TimeSpec {sec = ..., nsec = ...})
146−--
147−-- Note: This API is not safe on 32-bit machines.
148−--
149−-- /Pre-release/
150−--
151−{-# INLINE absTimesWith #-}
152−absTimesWith :: MonadIO m => Double -> Stream m AbsTime
153−absTimesWith = fmap (uncurry addToAbsTime64) . timesWith
154−
155−-- | @relTimesWith g@ returns a stream of relative time values starting from 0,
156−-- using a clock of granularity @g@ specified in seconds. A low granularity
157−-- clock is more expensive in terms of CPU usage. Any granularity lower than 1
158−-- ms is treated as 1 ms.
159−--
160−-- >>> f = Fold.drainMapM print
161−-- >>> Stream.fold f $ Stream.delayPre 1 $ Stream.take 3 $ Stream.relTimesWith 0.01
162−-- RelTime64 (NanoSecond64 ...)
163−-- RelTime64 (NanoSecond64 ...)
164−-- RelTime64 (NanoSecond64 ...)
165−--
166−-- Note: This API is not safe on 32-bit machines.
167−--
168−-- /Pre-release/
169−--
170−{-# INLINE relTimesWith #-}
171−relTimesWith :: MonadIO m => Double -> Stream m RelTime64
172−relTimesWith = fmap snd . timesWith
173−
174−------------------------------------------------------------------------------
175−-- Elimination - Running a Fold
176−------------------------------------------------------------------------------
177−
178−-- | Append a stream to a fold lazily to build an accumulator incrementally.
179−--
180−-- Example, to continue folding a list of streams on the same sum fold:
181−--
182−-- >>> streams = [Stream.fromList [1..5], Stream.fromList [6..10]]
183−-- >>> f = Prelude.foldl Stream.foldAddLazy Fold.sum streams
184−-- >>> Stream.fold f Stream.nil
185−-- 55
186−--
187−{-# INLINE foldAddLazy #-}
188−foldAddLazy :: Monad m => Fold m a b -> Stream m a -> Fold m a b
189−foldAddLazy f s = D.foldAddLazy f $ toStreamD s
190−
191−-- >>> foldAdd f = Stream.foldAddLazy f >=> Fold.reduce
192−
193−-- |
194−-- >>> foldAdd = flip Fold.addStream
195−--
196−foldAdd :: Monad m => Fold m a b -> Stream m a -> m (Fold m a b)
197−foldAdd f = fold (Fold.duplicate f)
198−
199−-- >>> fold f = Fold.extractM . Stream.foldAddLazy f
200−-- >>> fold f = Stream.fold Fold.one . Stream.foldManyPost f
201−-- >>> fold f = Fold.extractM <=< Stream.foldAdd f
202−
203−-- | Fold a stream using the supplied left 'Fold' and reducing the resulting
204−-- expression strictly at each step. The behavior is similar to 'foldl''. A
205−-- 'Fold' can terminate early without consuming the full stream. See the
206−-- documentation of individual 'Fold's for termination behavior.
207−--
208−-- Definitions:
209−--
210−-- >>> fold f = fmap fst . Stream.foldBreak f
211−-- >>> fold f = Stream.parse (Parser.fromFold f)
212−--
213−-- Example:
214−--
215−-- >>> Stream.fold Fold.sum (Stream.enumerateFromTo 1 100)
216−-- 5050
217−--
218−{-# INLINE fold #-}
219−fold :: Monad m => Fold m a b -> Stream m a -> m b
220−fold fl strm = D.fold fl $ D.fromStreamK $ toStreamK strm
221−
222−-- Alternative name foldSome, but may be confused vs foldMany.
223−
224−-- | Like 'fold' but also returns the remaining stream. The resulting stream
225−-- would be 'Stream.nil' if the stream finished before the fold.
226−--
227−-- /CPS/
228−--
229−{-# INLINE foldBreak #-}
230−foldBreak :: Monad m => Fold m a b -> Stream m a -> m (b, Stream m a)
231−foldBreak fl strm = fmap f $ K.foldBreak fl (toStreamK strm)
232−
233− where
234−
235− f (b, str) = (b, fromStreamK str)
236−
237−-- XXX The quadratic slowdown in recursive use is because recursive function
238−-- cannot be inlined and StreamD/StreamK conversions pile up and cannot be
239−-- eliminated by rewrite rules.
240−
241−-- | Like 'foldBreak' but fuses.
242−--
243−-- /Note:/ Unlike 'foldBreak', recursive application on the resulting stream
244−-- would lead to quadratic slowdown. If you need recursion with fusion (within
245−-- one iteration of recursion) use StreamD.foldBreak directly.
246−--
247−-- /Internal/
248−{-# INLINE foldBreak2 #-}
249−foldBreak2 :: Monad m => Fold m a b -> Stream m a -> m (b, Stream m a)
250−foldBreak2 fl strm = fmap f $ D.foldBreak fl $ toStreamD strm
251−
252− where
253−
254− f (b, str) = (b, fromStreamD str)
255−
256−-- | Fold resulting in either breaking the stream or continuation of the fold.
257−-- Instead of supplying the input stream in one go we can run the fold multiple
258−-- times, each time supplying the next segment of the input stream. If the fold
259−-- has not yet finished it returns a fold that can be run again otherwise it
260−-- returns the fold result and the residual stream.
261−--
262−-- /Internal/
263−{-# INLINE foldEither #-}
264−foldEither :: Monad m =>
265− Fold m a b -> Stream m a -> m (Either (Fold m a b) (b, Stream m a))
266−foldEither fl strm = fmap (fmap f) $ K.foldEither fl $ toStreamK strm
267−
268− where
269−
270− f (b, str) = (b, fromStreamK str)
271−
272−-- | Like 'foldEither' but fuses. However, recursive application on resulting
273−-- stream would lead to quadratic slowdown.
274−--
275−-- /Internal/
276−{-# INLINE foldEither2 #-}
277−foldEither2 :: Monad m =>
278− Fold m a b -> Stream m a -> m (Either (Fold m a b) (b, Stream m a))
279−foldEither2 fl strm = fmap (fmap f) $ D.foldEither fl $ toStreamD strm
280−
281− where
282−
283− f (b, str) = (b, fromStreamD str)
284−
285−-- XXX Array folds can be implemented using this.
286−-- foldContainers? Specialized to foldArrays.
287−
288−-- | Generate streams from individual elements of a stream and fold the
289−-- concatenation of those streams using the supplied fold. Return the result of
290−-- the fold and residual stream.
291−--
292−-- For example, this can be used to efficiently fold an Array Word8 stream
293−-- using Word8 folds.
294−--
295−-- The outer stream forces CPS to allow scalable appends and the inner stream
296−-- forces direct style for stream fusion.
297−--
298−-- /Internal/
299−{-# INLINE foldConcat #-}
300−foldConcat :: Monad m =>
301− Producer m a b -> Fold m b c -> Stream m a -> m (c, Stream m a)
302−foldConcat
303− (Producer pstep pinject pextract)
304− (Fold fstep begin done)
305− stream = do
306−
307− res <- begin
308− case res of
309− Fold.Partial fs -> go fs streamK
310− Fold.Done fb -> return (fb, fromStreamK streamK)
311−
312− where
313−
314− streamK = toStreamK stream
315−
316− go !acc m1 = do
317− let stop = do
318− r <- done acc
319− return (r, fromStreamK K.nil)
320− single a = do
321− st <- pinject a
322− res <- go1 SPEC acc st
323− case res of
324− Left fs -> do
325− r <- done fs
326− return (r, fromStreamK K.nil)
327− Right (b, s) -> do
328− x <- pextract s
329− return (b, fromStreamK (K.fromPure x))
330− yieldk a r = do
331− st <- pinject a
332− res <- go1 SPEC acc st
333− case res of
334− Left fs -> go fs r
335− Right (b, s) -> do
336− x <- pextract s
337− return (b, fromStreamK (x `K.cons` r))
338− in K.foldStream defState yieldk single stop m1
339−
340− {-# INLINE go1 #-}
341− go1 !_ !fs st = do
342− r <- pstep st
343− case r of
344− D.Yield x s -> do
345− res <- fstep fs x
346− case res of
347− Fold.Done b -> return $ Right (b, s)
348− Fold.Partial fs1 -> go1 SPEC fs1 s
349− D.Skip s -> go1 SPEC fs s
350− D.Stop -> return $ Left fs
351−
352−------------------------------------------------------------------------------
353−-- Transformation
354−------------------------------------------------------------------------------
355−
356−{-
357−-- |
358−-- >>> map = fmap
359−--
360−-- Same as 'fmap'.
361−--
362−-- >>> Stream.fold Fold.toList $ fmap (+1) $ Stream.fromList [1,2,3]
363−-- [2,3,4]
364−--
365−{-# INLINE map #-}
366−map :: Monad m => (a -> b) -> Stream m a -> Stream m b
367−map f = fromStreamD . D.map f . toStreamD
368−-}
369−
370−-- | Postscan a stream using the given monadic fold.
371−--
372−-- The following example extracts the input stream up to a point where the
373−-- running average of elements is no more than 10:
374−--
375−-- >>> import Data.Maybe (fromJust)
376−-- >>> let avg = Fold.teeWith (/) Fold.sum (fmap fromIntegral Fold.length)
377−-- >>> s = Stream.enumerateFromTo 1.0 100.0
378−-- >>> :{
379−-- Stream.fold Fold.toList
380−-- $ fmap (fromJust . fst)
381−-- $ Stream.takeWhile (\(_,x) -> x <= 10)
382−-- $ Stream.postscan (Fold.tee Fold.latest avg) s
383−-- :}
384−-- [1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0,16.0,17.0,18.0,19.0]
385−--
386−{-# INLINE postscan #-}
387−postscan :: Monad m => Fold m a b -> Stream m a -> Stream m b
388−postscan fld = fromStreamD . D.postscan fld . toStreamD
389−
390−-- $smapM_Notes
391−--
392−-- The stateful step function can be simplified to @(s -> a -> m b)@ to provide
393−-- a read-only environment. However, that would just be 'mapM'.
394−--
395−-- The initial action could be @m (s, Maybe b)@, and we can also add a final
396−-- action @s -> m (Maybe b)@. This can be used to get pre/post scan like
397−-- functionality and also to flush the state in the end like scanlMAfter'.
398−-- We can also use it along with a fusible version of bracket to get
399−-- scanlMAfter' like functionality. See issue #677.
400−--
401−-- This can be further generalized to a type similar to Fold/Parser, giving it
402−-- filtering and parsing capability as well (this is in fact equivalent to
403−-- parseMany):
404−--
405−-- smapM :: (s -> a -> m (Step s b)) -> m s -> Stream m a -> Stream m b
406−--
407−
408−-- | A stateful 'mapM', equivalent to a left scan, more like mapAccumL.
409−-- Hopefully, this is a better alternative to @scan@. Separation of state from
410−-- the output makes it easier to think in terms of a shared state, and also
411−-- makes it easier to keep the state fully strict and the output lazy.
412−--
413−-- See also: 'postscan'
414−--
415−-- /Pre-release/
416−--
417−{-# INLINE smapM #-}
418−smapM :: Monad m =>
419− (s -> a -> m (s, b))
420− -> m s
421− -> Stream m a
422− -> Stream m b
423−smapM step initial stream =
424− -- XXX implement this directly instead of using postscan
425− let f = Fold.foldlM'
426− (\(s, _) a -> step s a)
427− (fmap (,undefined) initial)
428− in fmap snd $ postscan f stream
429−
430−-- | In a stream of 'Maybe's, discard 'Nothing's and unwrap 'Just's.
431−--
432−-- >>> catMaybes = Stream.mapMaybe id
433−-- >>> catMaybes = fmap fromJust . Stream.filter isJust
434−--
435−-- /Pre-release/
436−--
437−{-# INLINE catMaybes #-}
438−catMaybes :: Monad m => Stream m (Maybe a) -> Stream m a
439−-- catMaybes = fmap fromJust . filter isJust
440−catMaybes = fromStreamD . D.catMaybes . toStreamD
441−
442−-- | Use a filtering fold on a stream.
443−--
444−-- >>> scanMaybe f = Stream.catMaybes . Stream.postscan f
445−--
446−{-# INLINE scanMaybe #-}
447−scanMaybe :: Monad m => Fold m a (Maybe b) -> Stream m a -> Stream m b
448−scanMaybe p = catMaybes . postscan p
449−
450−------------------------------------------------------------------------------
451−-- Transformation - Trimming
452−------------------------------------------------------------------------------
453−
454−-- | Take first 'n' elements from the stream and discard the rest.
455−--
456−{-# INLINE take #-}
457−take :: Monad m => Int -> Stream m a -> Stream m a
458−-- take n = scanMaybe (Fold.taking n)
459−take n m = fromStreamD $ D.take n $ toStreamD m
460−
461−-- | End the stream as soon as the predicate fails on an element.
462−--
463−{-# INLINE takeWhile #-}
464−takeWhile :: Monad m => (a -> Bool) -> Stream m a -> Stream m a
465−-- takeWhile p = scanMaybe (Fold.takingEndBy_ (not . p))
466−takeWhile p m = fromStreamD $ D.takeWhile p $ toStreamD m
467−
468−{-# INLINE takeEndBy #-}
469−takeEndBy :: Monad m => (a -> Bool) -> Stream m a -> Stream m a
470−-- takeEndBy p = scanMaybe (Fold.takingEndBy p)
471−takeEndBy p m = fromStreamD $ D.takeEndBy p $ toStreamD m
472−
473−-- | Discard first 'n' elements from the stream and take the rest.
474−--
475−{-# INLINE drop #-}
476−drop :: Monad m => Int -> Stream m a -> Stream m a
477−-- drop n = scanMaybe (Fold.dropping n)
478−drop n m = fromStreamD $ D.drop n $ toStreamD m
479−
480−------------------------------------------------------------------------------
481−-- Searching
482−------------------------------------------------------------------------------
483−
484−-- | Find all the indices where the element in the stream satisfies the given
485−-- predicate.
486−--
487−-- >>> findIndices p = Stream.scanMaybe (Fold.findIndices p)
488−--
489−{-# INLINE findIndices #-}
490−findIndices :: Monad m => (a -> Bool) -> Stream m a -> Stream m Int
491−-- findIndices p = scanMaybe (Fold.findIndices p)
492−findIndices p m = fromStreamD $ D.findIndices p (toStreamD m)
493−
494−------------------------------------------------------------------------------
495−-- Transformation by Inserting
496−------------------------------------------------------------------------------
497−
498−-- intersperseM = intersperseMWith 1
499−
500−-- | Insert an effect and its output before consuming an element of a stream
501−-- except the first one.
502−--
503−-- >>> input = Stream.fromList "hello"
504−-- >>> Stream.fold Fold.toList $ Stream.trace putChar $ Stream.intersperseM (putChar '.' >> return ',') input
505−-- h.,e.,l.,l.,o"h,e,l,l,o"
506−--
507−-- Be careful about the order of effects. In the above example we used trace
508−-- after the intersperse, if we use it before the intersperse the output would
509−-- be he.l.l.o."h,e,l,l,o".
510−--
511−-- >>> Stream.fold Fold.toList $ Stream.intersperseM (putChar '.' >> return ',') $ Stream.trace putChar input
512−-- he.l.l.o."h,e,l,l,o"
513−--
514−{-# INLINE intersperseM #-}
515−intersperseM :: Monad m => m a -> Stream m a -> Stream m a
516−intersperseM m = fromStreamD . D.intersperseM m . toStreamD
517−
518−------------------------------------------------------------------------------
519−-- Transformation by Reordering
520−------------------------------------------------------------------------------
521−
522−-- XXX Use a compact region list to temporarily store the list, in both reverse
523−-- as well as in reverse'.
524−--
525−-- /Note:/ 'reverse'' is much faster than this, use that when performance
526−-- matters.
527−--
528−-- | Returns the elements of the stream in reverse order. The stream must be
529−-- finite. Note that this necessarily buffers the entire stream in memory.
530−--
531−-- >>> reverse = Stream.foldlT (flip Stream.cons) Stream.nil
532−--
533−{-# INLINE reverse #-}
534−reverse :: Stream m a -> Stream m a
535−reverse s = fromStreamK $ K.reverse $ toStreamK s
536−
537−-- | Like 'reverse' but several times faster, requires a 'Storable' instance.
538−--
539−-- /O(n) space/
540−--
541−-- /Pre-release/
542−{-# INLINE reverse' #-}
543−reverse' :: (MonadIO m, Unbox a) => Stream m a -> Stream m a
544−-- reverse' s = fromStreamD $ D.reverse' $ toStreamD s
545−reverse' =
546− fromStreamD
547− . A.flattenArraysRev -- unfoldMany A.readRev
548− . D.fromStreamK
549− . K.reverse
550− . D.toStreamK
551− . A.chunksOf defaultChunkSize
552− . toStreamD
553−
554−------------------------------------------------------------------------------
555−-- Combine streams and flatten
556−------------------------------------------------------------------------------
557−
558−-- | Map a stream producing monadic function on each element of the stream
559−-- and then flatten the results into a single stream. Since the stream
560−-- generation function is monadic, unlike 'concatMap', it can produce an
561−-- effect at the beginning of each iteration of the inner loop.
562−--
563−-- See 'unfoldMany' for a fusible alternative.
564−--
565−{-# INLINE concatMapM #-}
566−concatMapM :: Monad m => (a -> m (Stream m b)) -> Stream m a -> Stream m b
567−concatMapM f m = fromStreamD $ D.concatMapM (fmap toStreamD . f) (toStreamD m)
568−
569−-- | Map a stream producing function on each element of the stream and then
570−-- flatten the results into a single stream.
571−--
572−-- >>> concatMap f = Stream.concatMapM (return . f)
573−-- >>> concatMap f = Stream.concatMapWith Stream.append f
574−-- >>> concatMap f = Stream.concat . fmap f
575−-- >>> concatMap f = Stream.unfoldMany (Unfold.lmap f Unfold.fromStream)
576−--
577−-- See 'unfoldMany' for a fusible alternative.
578−--
579−{-# INLINE concatMap #-}
580−concatMap ::Monad m => (a -> Stream m b) -> Stream m a -> Stream m b
581−concatMap f m = fromStreamD $ D.concatMap (toStreamD . f) (toStreamD m)
582−
583−-- >>> concatEffect = Stream.concat . lift -- requires (MonadTrans t)
584−-- >>> concatEffect = join . lift -- requires (MonadTrans t, Monad (Stream m))
585−
586−-- | Given a stream value in the underlying monad, lift and join the underlying
587−-- monad with the stream monad.
588−--
589−-- >>> concatEffect = Stream.concat . Stream.fromEffect
590−--
591−-- See also: 'concat', 'sequence'
592−--
593−-- See 'concatEffect2' for a fusible alternative.
594−--
595−-- /CPS/
596−--
597−{-# INLINE concatEffect #-}
598−concatEffect :: Monad m => m (Stream m a) -> Stream m a
599−concatEffect generator =
600− fromStreamK $ K.concatEffect $ fmap toStreamK generator
601−
602−{-# INLINE concatEffect2 #-}
603−concatEffect2 :: Monad m => m (Stream m a) -> Stream m a
604−-- concatEffect generator = concatMapM (\() -> generator) (fromPure ())
605−concatEffect2 generator =
606− fromStreamD $ D.concatEffect $ fmap toStreamD generator
607−
608−-- XXX Need a more intuitive name, and need to reconcile the names
609−-- foldMany/fold/parse/parseMany/parseManyPost etc.
610−
611−-- | Like 'foldMany' but evaluates the fold before the stream, and yields its
612−-- output even if the stream is empty, therefore, always results in a non-empty
613−-- output even on an empty stream (default result of the fold).
614−--
615−-- Example, empty stream:
616−--
617−-- >>> f = Fold.take 2 Fold.sum
618−-- >>> fmany = Stream.fold Fold.toList . Stream.foldManyPost f
619−-- >>> fmany $ Stream.fromList []
620−-- [0]
621−--
622−-- Example, last fold empty:
623−--
624−-- >>> fmany $ Stream.fromList [1..4]
625−-- [3,7,0]
626−--
627−-- Example, last fold non-empty:
628−--
629−-- >>> fmany $ Stream.fromList [1..5]
630−-- [3,7,5]
631−--
632−-- Note that using a closed fold e.g. @Fold.take 0@, would result in an
633−-- infinite stream without consuming the input.
634−--
635−-- /Pre-release/
636−--
637−{-# INLINE foldManyPost #-}
638−foldManyPost
639− :: Monad m
640− => Fold m a b
641− -> Stream m a
642− -> Stream m b
643−foldManyPost f m = fromStreamD $ D.foldManyPost f (toStreamD m)
644−
645−------------------------------------------------------------------------------
646−-- Zipping
647−------------------------------------------------------------------------------
648−
649−-- | Like 'zipWith' but using a monadic zipping function.
650−--
651−{-# INLINE zipWithM #-}
652−zipWithM :: Monad m =>
653− (a -> b -> m c) -> Stream m a -> Stream m b -> Stream m c
654−zipWithM f m1 m2 = fromStreamK $ K.zipWithM f (toStreamK m1) (toStreamK m2)
655−
656−-- | Stream @a@ is evaluated first, followed by stream @b@, the resulting
657−-- elements @a@ and @b@ are then zipped using the supplied zip function and the
658−-- result @c@ is yielded to the consumer.
659−--
660−-- If stream @a@ or stream @b@ ends, the zipped stream ends. If stream @b@ ends
661−-- first, the element @a@ from previous evaluation of stream @a@ is discarded.
662−--
663−-- >>> s1 = Stream.fromList [1,2,3]
664−-- >>> s2 = Stream.fromList [4,5,6]
665−-- >>> Stream.fold Fold.toList $ Stream.zipWith (+) s1 s2
666−-- [5,7,9]
667−--
668−{-# INLINE zipWith #-}
669−zipWith :: Monad m => (a -> b -> c) -> Stream m a -> Stream m b -> Stream m c
670−zipWith f m1 m2 = fromStreamK $ K.zipWith f (toStreamK m1) (toStreamK m2)
core/src/Streamly/Internal/Data/Stream/Cross.hsdeleted−143
@@ -1,143 +0,0 @@
1−{-# LANGUAGE UndecidableInstances #-}
2−
3−-- |
4−-- Module : Streamly.Internal.Data.Stream.Cross
5−-- Copyright : (c) 2017 Composewell Technologies
6−--
7−-- License : BSD3
8−-- Maintainer : streamly@composewell.com
9−-- Stability : experimental
10−-- Portability : GHC
11−--
12−module Streamly.Internal.Data.Stream.Cross
13− (
14− CrossStream (..)
15− )
16−where
17−
18−import Control.Monad.Catch (MonadThrow, throwM)
19−import Control.Monad.Trans.Class (MonadTrans(lift))
20−import Control.Applicative (liftA2)
21−import Control.Monad.IO.Class (MonadIO(..))
22−import Data.Functor.Identity (Identity(..))
23−import GHC.Exts (IsList(..), IsString(..))
24−import Streamly.Internal.Data.Stream.Type (Stream)
25−
26−import qualified Streamly.Internal.Data.Stream.Type as Stream
27−import qualified Streamly.Internal.Data.Stream.StreamK.Type as K
28−
29−-- $setup
30−-- >>> import Streamly.Internal.Data.Stream.Cross (CrossStream(..))
31−-- >>> import qualified Streamly.Data.Fold as Fold
32−-- >>> import qualified Streamly.Data.Stream as Stream
33−
34−------------------------------------------------------------------------------
35−-- Stream with a cross product style monad instance
36−------------------------------------------------------------------------------
37−
38−-- | A newtype wrapper for the 'Stream' type with a cross product style monad
39−-- instance.
40−--
41−-- Semigroup instance appends two streams.
42−--
43−-- A 'Monad' bind behaves like a @for@ loop:
44−--
45−-- >>> :{
46−-- Stream.fold Fold.toList $ unCrossStream $ do
47−-- x <- CrossStream (Stream.fromList [1,2]) -- foreach x in stream
48−-- return x
49−-- :}
50−-- [1,2]
51−--
52−-- Nested monad binds behave like nested @for@ loops:
53−--
54−-- >>> :{
55−-- Stream.fold Fold.toList $ unCrossStream $ do
56−-- x <- CrossStream (Stream.fromList [1,2]) -- foreach x in stream
57−-- y <- CrossStream (Stream.fromList [3,4]) -- foreach y in stream
58−-- return (x, y)
59−-- :}
60−-- [(1,3),(1,4),(2,3),(2,4)]
61−--
62−newtype CrossStream m a = CrossStream {unCrossStream :: Stream m a}
63− deriving (Functor, Semigroup, Monoid, Foldable)
64−
65−-- Pure (Identity monad) stream instances
66−deriving instance Traversable (CrossStream Identity)
67−deriving instance IsList (CrossStream Identity a)
68−deriving instance (a ~ Char) => IsString (CrossStream Identity a)
69−deriving instance Eq a => Eq (CrossStream Identity a)
70−deriving instance Ord a => Ord (CrossStream Identity a)
71−deriving instance Show a => Show (CrossStream Identity a)
72−deriving instance Read a => Read (CrossStream Identity a)
73−
74−------------------------------------------------------------------------------
75−-- Applicative
76−------------------------------------------------------------------------------
77−
78−-- Note: we need to define all the typeclass operations because we want to
79−-- INLINE them.
80−instance Monad m => Applicative (CrossStream m) where
81− {-# INLINE pure #-}
82− pure x = CrossStream (Stream.fromPure x)
83−
84− {-# INLINE (<*>) #-}
85− (CrossStream s1) <*> (CrossStream s2) =
86− CrossStream (Stream.crossApply s1 s2)
87− -- (<*>) = K.crossApply
88−
89− {-# INLINE liftA2 #-}
90− liftA2 f x = (<*>) (fmap f x)
91−
92− {-# INLINE (*>) #-}
93− (CrossStream s1) *> (CrossStream s2) =
94− CrossStream (Stream.crossApplySnd s1 s2)
95− -- (*>) = K.crossApplySnd
96−
97− {-# INLINE (<*) #-}
98− (CrossStream s1) <* (CrossStream s2) =
99− CrossStream (Stream.crossApplyFst s1 s2)
100− -- (<*) = K.crossApplyFst
101−
102−------------------------------------------------------------------------------
103−-- Monad
104−------------------------------------------------------------------------------
105−
106−instance Monad m => Monad (CrossStream m) where
107− return = pure
108−
109− -- Benchmarks better with StreamD bind and pure:
110− -- toList, filterAllout, *>, *<, >> (~2x)
111− --
112− -- pure = Stream . D.fromStreamD . D.fromPure
113− -- m >>= f = D.fromStreamD $ D.concatMap (D.toStreamD . f) (D.toStreamD m)
114−
115− -- Benchmarks better with CPS bind and pure:
116− -- Prime sieve (25x)
117− -- n binds, breakAfterSome, filterAllIn, state transformer (~2x)
118− --
119− {-# INLINE (>>=) #-}
120− (>>=) (CrossStream m) f =
121− CrossStream
122− (Stream.fromStreamK
123− $ K.bindWith
124− K.append
125− (Stream.toStreamK m)
126− (Stream.toStreamK . unCrossStream . f))
127−
128− {-# INLINE (>>) #-}
129− (>>) = (*>)
130−
131−------------------------------------------------------------------------------
132−-- Transformers
133−------------------------------------------------------------------------------
134−
135−instance (MonadIO m) => MonadIO (CrossStream m) where
136− liftIO x = CrossStream (Stream.fromEffect $ liftIO x)
137−
138−instance MonadTrans CrossStream where
139− {-# INLINE lift #-}
140− lift x = CrossStream (Stream.fromEffect x)
141−
142−instance (MonadThrow m) => MonadThrow (CrossStream m) where
143− throwM = lift . throwM
core/src/Streamly/Internal/Data/Stream/Eliminate.hsdeleted−377
@@ -1,377 +0,0 @@
1−-- |
2−-- Module : Streamly.Internal.Data.Stream.Eliminate
3−-- Copyright : (c) 2017 Composewell Technologies
4−-- License : BSD-3-Clause
5−-- Maintainer : streamly@composewell.com
6−-- Stability : experimental
7−-- Portability : GHC
8−--
9−-- This module contains functions ending in the shape:
10−--
11−-- @
12−-- Stream m a -> m b
13−-- @
14−--
15−-- We call them stream folding functions, they reduce a stream @Stream m a@ to
16−-- a monadic value @m b@.
17−
18−module Streamly.Internal.Data.Stream.Eliminate
19− (
20− -- * Running Examples
21− -- $setup
22−
23− -- * Running a 'Fold'
24− -- See "Streamly.Internal.Data.Fold".
25− fold
26− , foldBreak
27− , foldBreak2
28− , foldEither
29− , foldEither2
30− , foldConcat
31−
32− -- * Builders
33− , foldAdd
34− , foldAddLazy
35−
36− -- * Running a 'Parser'
37− -- "Streamly.Internal.Data.Parser".
38− , parse
39− --, parseK
40− , parseD
41− --, parseBreak
42− , parseBreakD
43−
44− -- * Stream Deconstruction
45− -- | foldr and foldl do not provide the remaining stream. 'uncons' is more
46− -- general, as it can be used to implement those as well. It allows to use
47− -- the stream one element at a time, and we have the remaining stream all
48− -- the time.
49− , uncons
50− , init
51−
52− -- * Right Folds
53− , foldrM
54− , foldr
55−
56− -- * Left Folds
57− -- Lazy left folds are useful only for reversing the stream
58− , foldlS
59−
60− -- * Multi-Stream folds
61− -- Full equivalence
62− , eqBy
63− , cmpBy
64−
65− -- finding subsequences
66− , isPrefixOf
67− , isInfixOf
68− , isSuffixOf
69− , isSubsequenceOf
70−
71− -- trimming sequences
72− , stripPrefix
73− -- , stripInfix
74− , stripSuffix
75− )
76−where
77−
78−#include "inline.hs"
79−
80−import Control.Monad.IO.Class (MonadIO(..))
81−import Foreign.Storable (Storable)
82−import Streamly.Internal.Data.Parser (Parser (..), ParseError (..))
83−import Streamly.Internal.Data.Unbox (Unbox)
84−import Streamly.Internal.Data.Stream.Type (Stream)
85−
86−import qualified Streamly.Internal.Data.Array.Type as Array
87−import qualified Streamly.Internal.Data.Fold as Fold
88−import qualified Streamly.Internal.Data.Parser as PRD
89−import qualified Streamly.Internal.Data.Parser.ParserK.Type as PRK
90−import qualified Streamly.Internal.Data.Stream as D
91−import qualified Streamly.Internal.Data.Stream.StreamK.Type as K
92−import qualified Streamly.Internal.Data.StreamK as K
93−
94−import Streamly.Internal.Data.Stream.Bottom
95−import Streamly.Internal.Data.Stream.Type hiding (Stream)
96−
97−import Prelude hiding (foldr, init, reverse)
98−
99−-- $setup
100−-- >>> :m
101−-- >>> import Streamly.Internal.Data.Stream (Stream)
102−-- >>> import qualified Streamly.Internal.Data.Stream as Stream
103−-- >>> import qualified Streamly.Internal.Data.Parser as Parser
104−-- >>> import qualified Streamly.Internal.Data.Fold as Fold
105−-- >>> import qualified Streamly.Internal.Data.Unfold as Unfold
106−
107−------------------------------------------------------------------------------
108−-- Deconstruction
109−------------------------------------------------------------------------------
110−
111−-- | Decompose a stream into its head and tail. If the stream is empty, returns
112−-- 'Nothing'. If the stream is non-empty, returns @Just (a, ma)@, where @a@ is
113−-- the head of the stream and @ma@ its tail.
114−--
115−-- Properties:
116−--
117−-- >>> Nothing <- Stream.uncons Stream.nil
118−-- >>> Just ("a", t) <- Stream.uncons (Stream.cons "a" Stream.nil)
119−--
120−-- This can be used to consume the stream in an imperative manner one element
121−-- at a time, as it just breaks down the stream into individual elements and we
122−-- can loop over them as we deem fit. For example, this can be used to convert
123−-- a streamly stream into other stream types.
124−--
125−-- All the folds in this module can be expressed in terms of 'uncons', however,
126−-- this is generally less efficient than specific folds because it takes apart
127−-- the stream one element at a time, therefore, does not take adavantage of
128−-- stream fusion.
129−--
130−-- 'foldBreak' is a more general way of consuming a stream piecemeal.
131−--
132−-- >>> :{
133−-- uncons xs = do
134−-- r <- Stream.foldBreak Fold.one xs
135−-- return $ case r of
136−-- (Nothing, _) -> Nothing
137−-- (Just h, t) -> Just (h, t)
138−-- :}
139−--
140−-- /CPS/
141−--
142−{-# INLINE uncons #-}
143−uncons :: Monad m => Stream m a -> m (Maybe (a, Stream m a))
144−uncons m = fmap (fmap (fmap fromStreamK)) $ K.uncons (toStreamK m)
145−
146−-- | Extract all but the last element of the stream, if any.
147−--
148−-- Note: This will end up buffering the entire stream.
149−--
150−-- /Pre-release/
151−{-# INLINE init #-}
152−init :: Monad m => Stream m a -> m (Maybe (Stream m a))
153−init m = fmap (fmap fromStreamK) $ K.init $ toStreamK m
154−
155−------------------------------------------------------------------------------
156−-- Right Folds
157−------------------------------------------------------------------------------
158−
159−-- | Right associative/lazy pull fold. @foldrM build final stream@ constructs
160−-- an output structure using the step function @build@. @build@ is invoked with
161−-- the next input element and the remaining (lazy) tail of the output
162−-- structure. It builds a lazy output expression using the two. When the "tail
163−-- structure" in the output expression is evaluated it calls @build@ again thus
164−-- lazily consuming the input @stream@ until either the output expression built
165−-- by @build@ is free of the "tail" or the input is exhausted in which case
166−-- @final@ is used as the terminating case for the output structure. For more
167−-- details see the description in the previous section.
168−--
169−-- Example, determine if any element is 'odd' in a stream:
170−--
171−-- >>> s = Stream.fromList (2:4:5:undefined)
172−-- >>> step x xs = if odd x then return True else xs
173−-- >>> Stream.foldrM step (return False) s
174−-- True
175−--
176−{-# INLINE foldrM #-}
177−foldrM :: Monad m => (a -> m b -> m b) -> m b -> Stream m a -> m b
178−foldrM step acc m = D.foldrM step acc $ toStreamD m
179−
180−-- | Right fold, lazy for lazy monads and pure streams, and strict for strict
181−-- monads.
182−--
183−-- Please avoid using this routine in strict monads like IO unless you need a
184−-- strict right fold. This is provided only for use in lazy monads (e.g.
185−-- Identity) or pure streams. Note that with this signature it is not possible
186−-- to implement a lazy foldr when the monad @m@ is strict. In that case it
187−-- would be strict in its accumulator and therefore would necessarily consume
188−-- all its input.
189−--
190−-- >>> foldr f z = Stream.foldrM (\a b -> f a <$> b) (return z)
191−--
192−{-# INLINE foldr #-}
193−foldr :: Monad m => (a -> b -> b) -> b -> Stream m a -> m b
194−foldr f z = foldrM (\a b -> f a <$> b) (return z)
195−
196−------------------------------------------------------------------------------
197−-- Left Folds
198−------------------------------------------------------------------------------
199−
200−-- | Lazy left fold to a stream.
201−{-# INLINE foldlS #-}
202−foldlS ::
203− (Stream m b -> a -> Stream m b) -> Stream m b -> Stream m a -> Stream m b
204−foldlS f z =
205− fromStreamK
206− . K.foldlS
207− (\xs x -> toStreamK $ f (fromStreamK xs) x)
208− (toStreamK z)
209− . toStreamK
210−
211−------------------------------------------------------------------------------
212−-- Running a Parser
213−------------------------------------------------------------------------------
214−
215−-- | Parse a stream using the supplied ParserD 'PRD.Parser'.
216−--
217−-- /Internal/
218−--
219−{-# INLINE_NORMAL parseD #-}
220−parseD :: Monad m => PRD.Parser a m b -> Stream m a -> m (Either ParseError b)
221−parseD p = D.parseD p . toStreamD
222−
223−-- XXX Drive directly as parserK rather than converting to parserD first.
224−
225−-- | Parse a stream using the supplied ParserK 'PRK.Parser'.
226−--
227−-- /Internal/
228−--{-# INLINE parseK #-}
229−--parseK :: Monad m => PRK.Parser a m b -> Stream m a -> m (Either ParseError b)
230−--parseK = parse
231−
232−-- | Parse a stream using the supplied 'Parser'.
233−--
234−-- Parsers (See "Streamly.Internal.Data.Parser") are more powerful folds that
235−-- add backtracking and error functionality to terminating folds. Unlike folds,
236−-- parsers may not always result in a valid output, they may result in an
237−-- error. For example:
238−--
239−-- >>> Stream.parse (Parser.takeEQ 1 Fold.drain) Stream.nil
240−-- Left (ParseError "takeEQ: Expecting exactly 1 elements, input terminated on 0")
241−--
242−-- Note: @parse p@ is not the same as @head . parseMany p@ on an empty stream.
243−--
244−{-# INLINE [3] parse #-}
245−parse :: Monad m => Parser a m b -> Stream m a -> m (Either ParseError b)
246−parse = parseD
247−
248−{-# INLINE_NORMAL parseBreakD #-}
249−parseBreakD :: Monad m =>
250− PRD.Parser a m b -> Stream m a -> m (Either ParseError b, Stream m a)
251−parseBreakD parser strm = do
252− (b, strmD) <- D.parseBreakD parser (toStreamD strm)
253− return $! (b, fromStreamD strmD)
254−
255−-- | Parse a stream using the supplied 'Parser'.
256−--
257−-- /CPS/
258−--
259−--{-# INLINE parseBreak #-}
260−--parseBreak :: Monad m => Parser a m b -> Stream m a -> m (Either ParseError b, Stream m a)
261−--parseBreak p strm = D.parseBreak p strm
262−
263−------------------------------------------------------------------------------
264−-- Multi-stream folds
265−------------------------------------------------------------------------------
266−
267−-- | Returns 'True' if the first stream is the same as or a prefix of the
268−-- second. A stream is a prefix of itself.
269−--
270−-- >>> Stream.isPrefixOf (Stream.fromList "hello") (Stream.fromList "hello" :: Stream IO Char)
271−-- True
272−--
273−{-# INLINE isPrefixOf #-}
274−isPrefixOf :: (Monad m, Eq a) => Stream m a -> Stream m a -> m Bool
275−isPrefixOf m1 m2 = D.isPrefixOf (toStreamD m1) (toStreamD m2)
276−
277−-- | Returns 'True' if the first stream is an infix of the second. A stream is
278−-- considered an infix of itself.
279−--
280−-- >>> s = Stream.fromList "hello" :: Stream IO Char
281−-- >>> Stream.isInfixOf s s
282−-- True
283−--
284−-- Space: @O(n)@ worst case where @n@ is the length of the infix.
285−--
286−-- /Pre-release/
287−--
288−-- /Requires 'Storable' constraint/
289−--
290−{-# INLINE isInfixOf #-}
291−isInfixOf :: (MonadIO m, Eq a, Enum a, Storable a, Unbox a)
292− => Stream m a -> Stream m a -> m Bool
293−isInfixOf infx stream = do
294− arr <- fold Array.write infx
295− -- XXX can use breakOnSeq instead (when available)
296− r <- D.null $ D.drop 1 $ D.splitOnSeq arr Fold.drain $ toStreamD stream
297− return (not r)
298−
299−-- Note: isPrefixOf uses the prefix stream only once. In contrast, isSuffixOf
300−-- may use the suffix stream many times. To run in optimal memory we do not
301−-- want to buffer the suffix stream in memory therefore we need an ability to
302−-- clone (or consume it multiple times) the suffix stream without any side
303−-- effects so that multiple potential suffix matches can proceed in parallel
304−-- without buffering the suffix stream. For example, we may create the suffix
305−-- stream from a file handle, however, if we evaluate the stream multiple
306−-- times, once for each match, we will need a different file handle each time
307−-- which may exhaust the file descriptors. Instead, we want to share the same
308−-- underlying file descriptor, use pread on it to generate the stream and clone
309−-- the stream for each match. Therefore the suffix stream should be built in
310−-- such a way that it can be consumed multiple times without any problems.
311−
312−-- XXX Can be implemented with better space/time complexity.
313−-- Space: @O(n)@ worst case where @n@ is the length of the suffix.
314−
315−-- | Returns 'True' if the first stream is a suffix of the second. A stream is
316−-- considered a suffix of itself.
317−--
318−-- >>> Stream.isSuffixOf (Stream.fromList "hello") (Stream.fromList "hello" :: Stream IO Char)
319−-- True
320−--
321−-- Space: @O(n)@, buffers entire input stream and the suffix.
322−--
323−-- /Pre-release/
324−--
325−-- /Suboptimal/ - Help wanted.
326−--
327−{-# INLINE isSuffixOf #-}
328−isSuffixOf :: (Monad m, Eq a) => Stream m a -> Stream m a -> m Bool
329−isSuffixOf suffix stream = reverse suffix `isPrefixOf` reverse stream
330−
331−-- | Returns 'True' if all the elements of the first stream occur, in order, in
332−-- the second stream. The elements do not have to occur consecutively. A stream
333−-- is a subsequence of itself.
334−--
335−-- >>> Stream.isSubsequenceOf (Stream.fromList "hlo") (Stream.fromList "hello" :: Stream IO Char)
336−-- True
337−--
338−{-# INLINE isSubsequenceOf #-}
339−isSubsequenceOf :: (Monad m, Eq a) => Stream m a -> Stream m a -> m Bool
340−isSubsequenceOf m1 m2 = D.isSubsequenceOf (toStreamD m1) (toStreamD m2)
341−
342−-- Note: If we want to return a Maybe value to know whether the
343−-- suffix/infix was present or not along with the stripped stream then
344−-- we need to buffer the whole input stream.
345−
346−-- | @stripPrefix prefix input@ strips the @prefix@ stream from the @input@
347−-- stream if it is a prefix of input. Returns 'Nothing' if the input does not
348−-- start with the given prefix, stripped input otherwise. Returns @Just nil@
349−-- when the prefix is the same as the input stream.
350−--
351−-- Space: @O(1)@
352−--
353−{-# INLINE stripPrefix #-}
354−stripPrefix
355− :: (Monad m, Eq a)
356− => Stream m a -> Stream m a -> m (Maybe (Stream m a))
357−stripPrefix m1 m2 = fmap fromStreamD <$>
358− D.stripPrefix (toStreamD m1) (toStreamD m2)
359−
360−-- | Drops the given suffix from a stream. Returns 'Nothing' if the stream does
361−-- not end with the given suffix. Returns @Just nil@ when the suffix is the
362−-- same as the stream.
363−--
364−-- It may be more efficient to convert the stream to an Array and use
365−-- stripSuffix on that especially if the elements have a Storable or Prim
366−-- instance.
367−--
368−-- See also "Streamly.Internal.Data.Stream.Reduce.dropSuffix".
369−--
370−-- Space: @O(n)@, buffers the entire input stream as well as the suffix
371−--
372−-- /Pre-release/
373−{-# INLINE stripSuffix #-}
374−stripSuffix
375− :: (Monad m, Eq a)
376− => Stream m a -> Stream m a -> m (Maybe (Stream m a))
377−stripSuffix m1 m2 = fmap reverse <$> stripPrefix (reverse m1) (reverse m2)
core/src/Streamly/Internal/Data/Stream/Enumerate.hsdeleted−560
@@ -1,560 +0,0 @@
1−-- |
2−-- Module : Streamly.Internal.Data.Stream.Enumerate
3−-- Copyright : (c) 2018 Composewell Technologies
4−--
5−-- License : BSD3
6−-- Maintainer : streamly@composewell.com
7−-- Stability : experimental
8−-- Portability : GHC
9−--
10−-- The functions defined in this module should be rarely needed for direct use,
11−-- try to use the operations from the 'Enumerable' type class
12−-- instances instead.
13−--
14−-- This module provides an 'Enumerable' type class to enumerate 'Enum' types
15−-- into a stream. The operations in this type class correspond to similar
16−-- perations in the 'Enum' type class, the only difference is that they produce
17−-- a stream instead of a list. These operations cannot be defined generically
18−-- based on the 'Enum' type class. We provide instances for commonly used
19−-- types. If instances for other types are needed convenience functions defined
20−-- in this module can be used to define them. Alternatively, these functions
21−-- can be used directly.
22−
23−-- XXX The Unfold.Enumeration module is more modular, check the differences and
24−-- reconcile the two.
25−
26−module Streamly.Internal.Data.Stream.Enumerate
27− (
28− Enumerable (..)
29−
30− -- ** Enumerating 'Bounded' 'Enum' Types
31− , enumerate
32− , enumerateTo
33− , enumerateFromBounded
34−
35− -- ** Enumerating 'Enum' Types not larger than 'Int'
36− , enumerateFromToSmall
37− , enumerateFromThenToSmall
38− , enumerateFromThenSmallBounded
39−
40− -- ** Enumerating 'Bounded' 'Integral' Types
41− , enumerateFromIntegral
42− , enumerateFromThenIntegral
43−
44− -- ** Enumerating 'Integral' Types
45− , enumerateFromToIntegral
46− , enumerateFromThenToIntegral
47−
48− -- ** Enumerating unbounded 'Integral' Types
49− , enumerateFromStepIntegral
50−
51− -- ** Enumerating 'Fractional' Types
52− , enumerateFromFractional
53− , enumerateFromToFractional
54− , enumerateFromThenFractional
55− , enumerateFromThenToFractional
56− )
57−where
58−
59−import Data.Fixed
60−import Data.Int
61−import Data.Ratio
62−import Data.Word
63−import Numeric.Natural
64−import Data.Functor.Identity (Identity(..))
65−
66−import Streamly.Internal.Data.Stream.Type (Stream, fromStreamD)
67−
68−import qualified Streamly.Internal.Data.Stream.StreamD.Generate as D
69−
70−-- $setup
71−-- >>> import Streamly.Data.Fold as Fold
72−-- >>> import Streamly.Internal.Data.Stream as Stream
73−-- >>> import Streamly.Internal.Data.Stream.Enumerate as Stream
74−
75−-------------------------------------------------------------------------------
76−-- Enumeration of Integral types
77−-------------------------------------------------------------------------------
78−--
79−-- | @enumerateFromStepIntegral from step@ generates an infinite stream whose
80−-- first element is @from@ and the successive elements are in increments of
81−-- @step@.
82−--
83−-- CAUTION: This function is not safe for finite integral types. It does not
84−-- check for overflow, underflow or bounds.
85−--
86−-- @
87−-- >>> Stream.fold Fold.toList $ Stream.take 4 $ Stream.enumerateFromStepIntegral 0 2
88−-- [0,2,4,6]
89−--
90−-- >>> Stream.fold Fold.toList $ Stream.take 3 $ Stream.enumerateFromStepIntegral 0 (-2)
91−-- [0,-2,-4]
92−--
93−-- @
94−--
95−{-# INLINE enumerateFromStepIntegral #-}
96−enumerateFromStepIntegral
97− :: (Monad m, Integral a)
98− => a -> a -> Stream m a
99−enumerateFromStepIntegral from stride =
100− fromStreamD $ D.enumerateFromStepIntegral from stride
101−
102−-- | Enumerate an 'Integral' type. @enumerateFromIntegral from@ generates a
103−-- stream whose first element is @from@ and the successive elements are in
104−-- increments of @1@. The stream is bounded by the size of the 'Integral' type.
105−--
106−-- @
107−-- >>> Stream.fold Fold.toList $ Stream.take 4 $ Stream.enumerateFromIntegral (0 :: Int)
108−-- [0,1,2,3]
109−--
110−-- @
111−--
112−{-# INLINE enumerateFromIntegral #-}
113−enumerateFromIntegral
114− :: (Monad m, Integral a, Bounded a)
115− => a -> Stream m a
116−enumerateFromIntegral from = fromStreamD $ D.enumerateFromIntegral from
117−
118−-- | Enumerate an 'Integral' type in steps. @enumerateFromThenIntegral from
119−-- then@ generates a stream whose first element is @from@, the second element
120−-- is @then@ and the successive elements are in increments of @then - from@.
121−-- The stream is bounded by the size of the 'Integral' type.
122−--
123−-- @
124−-- >>> Stream.fold Fold.toList $ Stream.take 4 $ Stream.enumerateFromThenIntegral (0 :: Int) 2
125−-- [0,2,4,6]
126−--
127−-- >>> Stream.fold Fold.toList $ Stream.take 4 $ Stream.enumerateFromThenIntegral (0 :: Int) (-2)
128−-- [0,-2,-4,-6]
129−--
130−-- @
131−--
132−{-# INLINE enumerateFromThenIntegral #-}
133−enumerateFromThenIntegral
134− :: (Monad m, Integral a, Bounded a)
135− => a -> a -> Stream m a
136−enumerateFromThenIntegral from next =
137− fromStreamD $ D.enumerateFromThenIntegral from next
138−
139−-- | Enumerate an 'Integral' type up to a given limit.
140−-- @enumerateFromToIntegral from to@ generates a finite stream whose first
141−-- element is @from@ and successive elements are in increments of @1@ up to
142−-- @to@.
143−--
144−-- @
145−-- >>> Stream.fold Fold.toList $ Stream.enumerateFromToIntegral 0 4
146−-- [0,1,2,3,4]
147−--
148−-- @
149−--
150−{-# INLINE enumerateFromToIntegral #-}
151−enumerateFromToIntegral :: (Monad m, Integral a) => a -> a -> Stream m a
152−enumerateFromToIntegral from to =
153− fromStreamD $ D.enumerateFromToIntegral from to
154−
155−-- | Enumerate an 'Integral' type in steps up to a given limit.
156−-- @enumerateFromThenToIntegral from then to@ generates a finite stream whose
157−-- first element is @from@, the second element is @then@ and the successive
158−-- elements are in increments of @then - from@ up to @to@.
159−--
160−-- @
161−-- >>> Stream.fold Fold.toList $ Stream.enumerateFromThenToIntegral 0 2 6
162−-- [0,2,4,6]
163−--
164−-- >>> Stream.fold Fold.toList $ Stream.enumerateFromThenToIntegral 0 (-2) (-6)
165−-- [0,-2,-4,-6]
166−--
167−-- @
168−--
169−{-# INLINE enumerateFromThenToIntegral #-}
170−enumerateFromThenToIntegral
171− :: (Monad m, Integral a)
172− => a -> a -> a -> Stream m a
173−enumerateFromThenToIntegral from next to =
174− fromStreamD $ D.enumerateFromThenToIntegral from next to
175−
176−-------------------------------------------------------------------------------
177−-- Enumeration of Fractional types
178−-------------------------------------------------------------------------------
179−--
180−-- Even though the underlying implementation of enumerateFromFractional and
181−-- enumerateFromThenFractional works for any 'Num' we have restricted these to
182−-- 'Fractional' because these do not perform any bounds check, in contrast to
183−-- integral versions and are therefore not equivalent substitutes for those.
184−--
185−-- | Numerically stable enumeration from a 'Fractional' number in steps of size
186−-- @1@. @enumerateFromFractional from@ generates a stream whose first element
187−-- is @from@ and the successive elements are in increments of @1@. No overflow
188−-- or underflow checks are performed.
189−--
190−-- This is the equivalent to 'enumFrom' for 'Fractional' types. For example:
191−--
192−-- @
193−-- >>> Stream.fold Fold.toList $ Stream.take 4 $ Stream.enumerateFromFractional 1.1
194−-- [1.1,2.1,3.1,4.1]
195−--
196−-- @
197−--
198−--
199−{-# INLINE enumerateFromFractional #-}
200−enumerateFromFractional :: (Monad m, Fractional a) => a -> Stream m a
201−enumerateFromFractional from = fromStreamD $ D.enumerateFromNum from
202−
203−-- | Numerically stable enumeration from a 'Fractional' number in steps.
204−-- @enumerateFromThenFractional from then@ generates a stream whose first
205−-- element is @from@, the second element is @then@ and the successive elements
206−-- are in increments of @then - from@. No overflow or underflow checks are
207−-- performed.
208−--
209−-- This is the equivalent of 'enumFromThen' for 'Fractional' types. For
210−-- example:
211−--
212−-- @
213−-- >>> Stream.fold Fold.toList $ Stream.take 4 $ Stream.enumerateFromThenFractional 1.1 2.1
214−-- [1.1,2.1,3.1,4.1]
215−--
216−-- >>> Stream.fold Fold.toList $ Stream.take 4 $ Stream.enumerateFromThenFractional 1.1 (-2.1)
217−-- [1.1,-2.1,-5.300000000000001,-8.500000000000002]
218−--
219−-- @
220−--
221−{-# INLINE enumerateFromThenFractional #-}
222−enumerateFromThenFractional
223− :: (Monad m, Fractional a)
224− => a -> a -> Stream m a
225−enumerateFromThenFractional from next = fromStreamD $ D.enumerateFromThenNum from next
226−
227−-- | Numerically stable enumeration from a 'Fractional' number to a given
228−-- limit. @enumerateFromToFractional from to@ generates a finite stream whose
229−-- first element is @from@ and successive elements are in increments of @1@ up
230−-- to @to@.
231−--
232−-- This is the equivalent of 'enumFromTo' for 'Fractional' types. For
233−-- example:
234−--
235−-- @
236−-- >>> Stream.fold Fold.toList $ Stream.enumerateFromToFractional 1.1 4
237−-- [1.1,2.1,3.1,4.1]
238−--
239−-- >>> Stream.fold Fold.toList $ Stream.enumerateFromToFractional 1.1 4.6
240−-- [1.1,2.1,3.1,4.1,5.1]
241−--
242−-- @
243−--
244−-- Notice that the last element is equal to the specified @to@ value after
245−-- rounding to the nearest integer.
246−--
247−{-# INLINE enumerateFromToFractional #-}
248−enumerateFromToFractional
249− :: (Monad m, Fractional a, Ord a)
250− => a -> a -> Stream m a
251−enumerateFromToFractional from to =
252− fromStreamD $ D.enumerateFromToFractional from to
253−
254−-- | Numerically stable enumeration from a 'Fractional' number in steps up to a
255−-- given limit. @enumerateFromThenToFractional from then to@ generates a
256−-- finite stream whose first element is @from@, the second element is @then@
257−-- and the successive elements are in increments of @then - from@ up to @to@.
258−--
259−-- This is the equivalent of 'enumFromThenTo' for 'Fractional' types. For
260−-- example:
261−--
262−-- @
263−-- >>> Stream.fold Fold.toList $ Stream.enumerateFromThenToFractional 0.1 2 6
264−-- [0.1,2.0,3.9,5.799999999999999]
265−--
266−-- >>> Stream.fold Fold.toList $ Stream.enumerateFromThenToFractional 0.1 (-2) (-6)
267−-- [0.1,-2.0,-4.1000000000000005,-6.200000000000001]
268−--
269−-- @
270−--
271−--
272−{-# INLINE enumerateFromThenToFractional #-}
273−enumerateFromThenToFractional
274− :: (Monad m, Fractional a, Ord a)
275− => a -> a -> a -> Stream m a
276−enumerateFromThenToFractional from next to =
277− fromStreamD $ D.enumerateFromThenToFractional from next to
278−
279−-------------------------------------------------------------------------------
280−-- Enumeration of Enum types not larger than Int
281−-------------------------------------------------------------------------------
282−--
283−-- | 'enumerateFromTo' for 'Enum' types not larger than 'Int'.
284−--
285−{-# INLINE enumerateFromToSmall #-}
286−enumerateFromToSmall :: (Monad m, Enum a) => a -> a -> Stream m a
287−enumerateFromToSmall from to =
288− fmap toEnum
289− $ enumerateFromToIntegral (fromEnum from) (fromEnum to)
290−
291−-- | 'enumerateFromThenTo' for 'Enum' types not larger than 'Int'.
292−--
293−{-# INLINE enumerateFromThenToSmall #-}
294−enumerateFromThenToSmall :: (Monad m, Enum a)
295− => a -> a -> a -> Stream m a
296−enumerateFromThenToSmall from next to =
297− fmap toEnum
298− $ enumerateFromThenToIntegral
299− (fromEnum from) (fromEnum next) (fromEnum to)
300−
301−-- | 'enumerateFromThen' for 'Enum' types not larger than 'Int'.
302−--
303−-- Note: We convert the 'Enum' to 'Int' and enumerate the 'Int'. If a
304−-- type is bounded but does not have a 'Bounded' instance then we can go on
305−-- enumerating it beyond the legal values of the type, resulting in the failure
306−-- of 'toEnum' when converting back to 'Enum'. Therefore we require a 'Bounded'
307−-- instance for this function to be safely used.
308−--
309−{-# INLINE enumerateFromThenSmallBounded #-}
310−enumerateFromThenSmallBounded :: (Monad m, Enumerable a, Bounded a)
311− => a -> a -> Stream m a
312−enumerateFromThenSmallBounded from next =
313− if fromEnum next >= fromEnum from
314− then enumerateFromThenTo from next maxBound
315− else enumerateFromThenTo from next minBound
316−
317−-------------------------------------------------------------------------------
318−-- Enumerable type class
319−-------------------------------------------------------------------------------
320−--
321−-- NOTE: We would like to rewrite calls to fromList [1..] etc. to stream
322−-- enumerations like this:
323−--
324−-- {-# RULES "fromList enumFrom" [1]
325−-- forall (a :: Int). D.fromList (enumFrom a) = D.enumerateFromIntegral a #-}
326−--
327−-- But this does not work because enumFrom is a class method and GHC rewrites
328−-- it quickly, so we do not get a chance to have our rule fired.
329−
330−-- | Types that can be enumerated as a stream. The operations in this type
331−-- class are equivalent to those in the 'Enum' type class, except that these
332−-- generate a stream instead of a list. Use the functions in
333−-- "Streamly.Internal.Data.Stream.Enumeration" module to define new instances.
334−--
335−class Enum a => Enumerable a where
336− -- | @enumerateFrom from@ generates a stream starting with the element
337− -- @from@, enumerating up to 'maxBound' when the type is 'Bounded' or
338− -- generating an infinite stream when the type is not 'Bounded'.
339− --
340− -- @
341− -- >>> Stream.fold Fold.toList $ Stream.take 4 $ Stream.enumerateFrom (0 :: Int)
342− -- [0,1,2,3]
343− --
344− -- @
345− --
346− -- For 'Fractional' types, enumeration is numerically stable. However, no
347− -- overflow or underflow checks are performed.
348− --
349− -- @
350− -- >>> Stream.fold Fold.toList $ Stream.take 4 $ Stream.enumerateFrom 1.1
351− -- [1.1,2.1,3.1,4.1]
352− --
353− -- @
354− --
355− enumerateFrom :: (Monad m) => a -> Stream m a
356−
357− -- | Generate a finite stream starting with the element @from@, enumerating
358− -- the type up to the value @to@. If @to@ is smaller than @from@ then an
359− -- empty stream is returned.
360− --
361− -- @
362− -- >>> Stream.fold Fold.toList $ Stream.enumerateFromTo 0 4
363− -- [0,1,2,3,4]
364− --
365− -- @
366− --
367− -- For 'Fractional' types, the last element is equal to the specified @to@
368− -- value after rounding to the nearest integral value.
369− --
370− -- @
371− -- >>> Stream.fold Fold.toList $ Stream.enumerateFromTo 1.1 4
372− -- [1.1,2.1,3.1,4.1]
373− --
374− -- >>> Stream.fold Fold.toList $ Stream.enumerateFromTo 1.1 4.6
375− -- [1.1,2.1,3.1,4.1,5.1]
376− --
377− -- @
378− --
379− enumerateFromTo :: (Monad m) => a -> a -> Stream m a
380−
381− -- | @enumerateFromThen from then@ generates a stream whose first element
382− -- is @from@, the second element is @then@ and the successive elements are
383− -- in increments of @then - from@. Enumeration can occur downwards or
384− -- upwards depending on whether @then@ comes before or after @from@. For
385− -- 'Bounded' types the stream ends when 'maxBound' is reached, for
386− -- unbounded types it keeps enumerating infinitely.
387− --
388− -- @
389− -- >>> Stream.fold Fold.toList $ Stream.take 4 $ Stream.enumerateFromThen 0 2
390− -- [0,2,4,6]
391− --
392− -- >>> Stream.fold Fold.toList $ Stream.take 4 $ Stream.enumerateFromThen 0 (-2)
393− -- [0,-2,-4,-6]
394− --
395− -- @
396− --
397− enumerateFromThen :: (Monad m) => a -> a -> Stream m a
398−
399− -- | @enumerateFromThenTo from then to@ generates a finite stream whose
400− -- first element is @from@, the second element is @then@ and the successive
401− -- elements are in increments of @then - from@ up to @to@. Enumeration can
402− -- occur downwards or upwards depending on whether @then@ comes before or
403− -- after @from@.
404− --
405− -- @
406− -- >>> Stream.fold Fold.toList $ Stream.enumerateFromThenTo 0 2 6
407− -- [0,2,4,6]
408− --
409− -- >>> Stream.fold Fold.toList $ Stream.enumerateFromThenTo 0 (-2) (-6)
410− -- [0,-2,-4,-6]
411− --
412− -- @
413− --
414− enumerateFromThenTo :: (Monad m) => a -> a -> a -> Stream m a
415−
416−-- MAYBE: Sometimes it is more convenient to know the count rather then the
417−-- ending or starting element. For those cases we can define the folllowing
418−-- APIs. All of these will work only for bounded types if we represent the
419−-- count by Int.
420−--
421−-- enumerateN
422−-- enumerateFromN
423−-- enumerateToN
424−-- enumerateFromStep
425−-- enumerateFromStepN
426−
427−-------------------------------------------------------------------------------
428−-- Convenient functions for bounded types
429−-------------------------------------------------------------------------------
430−--
431−-- |
432−-- > enumerate = enumerateFrom minBound
433−--
434−-- Enumerate a 'Bounded' type from its 'minBound' to 'maxBound'
435−--
436−{-# INLINE enumerate #-}
437−enumerate :: (Monad m, Bounded a, Enumerable a) => Stream m a
438−enumerate = enumerateFrom minBound
439−
440−-- |
441−-- > enumerateTo = enumerateFromTo minBound
442−--
443−-- Enumerate a 'Bounded' type from its 'minBound' to specified value.
444−--
445−{-# INLINE enumerateTo #-}
446−enumerateTo :: (Monad m, Bounded a, Enumerable a) => a -> Stream m a
447−enumerateTo = enumerateFromTo minBound
448−
449−-- |
450−-- > enumerateFromBounded = enumerateFromTo from maxBound
451−--
452−-- 'enumerateFrom' for 'Bounded' 'Enum' types.
453−--
454−{-# INLINE enumerateFromBounded #-}
455−enumerateFromBounded :: (Monad m, Enumerable a, Bounded a)
456− => a -> Stream m a
457−enumerateFromBounded from = enumerateFromTo from maxBound
458−
459−-------------------------------------------------------------------------------
460−-- Enumerable Instances
461−-------------------------------------------------------------------------------
462−--
463−-- For Enum types smaller than or equal to Int size.
464−#define ENUMERABLE_BOUNDED_SMALL(SMALL_TYPE) \
465−instance Enumerable SMALL_TYPE where { \
466− {-# INLINE enumerateFrom #-}; \
467− enumerateFrom = enumerateFromBounded; \
468− {-# INLINE enumerateFromThen #-}; \
469− enumerateFromThen = enumerateFromThenSmallBounded; \
470− {-# INLINE enumerateFromTo #-}; \
471− enumerateFromTo = enumerateFromToSmall; \
472− {-# INLINE enumerateFromThenTo #-}; \
473− enumerateFromThenTo = enumerateFromThenToSmall }
474−
475−
476−ENUMERABLE_BOUNDED_SMALL(())
477−ENUMERABLE_BOUNDED_SMALL(Bool)
478−ENUMERABLE_BOUNDED_SMALL(Ordering)
479−ENUMERABLE_BOUNDED_SMALL(Char)
480−
481−-- For bounded Integral Enum types, may be larger than Int.
482−#define ENUMERABLE_BOUNDED_INTEGRAL(INTEGRAL_TYPE) \
483−instance Enumerable INTEGRAL_TYPE where { \
484− {-# INLINE enumerateFrom #-}; \
485− enumerateFrom = enumerateFromIntegral; \
486− {-# INLINE enumerateFromThen #-}; \
487− enumerateFromThen = enumerateFromThenIntegral; \
488− {-# INLINE enumerateFromTo #-}; \
489− enumerateFromTo = enumerateFromToIntegral; \
490− {-# INLINE enumerateFromThenTo #-}; \
491− enumerateFromThenTo = enumerateFromThenToIntegral }
492−
493−ENUMERABLE_BOUNDED_INTEGRAL(Int)
494−ENUMERABLE_BOUNDED_INTEGRAL(Int8)
495−ENUMERABLE_BOUNDED_INTEGRAL(Int16)
496−ENUMERABLE_BOUNDED_INTEGRAL(Int32)
497−ENUMERABLE_BOUNDED_INTEGRAL(Int64)
498−ENUMERABLE_BOUNDED_INTEGRAL(Word)
499−ENUMERABLE_BOUNDED_INTEGRAL(Word8)
500−ENUMERABLE_BOUNDED_INTEGRAL(Word16)
501−ENUMERABLE_BOUNDED_INTEGRAL(Word32)
502−ENUMERABLE_BOUNDED_INTEGRAL(Word64)
503−
504−-- For unbounded Integral Enum types.
505−#define ENUMERABLE_UNBOUNDED_INTEGRAL(INTEGRAL_TYPE) \
506−instance Enumerable INTEGRAL_TYPE where { \
507− {-# INLINE enumerateFrom #-}; \
508− enumerateFrom from = enumerateFromStepIntegral from 1; \
509− {-# INLINE enumerateFromThen #-}; \
510− enumerateFromThen from next = \
511− enumerateFromStepIntegral from (next - from); \
512− {-# INLINE enumerateFromTo #-}; \
513− enumerateFromTo = enumerateFromToIntegral; \
514− {-# INLINE enumerateFromThenTo #-}; \
515− enumerateFromThenTo = enumerateFromThenToIntegral }
516−
517−ENUMERABLE_UNBOUNDED_INTEGRAL(Integer)
518−ENUMERABLE_UNBOUNDED_INTEGRAL(Natural)
519−
520−#define ENUMERABLE_FRACTIONAL(FRACTIONAL_TYPE,CONSTRAINT) \
521−instance (CONSTRAINT) => Enumerable FRACTIONAL_TYPE where { \
522− {-# INLINE enumerateFrom #-}; \
523− enumerateFrom = enumerateFromFractional; \
524− {-# INLINE enumerateFromThen #-}; \
525− enumerateFromThen = enumerateFromThenFractional; \
526− {-# INLINE enumerateFromTo #-}; \
527− enumerateFromTo = enumerateFromToFractional; \
528− {-# INLINE enumerateFromThenTo #-}; \
529− enumerateFromThenTo = enumerateFromThenToFractional }
530−
531−ENUMERABLE_FRACTIONAL(Float,)
532−ENUMERABLE_FRACTIONAL(Double,)
533−ENUMERABLE_FRACTIONAL((Fixed a),HasResolution a)
534−ENUMERABLE_FRACTIONAL((Ratio a),Integral a)
535−
536−instance Enumerable a => Enumerable (Identity a) where
537− {-# INLINE enumerateFrom #-}
538− enumerateFrom (Identity from) =
539− fmap Identity $ enumerateFrom from
540− {-# INLINE enumerateFromThen #-}
541− enumerateFromThen (Identity from) (Identity next) =
542− fmap Identity $ enumerateFromThen from next
543− {-# INLINE enumerateFromTo #-}
544− enumerateFromTo (Identity from) (Identity to) =
545− fmap Identity $ enumerateFromTo from to
546− {-# INLINE enumerateFromThenTo #-}
547− enumerateFromThenTo (Identity from) (Identity next) (Identity to) =
548− fmap Identity
549− $ enumerateFromThenTo from next to
550−
551−-- TODO
552−{-
553−instance Enumerable a => Enumerable (Last a)
554−instance Enumerable a => Enumerable (First a)
555−instance Enumerable a => Enumerable (Max a)
556−instance Enumerable a => Enumerable (Min a)
557−instance Enumerable a => Enumerable (Const a b)
558−instance Enumerable (f a) => Enumerable (Alt f a)
559−instance Enumerable (f a) => Enumerable (Ap f a)
560−-}
core/src/Streamly/Internal/Data/Stream/Exception.hsdeleted−222
@@ -1,222 +0,0 @@
1−-- |
2−-- Module : Streamly.Internal.Data.Stream.Exception
3−-- Copyright : (c) 2019 Composewell Technologies
4−-- License : BSD-3-Clause
5−-- Maintainer : streamly@composewell.com
6−-- Stability : experimental
7−-- Portability : GHC
8−
9−module Streamly.Internal.Data.Stream.Exception
10− (
11− before
12− , afterUnsafe
13− , afterIO
14− , bracketUnsafe
15− , bracketIO
16− , bracketIO3
17− , onException
18− , finallyUnsafe
19− , finallyIO
20− , ghandle
21− , handle
22− )
23−where
24−
25−import Control.Exception (Exception)
26−import Control.Monad.Catch (MonadCatch)
27−import Control.Monad.IO.Class (MonadIO)
28−import Streamly.Internal.Data.Stream.Type (Stream, fromStreamD, toStreamD)
29−
30−import qualified Streamly.Internal.Data.Stream as D
31−
32−-- $setup
33−-- >>> :m
34−-- >>> import qualified Streamly.Internal.Data.Stream as Stream
35−
36−------------------------------------------------------------------------------
37−-- Exceptions
38−------------------------------------------------------------------------------
39−
40−-- | Run the action @m b@ before the stream yields its first element.
41−--
42−-- Same as the following but more efficient due to fusion:
43−--
44−-- >>> before action xs = Stream.nilM action <> xs
45−-- >>> before action xs = Stream.concatMap (const xs) (Stream.fromEffect action)
46−--
47−{-# INLINE before #-}
48−before :: Monad m => m b -> Stream m a -> Stream m a
49−before action xs = fromStreamD $ D.before action $ toStreamD xs
50−
51−-- | Like 'after', with following differences:
52−--
53−-- * action @m b@ won't run if the stream is garbage collected
54−-- after partial evaluation.
55−-- * Monad @m@ does not require any other constraints.
56−-- * has slightly better performance than 'after'.
57−--
58−-- Same as the following, but with stream fusion:
59−--
60−-- >>> afterUnsafe action xs = xs <> Stream.nilM action
61−--
62−-- /Pre-release/
63−--
64−{-# INLINE afterUnsafe #-}
65−afterUnsafe :: Monad m => m b -> Stream m a -> Stream m a
66−afterUnsafe action xs = fromStreamD $ D.afterUnsafe action $ toStreamD xs
67−
68−-- | Run the action @IO b@ whenever the stream is evaluated to completion, or
69−-- if it is garbage collected after a partial lazy evaluation.
70−--
71−-- The semantics of the action @IO b@ are similar to the semantics of cleanup
72−-- action in 'bracketIO'.
73−--
74−-- /See also 'afterUnsafe'/
75−--
76−{-# INLINE afterIO #-}
77−afterIO :: MonadIO m => IO b -> Stream m a -> Stream m a
78−afterIO action xs = fromStreamD $ D.afterIO action $ toStreamD xs
79−
80−-- | Run the action @m b@ if the stream evaluation is aborted due to an
81−-- exception. The exception is not caught, simply rethrown.
82−--
83−-- /Inhibits stream fusion/
84−--
85−{-# INLINE onException #-}
86−onException :: MonadCatch m => m b -> Stream m a -> Stream m a
87−onException action xs = fromStreamD $ D.onException action $ toStreamD xs
88−
89−-- | Like 'finally' with following differences:
90−--
91−-- * action @m b@ won't run if the stream is garbage collected
92−-- after partial evaluation.
93−-- * has slightly better performance than 'finallyIO'.
94−--
95−-- /Inhibits stream fusion/
96−--
97−-- /Pre-release/
98−--
99−{-# INLINE finallyUnsafe #-}
100−finallyUnsafe :: MonadCatch m => m b -> Stream m a -> Stream m a
101−finallyUnsafe action xs = fromStreamD $ D.finallyUnsafe action $ toStreamD xs
102−
103−-- | Run the action @IO b@ whenever the stream stream stops normally, aborts
104−-- due to an exception or if it is garbage collected after a partial lazy
105−-- evaluation.
106−--
107−-- The semantics of running the action @IO b@ are similar to the cleanup action
108−-- semantics described in 'bracketIO'.
109−--
110−-- >>> finallyIO release = Stream.bracketIO (return ()) (const release)
111−--
112−-- /See also 'finallyUnsafe'/
113−--
114−-- /Inhibits stream fusion/
115−--
116−{-# INLINE finallyIO #-}
117−finallyIO :: (MonadIO m, MonadCatch m) =>
118− IO b -> Stream m a -> Stream m a
119−finallyIO action xs = fromStreamD $ D.finallyIO action $ toStreamD xs
120−
121−-- | Like 'bracket' but with following differences:
122−--
123−-- * alloc action @m b@ runs with async exceptions enabled
124−-- * cleanup action @b -> m c@ won't run if the stream is garbage collected
125−-- after partial evaluation.
126−-- * has slightly better performance than 'bracketIO'.
127−--
128−-- /Inhibits stream fusion/
129−--
130−-- /Pre-release/
131−--
132−{-# INLINE bracketUnsafe #-}
133−bracketUnsafe :: MonadCatch m
134− => m b -> (b -> m c) -> (b -> Stream m a) -> Stream m a
135−bracketUnsafe bef aft bet = fromStreamD $ D.bracketUnsafe bef aft (toStreamD . bet)
136−
137−-- | Run the alloc action @IO b@ with async exceptions disabled but keeping
138−-- blocking operations interruptible (see 'Control.Exception.mask'). Use the
139−-- output @b@ as input to @b -> Stream m a@ to generate an output stream.
140−--
141−-- @b@ is usually a resource under the IO monad, e.g. a file handle, that
142−-- requires a cleanup after use. The cleanup action @b -> IO c@, runs whenever
143−-- the stream ends normally, due to a sync or async exception or if it gets
144−-- garbage collected after a partial lazy evaluation.
145−--
146−-- 'bracketIO' only guarantees that the cleanup action runs, and it runs with
147−-- async exceptions enabled. The action must ensure that it can successfully
148−-- cleanup the resource in the face of sync or async exceptions.
149−--
150−-- When the stream ends normally or on a sync exception, cleanup action runs
151−-- immediately in the current thread context, whereas in other cases it runs in
152−-- the GC context, therefore, cleanup may be delayed until the GC gets to run.
153−--
154−-- /See also: 'bracketUnsafe'/
155−--
156−-- /Inhibits stream fusion/
157−--
158−{-# INLINE bracketIO #-}
159−bracketIO :: (MonadIO m, MonadCatch m)
160− => IO b -> (b -> IO c) -> (b -> Stream m a) -> Stream m a
161−bracketIO bef aft = bracketIO3 bef aft aft aft
162−
163−-- For a use case of this see the "streamly-process" package. It needs to kill
164−-- the process in case of exception or garbage collection, but waits for the
165−-- process to terminate in normal cases.
166−
167−-- | Like 'bracketIO' but can use 3 separate cleanup actions depending on the
168−-- mode of termination:
169−--
170−-- 1. When the stream stops normally
171−-- 2. When the stream is garbage collected
172−-- 3. When the stream encounters an exception
173−--
174−-- @bracketIO3 before onStop onGC onException action@ runs @action@ using the
175−-- result of @before@. If the stream stops, @onStop@ action is executed, if the
176−-- stream is abandoned @onGC@ is executed, if the stream encounters an
177−-- exception @onException@ is executed.
178−--
179−-- /Inhibits stream fusion/
180−--
181−-- /Pre-release/
182−{-# INLINE bracketIO3 #-}
183−bracketIO3 :: (MonadIO m, MonadCatch m)
184− => IO b
185− -> (b -> IO c)
186− -> (b -> IO d)
187− -> (b -> IO e)
188− -> (b -> Stream m a)
189− -> Stream m a
190−bracketIO3 bef aft gc exc bet = fromStreamD $
191− D.bracketIO3 bef aft exc gc (toStreamD . bet)
192−
193−-- | Like 'handle' but the exception handler is also provided with the stream
194−-- that generated the exception as input. The exception handler can thus
195−-- re-evaluate the stream to retry the action that failed. The exception
196−-- handler can again call 'ghandle' on it to retry the action multiple times.
197−--
198−-- This is highly experimental. In a stream of actions we can map the stream
199−-- with a retry combinator to retry each action on failure.
200−--
201−-- /Inhibits stream fusion/
202−--
203−-- /Pre-release/
204−--
205−{-# INLINE ghandle #-}
206−ghandle :: (MonadCatch m, Exception e)
207− => (e -> Stream m a -> Stream m a) -> Stream m a -> Stream m a
208−ghandle handler =
209− fromStreamD
210− . D.ghandle (\e xs -> toStreamD $ handler e (fromStreamD xs))
211− . toStreamD
212−
213−-- | When evaluating a stream if an exception occurs, stream evaluation aborts
214−-- and the specified exception handler is run with the exception as argument.
215−--
216−-- /Inhibits stream fusion/
217−--
218−{-# INLINE handle #-}
219−handle :: (MonadCatch m, Exception e)
220− => (e -> Stream m a) -> Stream m a -> Stream m a
221−handle handler xs =
222− fromStreamD $ D.handle (toStreamD . handler) $ toStreamD xs
core/src/Streamly/Internal/Data/Stream/Expand.hsdeleted−893
@@ -1,893 +0,0 @@
1−-- |
2−-- Module : Streamly.Internal.Data.Stream.Expand
3−-- Copyright : (c) 2017 Composewell Technologies
4−-- License : BSD-3-Clause
5−-- Maintainer : streamly@composewell.com
6−-- Stability : experimental
7−-- Portability : GHC
8−--
9−-- Expand a stream by combining two or more streams or by combining streams
10−-- with unfolds.
11−
12−module Streamly.Internal.Data.Stream.Expand
13− (
14− -- * Binary Combinators (Linear)
15− -- | Functions ending in the shape:
16− --
17− -- @Stream m a -> Stream m a -> Stream m a@.
18− --
19− -- The functions in this section have a linear or flat n-ary combining
20− -- characterstics. It means that when combined @n@ times (e.g. @a `serial`
21− -- b `serial` c ...@) the resulting expression will have an @O(n)@
22− -- complexity (instead O(n^2) for pair wise combinators described in the
23− -- next section. These functions can be used efficiently with
24− -- 'concatMapWith' et. al. combinators that combine streams in a linear
25− -- fashion (contrast with 'mergeMapWith' which combines streams as a
26− -- binary tree).
27−
28− append
29− -- * Binary Combinators (Pair Wise)
30− -- | Like the functions in the section above these functions also combine
31− -- two streams into a single stream but when used @n@ times linearly they
32− -- exhibit O(n^2) complexity. They are best combined in a binary tree
33− -- fashion using 'mergeMapWith' giving a @n * log n@ complexity. Avoid
34− -- using these with 'concatMapWith' when combining a large or infinite
35− -- number of streams.
36−
37− -- ** Append
38− , append2
39−
40− -- ** Interleave
41− , interleave
42− , interleave2
43− , interleaveFst
44− , interleaveFst2
45− , interleaveFstSuffix2
46− , interleaveMin
47− , interleaveMin2
48−
49− -- ** Round Robin
50− , roundrobin
51−
52− -- ** Merge
53− , mergeBy
54− , mergeByM
55− , mergeByM2
56− , mergeMinBy
57− , mergeFstBy
58−
59− -- ** Zip
60− , zipWith
61− , zipWithM
62−
63− -- * Combine Streams and Unfolds
64− -- |
65− -- Expand a stream by repeatedly using an unfold and merging the resulting
66− -- streams. Functions generally ending in the shape:
67− --
68− -- @Unfold m a b -> Stream m a -> Stream m b@
69−
70− -- ** Unfold and combine streams
71− -- | Unfold and flatten streams.
72− , unfoldMany -- XXX Rename to unfoldAppend
73− , unfoldInterleave
74− , unfoldRoundRobin
75−
76− -- ** Interpose
77− -- | Insert effects between streams. Like unfoldMany but intersperses an
78− -- effect between the streams. A special case of gintercalate.
79− , interpose
80− , interposeSuffix
81− -- , interposeBy
82−
83− -- ** Intercalate
84− -- | Insert Streams between Streams.
85− -- Like unfoldMany but intersperses streams from another source between
86− -- the streams from the first source.
87− , intercalate
88− , intercalateSuffix
89− , gintercalate
90− , gintercalateSuffix
91−
92− -- * Combine Streams of Streams
93− -- | Map and serially append streams. 'concatMapM' is a generalization of
94− -- the binary append operation to append many streams.
95− , concatMapM
96− , concatMap
97− , concatEffect
98− , concat
99−
100− -- * ConcatMapWith
101− -- | Map and flatten a stream like 'concatMap' but using a custom binary
102− -- stream merging combinator instead of just appending the streams. The
103− -- merging occurs sequentially, it works efficiently for 'serial', 'async',
104− -- 'ahead' like merge operations where we consume one stream before the
105− -- next or in case of 'wAsync' or 'parallel' where we consume all streams
106− -- simultaneously anyway.
107− --
108− -- However, in cases where the merging consumes streams in a round robin
109− -- fashion, a pair wise merging using 'mergeMapWith' would be more
110− -- efficient. These cases include operations like 'mergeBy' or 'zipWith'.
111−
112− , concatMapWith
113− , bindWith
114− , concatSmapMWith
115−
116− -- * MergeMapWith
117− -- | See the notes about suitable merge functions in the 'concatMapWith'
118− -- section.
119− , mergeMapWith
120−
121− -- * Iterate
122− -- | Map and flatten Trees of Streams
123− , unfoldIterateDfs
124− , unfoldIterateBfs
125− , unfoldIterateBfsRev
126−
127− , concatIterateWith
128− , mergeIterateWith
129−
130− , concatIterateDfs
131− , concatIterateBfs
132−
133− -- More experimental ops
134− , concatIterateBfsRev
135− , concatIterateLeftsWith
136− , concatIterateScanWith
137− , concatIterateScan
138− )
139−where
140−
141−#include "inline.hs"
142−
143−import Streamly.Internal.Data.Stream.Bottom
144− ( concatEffect, concatMapM, concatMap, smapM, zipWith, zipWithM)
145−import Streamly.Internal.Data.Stream.Type
146− ( Stream, fromStreamD, fromStreamK, toStreamD, toStreamK
147− , bindWith, concatMapWith, cons, nil)
148−import Streamly.Internal.Data.Unfold.Type (Unfold)
149−
150−import qualified Streamly.Internal.Data.Stream as D
151−import qualified Streamly.Internal.Data.StreamK as K (mergeBy, mergeByM)
152−import qualified Streamly.Internal.Data.Stream.StreamK.Type as K
153−
154−import Prelude hiding (concat, concatMap, zipWith)
155−
156−-- $setup
157−-- >>> :m
158−-- >>> import Data.Either (either)
159−-- >>> import Data.IORef
160−-- >>> import Streamly.Internal.Data.Stream (Stream)
161−-- >>> import Prelude hiding (zipWith, concatMap, concat)
162−-- >>> import qualified Streamly.Data.Array as Array
163−-- >>> import qualified Streamly.Internal.Data.Fold as Fold
164−-- >>> import qualified Streamly.Internal.Data.Stream as Stream
165−-- >>> import qualified Streamly.Internal.Data.Unfold as Unfold
166−-- >>> import qualified Streamly.Internal.Data.Parser as Parser
167−-- >>> import qualified Streamly.Internal.FileSystem.Dir as Dir
168−--
169−
170−------------------------------------------------------------------------------
171−-- Appending
172−------------------------------------------------------------------------------
173−
174−infixr 6 `append2`
175−
176−-- | This is fused version of 'append'. It could be up to 100x faster than
177−-- 'append' when combining two fusible streams. However, it slows down
178−-- quadratically with the number of streams being appended. Therefore, it is
179−-- suitable for ad-hoc append of a few streams, and should not be used with
180−-- 'concatMapWith' or 'mergeMapWith'.
181−--
182−-- /Fused/
183−--
184−{-# INLINE append2 #-}
185−append2 ::Monad m => Stream m b -> Stream m b -> Stream m b
186−append2 m1 m2 = fromStreamD $ D.append (toStreamD m1) (toStreamD m2)
187−
188−infixr 6 `append`
189−
190−-- | Appends two streams sequentially, yielding all elements from the first
191−-- stream, and then all elements from the second stream.
192−--
193−-- >>> s1 = Stream.fromList [1,2]
194−-- >>> s2 = Stream.fromList [3,4]
195−-- >>> Stream.fold Fold.toList $ s1 `Stream.append` s2
196−-- [1,2,3,4]
197−--
198−-- This has O(n) append performance where @n@ is the number of streams. It can
199−-- be used to efficiently fold an infinite lazy container of streams
200−-- 'concatMapWith' et. al.
201−--
202−-- See 'append2' for a fusible alternative.
203−--
204−-- /CPS/
205−{-# INLINE append #-}
206−append :: Stream m a -> Stream m a -> Stream m a
207−append = (<>)
208−
209−------------------------------------------------------------------------------
210−-- Interleaving
211−------------------------------------------------------------------------------
212−
213−infixr 6 `interleave`
214−
215−-- | Interleaves two streams, yielding one element from each stream
216−-- alternately. When one stream stops the rest of the other stream is used in
217−-- the output stream.
218−--
219−-- When joining many streams in a left associative manner earlier streams will
220−-- get exponential priority than the ones joining later. Because of exponential
221−-- weighting it can be used with 'concatMapWith' even on a large number of
222−-- streams.
223−--
224−-- See 'interleave2' for a fusible alternative.
225−--
226−-- /CPS/
227−{-# INLINE interleave #-}
228−interleave :: Stream m a -> Stream m a -> Stream m a
229−interleave s1 s2 = fromStreamK $ K.interleave (toStreamK s1) (toStreamK s2)
230−
231−{-# INLINE interleave2 #-}
232−interleave2 :: Monad m => Stream m a -> Stream m a -> Stream m a
233−interleave2 s1 s2 = fromStreamD $ D.interleave (toStreamD s1) (toStreamD s2)
234−
235−-- | Like `interleave` but stops interleaving as soon as the first stream
236−-- stops.
237−--
238−-- See 'interleaveFst2' for a fusible alternative.
239−--
240−-- /CPS/
241−{-# INLINE interleaveFst #-}
242−interleaveFst :: Stream m a -> Stream m a -> Stream m a
243−interleaveFst s1 s2 =
244− fromStreamK $ K.interleaveFst (toStreamK s1) (toStreamK s2)
245−
246−-- | Like `interleave` but stops interleaving as soon as any of the two streams
247−-- stops.
248−--
249−-- See 'interleaveMin2' for a fusible alternative.
250−--
251−-- /CPS/
252−{-# INLINE interleaveMin #-}
253−interleaveMin :: Stream m a -> Stream m a -> Stream m a
254−interleaveMin s1 s2 =
255− fromStreamK $ K.interleaveMin (toStreamK s1) (toStreamK s2)
256−
257−{-# INLINE interleaveMin2 #-}
258−interleaveMin2 :: Monad m => Stream m a -> Stream m a -> Stream m a
259−interleaveMin2 s1 s2 =
260− fromStreamD $ D.interleaveMin (toStreamD s1) (toStreamD s2)
261−
262−-- | Interleaves the outputs of two streams, yielding elements from each stream
263−-- alternately, starting from the first stream. As soon as the first stream
264−-- finishes, the output stops, discarding the remaining part of the second
265−-- stream. In this case, the last element in the resulting stream would be from
266−-- the second stream. If the second stream finishes early then the first stream
267−-- still continues to yield elements until it finishes.
268−--
269−-- >>> :set -XOverloadedStrings
270−-- >>> import Data.Functor.Identity (Identity)
271−-- >>> Stream.interleaveFstSuffix2 "abc" ",,,," :: Stream Identity Char
272−-- fromList "a,b,c,"
273−-- >>> Stream.interleaveFstSuffix2 "abc" "," :: Stream Identity Char
274−-- fromList "a,bc"
275−--
276−-- 'interleaveFstSuffix2' is a dual of 'interleaveFst2'.
277−--
278−-- Do not use at scale in concatMapWith.
279−--
280−-- /Pre-release/
281−{-# INLINE interleaveFstSuffix2 #-}
282−interleaveFstSuffix2 :: Monad m => Stream m b -> Stream m b -> Stream m b
283−interleaveFstSuffix2 m1 m2 =
284− fromStreamD $ D.interleaveFstSuffix (toStreamD m1) (toStreamD m2)
285−
286−-- | Interleaves the outputs of two streams, yielding elements from each stream
287−-- alternately, starting from the first stream and ending at the first stream.
288−-- If the second stream is longer than the first, elements from the second
289−-- stream are infixed with elements from the first stream. If the first stream
290−-- is longer then it continues yielding elements even after the second stream
291−-- has finished.
292−--
293−-- >>> :set -XOverloadedStrings
294−-- >>> import Data.Functor.Identity (Identity)
295−-- >>> Stream.interleaveFst2 "abc" ",,,," :: Stream Identity Char
296−-- fromList "a,b,c"
297−-- >>> Stream.interleaveFst2 "abc" "," :: Stream Identity Char
298−-- fromList "a,bc"
299−--
300−-- 'interleaveFst2' is a dual of 'interleaveFstSuffix2'.
301−--
302−-- Do not use at scale in concatMapWith.
303−--
304−-- /Pre-release/
305−{-# INLINE interleaveFst2 #-}
306−interleaveFst2 :: Monad m => Stream m b -> Stream m b -> Stream m b
307−interleaveFst2 m1 m2 =
308− fromStreamD $ D.interleaveFst (toStreamD m1) (toStreamD m2)
309−
310−------------------------------------------------------------------------------
311−-- Scheduling
312−------------------------------------------------------------------------------
313−
314−-- | Schedule the execution of two streams in a fair round-robin manner,
315−-- executing each stream once, alternately. Execution of a stream may not
316−-- necessarily result in an output, a stream may chose to @Skip@ producing an
317−-- element until later giving the other stream a chance to run. Therefore, this
318−-- combinator fairly interleaves the execution of two streams rather than
319−-- fairly interleaving the output of the two streams. This can be useful in
320−-- co-operative multitasking without using explicit threads. This can be used
321−-- as an alternative to `async`.
322−--
323−-- Do not use at scale in concatMapWith.
324−--
325−-- /Pre-release/
326−{-# INLINE roundrobin #-}
327−roundrobin :: Monad m => Stream m b -> Stream m b -> Stream m b
328−roundrobin m1 m2 = fromStreamD $ D.roundRobin (toStreamD m1) (toStreamD m2)
329−
330−------------------------------------------------------------------------------
331−-- Merging (sorted streams)
332−------------------------------------------------------------------------------
333−
334−-- | Merge two streams using a comparison function. The head elements of both
335−-- the streams are compared and the smaller of the two elements is emitted, if
336−-- both elements are equal then the element from the first stream is used
337−-- first.
338−--
339−-- If the streams are sorted in ascending order, the resulting stream would
340−-- also remain sorted in ascending order.
341−--
342−-- >>> s1 = Stream.fromList [1,3,5]
343−-- >>> s2 = Stream.fromList [2,4,6,8]
344−-- >>> Stream.fold Fold.toList $ Stream.mergeBy compare s1 s2
345−-- [1,2,3,4,5,6,8]
346−--
347−-- See 'mergeByM2' for a fusible alternative.
348−--
349−-- /CPS/
350−{-# INLINE mergeBy #-}
351−mergeBy :: (a -> a -> Ordering) -> Stream m a -> Stream m a -> Stream m a
352−mergeBy f m1 m2 = fromStreamK $ K.mergeBy f (toStreamK m1) (toStreamK m2)
353−
354−-- | Like 'mergeBy' but with a monadic comparison function.
355−--
356−-- Merge two streams randomly:
357−--
358−-- @
359−-- > randomly _ _ = randomIO >>= \x -> return $ if x then LT else GT
360−-- > Stream.toList $ Stream.mergeByM randomly (Stream.fromList [1,1,1,1]) (Stream.fromList [2,2,2,2])
361−-- [2,1,2,2,2,1,1,1]
362−-- @
363−--
364−-- Merge two streams in a proportion of 2:1:
365−--
366−-- >>> :{
367−-- do
368−-- let s1 = Stream.fromList [1,1,1,1,1,1]
369−-- s2 = Stream.fromList [2,2,2]
370−-- let proportionately m n = do
371−-- ref <- newIORef $ cycle $ Prelude.concat [Prelude.replicate m LT, Prelude.replicate n GT]
372−-- return $ \_ _ -> do
373−-- r <- readIORef ref
374−-- writeIORef ref $ Prelude.tail r
375−-- return $ Prelude.head r
376−-- f <- proportionately 2 1
377−-- xs <- Stream.fold Fold.toList $ Stream.mergeByM f s1 s2
378−-- print xs
379−-- :}
380−-- [1,1,2,1,1,2,1,1,2]
381−--
382−-- See 'mergeByM2' for a fusible alternative.
383−--
384−-- /CPS/
385−{-# INLINE mergeByM #-}
386−mergeByM
387− :: Monad m
388− => (a -> a -> m Ordering) -> Stream m a -> Stream m a -> Stream m a
389−mergeByM f m1 m2 = fromStreamK $ K.mergeByM f (toStreamK m1) (toStreamK m2)
390−
391−-- | Like 'mergeByM' but much faster, works best when merging statically known
392−-- number of streams. When merging more than two streams try to merge pairs and
393−-- pair of pairs in a tree like structure.'mergeByM' works better with variable
394−-- number of streams being merged using 'mergeMapWith'.
395−--
396−-- /Internal/
397−{-# INLINE mergeByM2 #-}
398−mergeByM2
399− :: Monad m
400− => (a -> a -> m Ordering) -> Stream m a -> Stream m a -> Stream m a
401−mergeByM2 f m1 m2 =
402− fromStreamD $ D.mergeByM f (toStreamD m1) (toStreamD m2)
403−
404−-- | Like 'mergeByM' but stops merging as soon as any of the two streams stops.
405−--
406−-- /Unimplemented/
407−{-# INLINABLE mergeMinBy #-}
408−mergeMinBy :: -- Monad m =>
409− (a -> a -> m Ordering) -> Stream m a -> Stream m a -> Stream m a
410−mergeMinBy _f _m1 _m2 = undefined
411− -- fromStreamD $ D.mergeMinBy f (toStreamD m1) (toStreamD m2)
412−
413−-- | Like 'mergeByM' but stops merging as soon as the first stream stops.
414−--
415−-- /Unimplemented/
416−{-# INLINABLE mergeFstBy #-}
417−mergeFstBy :: -- Monad m =>
418− (a -> a -> m Ordering) -> Stream m a -> Stream m a -> Stream m a
419−mergeFstBy _f _m1 _m2 = undefined
420− -- fromStreamK $ D.mergeFstBy f (toStreamD m1) (toStreamD m2)
421−
422−------------------------------------------------------------------------------
423−-- Combine N Streams - unfoldMany
424−------------------------------------------------------------------------------
425−
426−-- | Like 'concatMap' but uses an 'Unfold' for stream generation. Unlike
427−-- 'concatMap' this can fuse the 'Unfold' code with the inner loop and
428−-- therefore provide many times better performance.
429−--
430−{-# INLINE unfoldMany #-}
431−unfoldMany ::Monad m => Unfold m a b -> Stream m a -> Stream m b
432−unfoldMany u m = fromStreamD $ D.unfoldMany u (toStreamD m)
433−
434−-- | This does not pair streams like mergeMapWith, instead, it goes through
435−-- each stream one by one and yields one element from each stream. After it
436−-- goes to the last stream it reverses the traversal to come back to the first
437−-- stream yielding elements from each stream on its way back to the first
438−-- stream and so on.
439−--
440−-- >>> lists = Stream.fromList [[1,1],[2,2],[3,3],[4,4],[5,5]]
441−-- >>> interleaved = Stream.unfoldInterleave Unfold.fromList lists
442−-- >>> Stream.fold Fold.toList interleaved
443−-- [1,2,3,4,5,5,4,3,2,1]
444−--
445−-- Note that this is order of magnitude more efficient than "mergeMapWith
446−-- wSerial" because of fusion.
447−--
448−-- /Fused/
449−{-# INLINE unfoldInterleave #-}
450−unfoldInterleave ::Monad m => Unfold m a b -> Stream m a -> Stream m b
451−unfoldInterleave u m =
452− fromStreamD $ D.unfoldInterleave u (toStreamD m)
453−
454−-- | 'unfoldInterleave' switches to the next stream whenever a value from a
455−-- stream is yielded, it does not switch on a 'Skip'. So if a stream keeps
456−-- skipping for long time other streams won't get a chance to run.
457−-- 'unfoldRoundRobin' switches on Skip as well. So it basically schedules each
458−-- stream fairly irrespective of whether it produces a value or not.
459−--
460−{-# INLINE unfoldRoundRobin #-}
461−unfoldRoundRobin ::Monad m => Unfold m a b -> Stream m a -> Stream m b
462−unfoldRoundRobin u m =
463− fromStreamD $ D.unfoldRoundRobin u (toStreamD m)
464−
465−------------------------------------------------------------------------------
466−-- Combine N Streams - interpose
467−------------------------------------------------------------------------------
468−
469−-- > interpose x unf str = gintercalate unf str UF.identity (repeat x)
470−
471−-- | Unfold the elements of a stream, intersperse the given element between the
472−-- unfolded streams and then concat them into a single stream.
473−--
474−-- >>> unwords = Stream.interpose ' '
475−--
476−-- /Pre-release/
477−{-# INLINE interpose #-}
478−interpose :: Monad m
479− => c -> Unfold m b c -> Stream m b -> Stream m c
480−interpose x unf str =
481− fromStreamD $ D.interpose x unf (toStreamD str)
482−
483−-- interposeSuffix x unf str = gintercalateSuffix unf str UF.identity (repeat x)
484−
485−-- | Unfold the elements of a stream, append the given element after each
486−-- unfolded stream and then concat them into a single stream.
487−--
488−-- >>> unlines = Stream.interposeSuffix '\n'
489−--
490−-- /Pre-release/
491−{-# INLINE interposeSuffix #-}
492−interposeSuffix :: Monad m
493− => c -> Unfold m b c -> Stream m b -> Stream m c
494−interposeSuffix x unf str =
495− fromStreamD $ D.interposeSuffix x unf (toStreamD str)
496−
497−------------------------------------------------------------------------------
498−-- Combine N Streams - intercalate
499−------------------------------------------------------------------------------
500−
501−-- XXX we can swap the order of arguments to gintercalate so that the
502−-- definition of unfoldMany becomes simpler? The first stream should be
503−-- infixed inside the second one. However, if we change the order in
504−-- "interleave" as well similarly, then that will make it a bit unintuitive.
505−--
506−-- > unfoldMany unf str =
507−-- > gintercalate unf str (UF.nilM (\_ -> return ())) (repeat ())
508−
509−-- | 'interleaveFst' followed by unfold and concat.
510−--
511−-- /Pre-release/
512−{-# INLINE gintercalate #-}
513−gintercalate
514− :: Monad m
515− => Unfold m a c -> Stream m a -> Unfold m b c -> Stream m b -> Stream m c
516−gintercalate unf1 str1 unf2 str2 =
517− fromStreamD $ D.gintercalate
518− unf1 (toStreamD str1)
519− unf2 (toStreamD str2)
520−
521−-- > intercalate unf seed str = gintercalate unf str unf (repeatM seed)
522−
523−-- | 'intersperse' followed by unfold and concat.
524−--
525−-- >>> intercalate u a = Stream.unfoldMany u . Stream.intersperse a
526−-- >>> intersperse = Stream.intercalate Unfold.identity
527−-- >>> unwords = Stream.intercalate Unfold.fromList " "
528−--
529−-- >>> input = Stream.fromList ["abc", "def", "ghi"]
530−-- >>> Stream.fold Fold.toList $ Stream.intercalate Unfold.fromList " " input
531−-- "abc def ghi"
532−--
533−{-# INLINE intercalate #-}
534−intercalate :: Monad m
535− => Unfold m b c -> b -> Stream m b -> Stream m c
536−intercalate unf seed str = fromStreamD $
537− D.unfoldMany unf $ D.intersperse seed (toStreamD str)
538−
539−-- | 'interleaveFstSuffix2' followed by unfold and concat.
540−--
541−-- /Pre-release/
542−{-# INLINE gintercalateSuffix #-}
543−gintercalateSuffix
544− :: Monad m
545− => Unfold m a c -> Stream m a -> Unfold m b c -> Stream m b -> Stream m c
546−gintercalateSuffix unf1 str1 unf2 str2 =
547− fromStreamD $ D.gintercalateSuffix
548− unf1 (toStreamD str1)
549− unf2 (toStreamD str2)
550−
551−-- > intercalateSuffix unf seed str = gintercalateSuffix unf str unf (repeatM seed)
552−
553−-- | 'intersperseMSuffix' followed by unfold and concat.
554−--
555−-- >>> intercalateSuffix u a = Stream.unfoldMany u . Stream.intersperseMSuffix a
556−-- >>> intersperseMSuffix = Stream.intercalateSuffix Unfold.identity
557−-- >>> unlines = Stream.intercalateSuffix Unfold.fromList "\n"
558−--
559−-- >>> input = Stream.fromList ["abc", "def", "ghi"]
560−-- >>> Stream.fold Fold.toList $ Stream.intercalateSuffix Unfold.fromList "\n" input
561−-- "abc\ndef\nghi\n"
562−--
563−{-# INLINE intercalateSuffix #-}
564−intercalateSuffix :: Monad m
565− => Unfold m b c -> b -> Stream m b -> Stream m c
566−intercalateSuffix unf seed =
567− fromStreamD . D.intercalateSuffix unf seed . toStreamD
568−
569−------------------------------------------------------------------------------
570−-- Combine N Streams - concatMap
571−------------------------------------------------------------------------------
572−
573−-- | Flatten a stream of streams to a single stream.
574−--
575−-- >>> concat = Stream.concatMap id
576−--
577−-- /Pre-release/
578−{-# INLINE concat #-}
579−concat :: Monad m => Stream m (Stream m a) -> Stream m a
580−concat = concatMap id
581−
582−------------------------------------------------------------------------------
583−-- Combine N Streams - concatMap
584−------------------------------------------------------------------------------
585−
586−-- | Like 'concatMapWith' but carries a state which can be used to share
587−-- information across multiple steps of concat.
588−--
589−-- >>> concatSmapMWith combine f initial = Stream.concatMapWith combine id . Stream.smapM f initial
590−--
591−-- /Pre-release/
592−--
593−{-# INLINE concatSmapMWith #-}
594−concatSmapMWith
595− :: Monad m
596− => (Stream m b -> Stream m b -> Stream m b)
597− -> (s -> a -> m (s, Stream m b))
598− -> m s
599− -> Stream m a
600− -> Stream m b
601−concatSmapMWith combine f initial =
602− concatMapWith combine id . smapM f initial
603−
604−-- XXX Implement a StreamD version for fusion.
605−
606−-- | Combine streams in pairs using a binary combinator, the resulting streams
607−-- are then combined again in pairs recursively until we get to a single
608−-- combined stream. The composition would thus form a binary tree.
609−--
610−-- For example, you can sort a stream using merge sort like this:
611−--
612−-- >>> s = Stream.fromList [5,1,7,9,2]
613−-- >>> generate = Stream.fromPure
614−-- >>> combine = Stream.mergeBy compare
615−-- >>> Stream.fold Fold.toList $ Stream.mergeMapWith combine generate s
616−-- [1,2,5,7,9]
617−--
618−-- Note that if the stream length is not a power of 2, the binary tree composed
619−-- by mergeMapWith would not be balanced, which may or may not be important
620−-- depending on what you are trying to achieve.
621−--
622−-- /Caution: the stream of streams must be finite/
623−--
624−-- /CPS/
625−--
626−-- /Pre-release/
627−--
628−{-# INLINE mergeMapWith #-}
629−mergeMapWith ::
630− (Stream m b -> Stream m b -> Stream m b)
631− -> (a -> Stream m b)
632− -> Stream m a
633− -> Stream m b
634−mergeMapWith par f m =
635− fromStreamK
636− $ K.mergeMapWith
637− (\s1 s2 -> toStreamK $ fromStreamK s1 `par` fromStreamK s2)
638− (toStreamK . f)
639− (toStreamK m)
640−
641−------------------------------------------------------------------------------
642−-- concatIterate - Map and flatten Trees of Streams
643−------------------------------------------------------------------------------
644−
645−-- | Yield an input element in the output stream, map a stream generator on it
646−-- and repeat the process on the resulting stream. Resulting streams are
647−-- flattened using the 'concatMapWith' combinator. This can be used for a depth
648−-- first style (DFS) traversal of a tree like structure.
649−--
650−-- Example, list a directory tree using DFS:
651−--
652−-- >>> f = either Dir.readEitherPaths (const Stream.nil)
653−-- >>> input = Stream.fromPure (Left ".")
654−-- >>> ls = Stream.concatIterateWith Stream.append f input
655−--
656−-- Note that 'iterateM' is a special case of 'concatIterateWith':
657−--
658−-- >>> iterateM f = Stream.concatIterateWith Stream.append (Stream.fromEffect . f) . Stream.fromEffect
659−--
660−-- /CPS/
661−--
662−-- /Pre-release/
663−--
664−{-# INLINE concatIterateWith #-}
665−concatIterateWith ::
666− (Stream m a -> Stream m a -> Stream m a)
667− -> (a -> Stream m a)
668− -> Stream m a
669− -> Stream m a
670−concatIterateWith combine f = iterateStream
671−
672− where
673−
674− iterateStream = concatMapWith combine generate
675−
676− generate x = x `cons` iterateStream (f x)
677−
678−-- | Traverse the stream in depth first style (DFS). Map each element in the
679−-- input stream to a stream and flatten, recursively map the resulting elements
680−-- as well to a stream and flatten until no more streams are generated.
681−--
682−-- Example, list a directory tree using DFS:
683−--
684−-- >>> f = either (Just . Dir.readEitherPaths) (const Nothing)
685−-- >>> input = Stream.fromPure (Left ".")
686−-- >>> ls = Stream.concatIterateDfs f input
687−--
688−-- This is equivalent to using @concatIterateWith Stream.append@.
689−--
690−-- /Pre-release/
691−{-# INLINE concatIterateDfs #-}
692−concatIterateDfs :: Monad m =>
693− (a -> Maybe (Stream m a))
694− -> Stream m a
695− -> Stream m a
696−concatIterateDfs f stream =
697− fromStreamD
698− $ D.concatIterateDfs (fmap toStreamD . f ) (toStreamD stream)
699−
700−-- | Similar to 'concatIterateDfs' except that it traverses the stream in
701−-- breadth first style (BFS). First, all the elements in the input stream are
702−-- emitted, and then their traversals are emitted.
703−--
704−-- Example, list a directory tree using BFS:
705−--
706−-- >>> f = either (Just . Dir.readEitherPaths) (const Nothing)
707−-- >>> input = Stream.fromPure (Left ".")
708−-- >>> ls = Stream.concatIterateBfs f input
709−--
710−-- /Pre-release/
711−{-# INLINE concatIterateBfs #-}
712−concatIterateBfs :: Monad m =>
713− (a -> Maybe (Stream m a))
714− -> Stream m a
715− -> Stream m a
716−concatIterateBfs f stream =
717− fromStreamD
718− $ D.concatIterateBfs (fmap toStreamD . f ) (toStreamD stream)
719−
720−-- | Same as 'concatIterateBfs' except that the traversal of the last
721−-- element on a level is emitted first and then going backwards up to the first
722−-- element (reversed ordering). This may be slightly faster than
723−-- 'concatIterateBfs'.
724−--
725−{-# INLINE concatIterateBfsRev #-}
726−concatIterateBfsRev :: Monad m =>
727− (a -> Maybe (Stream m a))
728− -> Stream m a
729− -> Stream m a
730−concatIterateBfsRev f stream =
731− fromStreamD
732− $ D.concatIterateBfsRev (fmap toStreamD . f ) (toStreamD stream)
733−
734−-- | Like 'concatIterateWith' but uses the pairwise flattening combinator
735−-- 'mergeMapWith' for flattening the resulting streams. This can be used for a
736−-- balanced traversal of a tree like structure.
737−--
738−-- Example, list a directory tree using balanced traversal:
739−--
740−-- >>> f = either Dir.readEitherPaths (const Stream.nil)
741−-- >>> input = Stream.fromPure (Left ".")
742−-- >>> ls = Stream.mergeIterateWith Stream.interleave f input
743−--
744−-- /CPS/
745−--
746−-- /Pre-release/
747−--
748−{-# INLINE mergeIterateWith #-}
749−mergeIterateWith ::
750− (Stream m a -> Stream m a -> Stream m a)
751− -> (a -> Stream m a)
752− -> Stream m a
753− -> Stream m a
754−mergeIterateWith combine f = iterateStream
755−
756− where
757−
758− iterateStream = mergeMapWith combine generate
759−
760− generate x = x `cons` iterateStream (f x)
761−
762−-- | Same as @concatIterateDfs@ but more efficient due to stream fusion.
763−--
764−-- Example, list a directory tree using DFS:
765−--
766−-- >>> f = Unfold.either Dir.eitherReaderPaths Unfold.nil
767−-- >>> input = Stream.fromPure (Left ".")
768−-- >>> ls = Stream.unfoldIterateDfs f input
769−--
770−-- /Pre-release/
771−{-# INLINE unfoldIterateDfs #-}
772−unfoldIterateDfs :: Monad m => Unfold m a a -> Stream m a -> Stream m a
773−unfoldIterateDfs u = fromStreamD . D.unfoldIterateDfs u . toStreamD
774−
775−-- | Like 'unfoldIterateDfs' but uses breadth first style traversal.
776−--
777−-- /Pre-release/
778−{-# INLINE unfoldIterateBfs #-}
779−unfoldIterateBfs :: Monad m => Unfold m a a -> Stream m a -> Stream m a
780−unfoldIterateBfs u = fromStreamD . D.unfoldIterateBfs u . toStreamD
781−
782−-- | Like 'unfoldIterateBfs' but processes the children in reverse order,
783−-- therefore, may be slightly faster.
784−--
785−-- /Pre-release/
786−{-# INLINE unfoldIterateBfsRev #-}
787−unfoldIterateBfsRev :: Monad m => Unfold m a a -> Stream m a -> Stream m a
788−unfoldIterateBfsRev u =
789− fromStreamD . D.unfoldIterateBfsRev u . toStreamD
790−
791−------------------------------------------------------------------------------
792−-- Flattening Graphs
793−------------------------------------------------------------------------------
794−
795−-- To traverse graphs we need a state to be carried around in the traversal.
796−-- For example, we can use a hashmap to store the visited status of nodes.
797−
798−-- | Like 'iterateMap' but carries a state in the stream generation function.
799−-- This can be used to traverse graph like structures, we can remember the
800−-- visited nodes in the state to avoid cycles.
801−--
802−-- Note that a combination of 'iterateMap' and 'usingState' can also be used to
803−-- traverse graphs. However, this function provides a more localized state
804−-- instead of using a global state.
805−--
806−-- See also: 'mfix'
807−--
808−-- /Pre-release/
809−--
810−{-# INLINE concatIterateScanWith #-}
811−concatIterateScanWith
812− :: Monad m
813− => (Stream m a -> Stream m a -> Stream m a)
814− -> (b -> a -> m (b, Stream m a))
815− -> m b
816− -> Stream m a
817− -> Stream m a
818−concatIterateScanWith combine f initial stream =
819− concatEffect $ do
820− b <- initial
821− iterateStream (b, stream)
822−
823− where
824−
825− iterateStream (b, s) = pure $ concatMapWith combine (generate b) s
826−
827− generate b a = a `cons` feedback b a
828−
829− feedback b a = concatEffect $ f b a >>= iterateStream
830−
831−-- Next stream is to be generated by the return value of the previous stream. A
832−-- general intuitive way of doing that could be to use an appending monad
833−-- instance for streams where the result of the previous stream is used to
834−-- generate the next one. In the first pass we can just emit the values in the
835−-- stream and keep building a buffered list/stream, once done we can then
836−-- process the buffered stream.
837−
838−{-# INLINE concatIterateScan #-}
839−concatIterateScan
840− :: Monad m
841− => (b -> a -> m b)
842− -> (b -> m (Maybe (b, Stream m a)))
843− -> b
844− -> Stream m a
845−concatIterateScan scanner generate initial =
846− fromStreamD
847− $ D.concatIterateScan
848− scanner (fmap (fmap (fmap toStreamD)) . generate) initial
849−
850−------------------------------------------------------------------------------
851−-- Either streams
852−------------------------------------------------------------------------------
853−
854−-- Keep concating either streams as long as rights are generated, stop as soon
855−-- as a left is generated and concat the left stream.
856−--
857−-- See also: 'handle'
858−--
859−-- /Unimplemented/
860−--
861−{-
862−concatMapEitherWith
863− :: (forall x. t m x -> t m x -> t m x)
864− -> (a -> t m (Either (Stream m b) b))
865− -> Stream m a
866− -> Stream m b
867−concatMapEitherWith = undefined
868−-}
869−
870−-- XXX We should prefer using the Maybe stream returning signatures over this.
871−-- This API should perhaps be removed in favor of those.
872−
873−-- | In an 'Either' stream iterate on 'Left's. This is a special case of
874−-- 'concatIterateWith':
875−--
876−-- >>> concatIterateLeftsWith combine f = Stream.concatIterateWith combine (either f (const Stream.nil))
877−--
878−-- To traverse a directory tree:
879−--
880−-- >>> input = Stream.fromPure (Left ".")
881−-- >>> ls = Stream.concatIterateLeftsWith Stream.append Dir.readEither input
882−--
883−-- /Pre-release/
884−--
885−{-# INLINE concatIterateLeftsWith #-}
886−concatIterateLeftsWith
887− :: (b ~ Either a c)
888− => (Stream m b -> Stream m b -> Stream m b)
889− -> (a -> Stream m b)
890− -> Stream m b
891− -> Stream m b
892−concatIterateLeftsWith combine f =
893− concatIterateWith combine (either f (const nil))
core/src/Streamly/Internal/Data/Stream/Generate.hsdeleted−460
@@ -1,460 +0,0 @@
1−{-# OPTIONS_GHC -Wno-orphans #-}
2−
3−-- |
4−-- Module : Streamly.Internal.Data.Stream.Generate
5−-- Copyright : (c) 2017 Composewell Technologies
6−-- License : BSD-3-Clause
7−-- Maintainer : streamly@composewell.com
8−-- Stability : experimental
9−-- Portability : GHC
10−--
11−module Streamly.Internal.Data.Stream.Generate
12− (
13− -- * Primitives
14− Stream.nil
15− , Stream.nilM
16− , Stream.cons
17− , Stream.consM
18−
19− -- * From 'Unfold'
20− , unfold
21−
22− -- * Unfolding
23− , unfoldr
24− , unfoldrM
25−
26− -- * From Values
27− , Stream.fromPure
28− , Stream.fromEffect
29− , repeat
30− , repeatM
31− , replicate
32− , replicateM
33−
34− -- * Enumeration
35− , Enumerable (..)
36− , enumerate
37− , enumerateTo
38−
39− -- * Time Enumeration
40− , times
41− , timesWith
42− , absTimes
43− , absTimesWith
44− , relTimes
45− , relTimesWith
46− , durations
47− , timeout
48−
49− -- * Iteration
50− , iterate
51− , iterateM
52−
53− -- * Cyclic Elements
54− , mfix
55−
56− -- * From Containers
57− , Bottom.fromList
58− , fromFoldable
59−
60− -- * From memory
61− , fromPtr
62− , fromPtrN
63− , fromByteStr#
64− -- , fromByteArray#
65− , fromUnboxedIORef
66− )
67−where
68−
69−#include "inline.hs"
70−
71−import Control.Monad.IO.Class (MonadIO)
72−import Data.Word (Word8)
73−import Foreign.Storable (Storable)
74−import GHC.Exts (Addr#, Ptr (Ptr))
75−import Streamly.Internal.Data.Stream.Bottom
76− (absTimesWith, relTimesWith, timesWith)
77−import Streamly.Internal.Data.Stream.Enumerate
78− (Enumerable(..), enumerate, enumerateTo)
79−import Streamly.Internal.Data.Stream.Type
80− (Stream, fromStreamD, fromStreamK, toStreamK)
81−import Streamly.Internal.Data.Time.Units (AbsTime, RelTime64, addToAbsTime64)
82−import Streamly.Internal.Data.Unbox (Unbox)
83−import Streamly.Internal.Data.Unfold.Type (Unfold)
84−
85−import qualified Streamly.Internal.Data.IORef.Unboxed as Unboxed
86−import qualified Streamly.Internal.Data.Stream.Bottom as Bottom
87−import qualified Streamly.Internal.Data.Stream as D
88−import qualified Streamly.Internal.Data.Stream.StreamK.Type as K
89−import qualified Streamly.Internal.Data.Stream.Type as Stream
90−import qualified Streamly.Internal.Data.Stream.Transform as Stream (sequence)
91−
92−import Prelude hiding (iterate, replicate, repeat, take)
93−
94−-- $setup
95−-- >>> :m
96−-- >>> import Control.Concurrent (threadDelay)
97−-- >>> import Data.Function (fix, (&))
98−-- >>> import Data.Semigroup (cycle1)
99−-- >>> import Streamly.Internal.Data.Stream.Cross (CrossStream(..))
100−-- >>> import qualified Streamly.Data.Fold as Fold
101−-- >>> import qualified Streamly.Data.Unfold as Unfold
102−-- >>> import qualified Streamly.Internal.Data.Stream as Stream
103−-- >>> import GHC.Exts (Ptr (Ptr))
104−
105−------------------------------------------------------------------------------
106−-- From Unfold
107−------------------------------------------------------------------------------
108−
109−-- | Convert an 'Unfold' into a stream by supplying it an input seed.
110−--
111−-- >>> s = Stream.unfold Unfold.replicateM (3, putStrLn "hello")
112−-- >>> Stream.fold Fold.drain s
113−-- hello
114−-- hello
115−-- hello
116−--
117−{-# INLINE unfold #-}
118−unfold :: Monad m => Unfold m a b -> a -> Stream m b
119−unfold unf = Stream.fromStreamD . D.unfold unf
120−
121−------------------------------------------------------------------------------
122−-- Generation by Unfolding
123−------------------------------------------------------------------------------
124−
125−-- |
126−-- >>> :{
127−-- unfoldr step s =
128−-- case step s of
129−-- Nothing -> Stream.nil
130−-- Just (a, b) -> a `Stream.cons` unfoldr step b
131−-- :}
132−--
133−-- Build a stream by unfolding a /pure/ step function @step@ starting from a
134−-- seed @s@. The step function returns the next element in the stream and the
135−-- next seed value. When it is done it returns 'Nothing' and the stream ends.
136−-- For example,
137−--
138−-- >>> :{
139−-- let f b =
140−-- if b > 2
141−-- then Nothing
142−-- else Just (b, b + 1)
143−-- in Stream.fold Fold.toList $ Stream.unfoldr f 0
144−-- :}
145−-- [0,1,2]
146−--
147−{-# INLINE_EARLY unfoldr #-}
148−unfoldr :: Monad m => (b -> Maybe (a, b)) -> b -> Stream m a
149−unfoldr step seed = fromStreamD (D.unfoldr step seed)
150−{-# RULES "unfoldr fallback to StreamK" [1]
151− forall a b. D.toStreamK (D.unfoldr a b) = K.unfoldr a b #-}
152−
153−-- | Build a stream by unfolding a /monadic/ step function starting from a
154−-- seed. The step function returns the next element in the stream and the next
155−-- seed value. When it is done it returns 'Nothing' and the stream ends. For
156−-- example,
157−--
158−-- >>> :{
159−-- let f b =
160−-- if b > 2
161−-- then return Nothing
162−-- else return (Just (b, b + 1))
163−-- in Stream.fold Fold.toList $ Stream.unfoldrM f 0
164−-- :}
165−-- [0,1,2]
166−--
167−{-# INLINE unfoldrM #-}
168−unfoldrM :: Monad m => (b -> m (Maybe (a, b))) -> b -> Stream m a
169−unfoldrM step = fromStreamD . D.unfoldrM step
170−
171−------------------------------------------------------------------------------
172−-- From Values
173−------------------------------------------------------------------------------
174−
175−-- |
176−-- Generate an infinite stream by repeating a pure value.
177−--
178−{-# INLINE_NORMAL repeat #-}
179−repeat :: Monad m => a -> Stream m a
180−repeat = fromStreamD . D.repeat
181−
182−-- |
183−-- >>> repeatM = Stream.sequence . Stream.repeat
184−-- >>> repeatM = fix . Stream.consM
185−-- >>> repeatM = cycle1 . Stream.fromEffect
186−--
187−-- Generate a stream by repeatedly executing a monadic action forever.
188−--
189−-- >>> :{
190−-- repeatAction =
191−-- Stream.repeatM (threadDelay 1000000 >> print 1)
192−-- & Stream.take 10
193−-- & Stream.fold Fold.drain
194−-- :}
195−--
196−{-# INLINE_NORMAL repeatM #-}
197−repeatM :: Monad m => m a -> Stream m a
198−repeatM = Stream.sequence . repeat
199−
200−-- |
201−-- >>> replicate n = Stream.take n . Stream.repeat
202−--
203−-- Generate a stream of length @n@ by repeating a value @n@ times.
204−--
205−{-# INLINE_NORMAL replicate #-}
206−replicate :: Monad m => Int -> a -> Stream m a
207−replicate n = fromStreamD . D.replicate n
208−
209−-- |
210−-- >>> replicateM n = Stream.sequence . Stream.replicate n
211−--
212−-- Generate a stream by performing a monadic action @n@ times.
213−{-# INLINE_NORMAL replicateM #-}
214−replicateM :: Monad m => Int -> m a -> Stream m a
215−replicateM n = Stream.sequence . replicate n
216−
217−------------------------------------------------------------------------------
218−-- Time Enumeration
219−------------------------------------------------------------------------------
220−
221−-- | @times@ returns a stream of time value tuples with clock of 10 ms
222−-- granularity. The first component of the tuple is an absolute time reference
223−-- (epoch) denoting the start of the stream and the second component is a time
224−-- relative to the reference.
225−--
226−-- >>> f = Fold.drainMapM (\x -> print x >> threadDelay 1000000)
227−-- >>> Stream.fold f $ Stream.take 3 $ Stream.times
228−-- (AbsTime (TimeSpec {sec = ..., nsec = ...}),RelTime64 (NanoSecond64 ...))
229−-- (AbsTime (TimeSpec {sec = ..., nsec = ...}),RelTime64 (NanoSecond64 ...))
230−-- (AbsTime (TimeSpec {sec = ..., nsec = ...}),RelTime64 (NanoSecond64 ...))
231−--
232−-- Note: This API is not safe on 32-bit machines.
233−--
234−-- /Pre-release/
235−--
236−{-# INLINE times #-}
237−times :: MonadIO m => Stream m (AbsTime, RelTime64)
238−times = timesWith 0.01
239−
240−-- | @absTimes@ returns a stream of absolute timestamps using a clock of 10 ms
241−-- granularity.
242−--
243−-- >>> f = Fold.drainMapM print
244−-- >>> Stream.fold f $ Stream.delayPre 1 $ Stream.take 3 $ Stream.absTimes
245−-- AbsTime (TimeSpec {sec = ..., nsec = ...})
246−-- AbsTime (TimeSpec {sec = ..., nsec = ...})
247−-- AbsTime (TimeSpec {sec = ..., nsec = ...})
248−--
249−-- Note: This API is not safe on 32-bit machines.
250−--
251−-- /Pre-release/
252−--
253−{-# INLINE absTimes #-}
254−absTimes :: MonadIO m => Stream m AbsTime
255−absTimes = fmap (uncurry addToAbsTime64) times
256−
257−-- | @relTimes@ returns a stream of relative time values starting from 0,
258−-- using a clock of granularity 10 ms.
259−--
260−-- >>> f = Fold.drainMapM print
261−-- >>> Stream.fold f $ Stream.delayPre 1 $ Stream.take 3 $ Stream.relTimes
262−-- RelTime64 (NanoSecond64 ...)
263−-- RelTime64 (NanoSecond64 ...)
264−-- RelTime64 (NanoSecond64 ...)
265−--
266−-- Note: This API is not safe on 32-bit machines.
267−--
268−-- /Pre-release/
269−--
270−{-# INLINE relTimes #-}
271−relTimes :: MonadIO m => Stream m RelTime64
272−relTimes = fmap snd times
273−
274−-- | @durations g@ returns a stream of relative time values measuring the time
275−-- elapsed since the immediate predecessor element of the stream was generated.
276−-- The first element of the stream is always 0. @durations@ uses a clock of
277−-- granularity @g@ specified in seconds. A low granularity clock is more
278−-- expensive in terms of CPU usage. The minimum granularity is 1 millisecond.
279−-- Durations lower than 1 ms will be 0.
280−--
281−-- Note: This API is not safe on 32-bit machines.
282−--
283−-- /Unimplemented/
284−--
285−{-# INLINE durations #-}
286−durations :: -- Monad m =>
287− Double -> t m RelTime64
288−durations = undefined
289−
290−-- | Generate a singleton event at or after the specified absolute time. Note
291−-- that this is different from a threadDelay, a threadDelay starts from the
292−-- time when the action is evaluated, whereas if we use AbsTime based timeout
293−-- it will immediately expire if the action is evaluated too late.
294−--
295−-- /Unimplemented/
296−--
297−{-# INLINE timeout #-}
298−timeout :: -- Monad m =>
299− AbsTime -> t m ()
300−timeout = undefined
301−
302−------------------------------------------------------------------------------
303−-- Iterating functions
304−------------------------------------------------------------------------------
305−
306−-- |
307−-- >>> iterate f x = x `Stream.cons` iterate f x
308−--
309−-- Generate an infinite stream with @x@ as the first element and each
310−-- successive element derived by applying the function @f@ on the previous
311−-- element.
312−--
313−-- >>> Stream.fold Fold.toList $ Stream.take 5 $ Stream.iterate (+1) 1
314−-- [1,2,3,4,5]
315−--
316−{-# INLINE_NORMAL iterate #-}
317−iterate :: Monad m => (a -> a) -> a -> Stream m a
318−iterate step = fromStreamD . D.iterate step
319−
320−-- |
321−-- >>> iterateM f m = m >>= \a -> return a `Stream.consM` iterateM f (f a)
322−--
323−-- Generate an infinite stream with the first element generated by the action
324−-- @m@ and each successive element derived by applying the monadic function
325−-- @f@ on the previous element.
326−--
327−-- >>> :{
328−-- Stream.iterateM (\x -> print x >> return (x + 1)) (return 0)
329−-- & Stream.take 3
330−-- & Stream.fold Fold.toList
331−-- :}
332−-- 0
333−-- 1
334−-- [0,1,2]
335−--
336−{-# INLINE iterateM #-}
337−iterateM :: Monad m => (a -> m a) -> m a -> Stream m a
338−iterateM step = fromStreamD . D.iterateM step
339−
340−-- | We can define cyclic structures using @let@:
341−--
342−-- >>> let (a, b) = ([1, b], head a) in (a, b)
343−-- ([1,1],1)
344−--
345−-- The function @fix@ defined as:
346−--
347−-- >>> fix f = let x = f x in x
348−--
349−-- ensures that the argument of a function and its output refer to the same
350−-- lazy value @x@ i.e. the same location in memory. Thus @x@ can be defined
351−-- in terms of itself, creating structures with cyclic references.
352−--
353−-- >>> f ~(a, b) = ([1, b], head a)
354−-- >>> fix f
355−-- ([1,1],1)
356−--
357−-- 'Control.Monad.mfix' is essentially the same as @fix@ but for monadic
358−-- values.
359−--
360−-- Using 'mfix' for streams we can construct a stream in which each element of
361−-- the stream is defined in a cyclic fashion. The argument of the function
362−-- being fixed represents the current element of the stream which is being
363−-- returned by the stream monad. Thus, we can use the argument to construct
364−-- itself.
365−--
366−-- In the following example, the argument @action@ of the function @f@
367−-- represents the tuple @(x,y)@ returned by it in a given iteration. We define
368−-- the first element of the tuple in terms of the second.
369−--
370−-- >>> import Streamly.Internal.Data.Stream as Stream
371−-- >>> import System.IO.Unsafe (unsafeInterleaveIO)
372−--
373−-- >>> :{
374−-- main = Stream.fold (Fold.drainMapM print) $ Stream.mfix f
375−-- where
376−-- f action = unCrossStream $ do
377−-- let incr n act = fmap ((+n) . snd) $ unsafeInterleaveIO act
378−-- x <- CrossStream (Stream.sequence $ Stream.fromList [incr 1 action, incr 2 action])
379−-- y <- CrossStream (Stream.fromList [4,5])
380−-- return (x, y)
381−-- :}
382−--
383−-- Note: you cannot achieve this by just changing the order of the monad
384−-- statements because that would change the order in which the stream elements
385−-- are generated.
386−--
387−-- Note that the function @f@ must be lazy in its argument, that's why we use
388−-- 'unsafeInterleaveIO' on @action@ because IO monad is strict.
389−--
390−-- /CPS/
391−--
392−-- /Pre-release/
393−{-# INLINE mfix #-}
394−mfix :: Monad m => (m a -> Stream m a) -> Stream m a
395−mfix f = fromStreamK $ K.mfix (toStreamK . f)
396−
397−------------------------------------------------------------------------------
398−-- Conversions
399−------------------------------------------------------------------------------
400−
401−-- |
402−-- >>> fromFoldable = Prelude.foldr Stream.cons Stream.nil
403−--
404−-- Construct a stream from a 'Foldable' containing pure values:
405−--
406−-- /CPS/
407−--
408−{-# INLINE fromFoldable #-}
409−fromFoldable :: Foldable f => f a -> Stream m a
410−fromFoldable = fromStreamK . K.fromFoldable
411−
412−------------------------------------------------------------------------------
413−-- From pointers
414−------------------------------------------------------------------------------
415−
416−-- | Keep reading 'Storable' elements from 'Ptr' onwards.
417−--
418−-- /Unsafe:/ The caller is responsible for safe addressing.
419−--
420−-- /Pre-release/
421−{-# INLINE fromPtr #-}
422−fromPtr :: (MonadIO m, Storable a) => Ptr a -> Stream m a
423−fromPtr = Stream.fromStreamD . D.fromPtr
424−
425−-- | Take @n@ 'Storable' elements starting from 'Ptr' onwards.
426−--
427−-- >>> fromPtrN n = Stream.take n . Stream.fromPtr
428−--
429−-- /Unsafe:/ The caller is responsible for safe addressing.
430−--
431−-- /Pre-release/
432−{-# INLINE fromPtrN #-}
433−fromPtrN :: (MonadIO m, Storable a) => Int -> Ptr a -> Stream m a
434−fromPtrN n = Stream.fromStreamD . D.take n . D.fromPtr
435−
436−-- | Read bytes from an 'Addr#' until a 0 byte is encountered, the 0 byte is
437−-- not included in the stream.
438−--
439−-- >>> fromByteStr# addr = Stream.takeWhile (/= 0) $ Stream.fromPtr $ Ptr addr
440−--
441−-- /Unsafe:/ The caller is responsible for safe addressing.
442−--
443−-- Note that this is completely safe when reading from Haskell string
444−-- literals because they are guaranteed to be NULL terminated:
445−--
446−-- >>> Stream.fold Fold.toList $ Stream.fromByteStr# "\1\2\3\0"#
447−-- [1,2,3]
448−--
449−{-# INLINE fromByteStr# #-}
450−fromByteStr# :: MonadIO m => Addr# -> Stream m Word8
451−fromByteStr# addr =
452− Stream.fromStreamD $ D.takeWhile (/= 0) $ D.fromPtr $ Ptr addr
453−
454−-- | Construct a stream by reading an 'Unboxed' 'IORef' repeatedly.
455−--
456−-- /Pre-release/
457−--
458−{-# INLINE fromUnboxedIORef #-}
459−fromUnboxedIORef :: (MonadIO m, Unbox a) => Unboxed.IORef a -> Stream m a
460−fromUnboxedIORef = fromStreamD . Unboxed.toStreamD
core/src/Streamly/Internal/Data/Stream/Lift.hsdeleted−95
@@ -1,95 +0,0 @@
1−-- |
2−-- Module : Streamly.Internal.Data.Stream.Lift
3−-- Copyright : (c) 2019 Composewell Technologies
4−-- License : BSD-3-Clause
5−-- Maintainer : streamly@composewell.com
6−-- Stability : experimental
7−-- Portability : GHC
8−
9−module Streamly.Internal.Data.Stream.Lift
10− (
11− -- * Generalize Inner Monad
12− morphInner
13− , generalizeInner
14−
15− -- * Transform Inner Monad
16− , liftInnerWith
17− , runInnerWith
18− , runInnerWithState
19− )
20−where
21−
22−import Data.Functor.Identity (Identity (..))
23−import Streamly.Internal.Data.Stream.Type
24− (Stream, fromStreamD, toStreamD, fromStreamK, toStreamK)
25−
26−import qualified Streamly.Internal.Data.Stream as D
27−import qualified Streamly.Internal.Data.StreamK as K
28−
29−-- $setup
30−-- >>> :m
31−-- >>> import Data.Functor.Identity (runIdentity)
32−-- >>> import Streamly.Internal.Data.Stream as Stream
33−
34−------------------------------------------------------------------------------
35−-- Generalize the underlying monad
36−------------------------------------------------------------------------------
37−
38−-- | Transform the inner monad of a stream using a natural transformation.
39−--
40−-- Example, generalize the inner monad from Identity to any other:
41−--
42−-- >>> generalizeInner = Stream.morphInner (return . runIdentity)
43−--
44−-- Also known as hoist.
45−--
46−-- /CPS/
47−{-# INLINE morphInner #-}
48−morphInner :: (Monad m, Monad n)
49− => (forall x. m x -> n x) -> Stream m a -> Stream n a
50−morphInner f xs = fromStreamK $ K.hoist f (toStreamK xs)
51−
52−-- | Generalize the inner monad of the stream from 'Identity' to any monad.
53−--
54−-- Definition:
55−--
56−-- >>> generalizeInner = Stream.morphInner (return . runIdentity)
57−--
58−-- /CPS/
59−--
60−{-# INLINE generalizeInner #-}
61−generalizeInner :: Monad m => Stream Identity a -> Stream m a
62−generalizeInner = morphInner (return . runIdentity)
63− -- fromStreamK $ K.hoist (return . runIdentity) (toStreamK xs)
64−
65−------------------------------------------------------------------------------
66−-- Add and remove a monad transformer
67−------------------------------------------------------------------------------
68−
69−-- | Lift the inner monad @m@ of a stream @Stream m a@ to @t m@ using the
70−-- supplied lift function.
71−--
72−{-# INLINE liftInnerWith #-}
73−liftInnerWith :: (Monad m, Monad (t m))
74− => (forall b. m b -> t m b) -> Stream m a -> Stream (t m) a
75−liftInnerWith lift xs = fromStreamD $ D.liftInnerWith lift (toStreamD xs)
76−
77−-- | Evaluate the inner monad of a stream using the supplied runner function.
78−--
79−{-# INLINE runInnerWith #-}
80−runInnerWith :: (Monad m, Applicative (t m)) =>
81− (forall b. t m b -> m b) -> Stream (t m) a -> Stream m a
82−runInnerWith run xs = fromStreamD $ D.runInnerWith run (toStreamD xs)
83−
84−-- | Evaluate the inner monad of a stream using the supplied stateful runner
85−-- function and the initial state. The state returned by an invocation of the
86−-- runner is supplied as input state to the next invocation.
87−--
88−{-# INLINE runInnerWithState #-}
89−runInnerWithState :: (Monad m, Applicative (t m)) =>
90− (forall b. s -> t m b -> m (b, s))
91− -> m s
92− -> Stream (t m) a
93− -> Stream m (s, a)
94−runInnerWithState run initial xs =
95− fromStreamD $ D.runInnerWithState run initial (toStreamD xs)
core/src/Streamly/Internal/Data/Stream/Reduce.hsdeleted−444
@@ -1,444 +0,0 @@
1−-- |
2−-- Module : Streamly.Internal.Data.Stream.Reduce
3−-- Copyright : (c) 2017 Composewell Technologies
4−-- License : BSD-3-Clause
5−-- Maintainer : streamly@composewell.com
6−-- Stability : experimental
7−-- Portability : GHC
8−--
9−-- Reduce streams by streams, folds or parsers.
10−
11−module Streamly.Internal.Data.Stream.Reduce
12− (
13− -- * Reduce By Streams
14− dropPrefix
15− , dropInfix
16− , dropSuffix
17−
18− -- * Reduce By Folds
19− -- |
20− -- Reduce a stream by folding or parsing chunks of the stream. Functions
21− -- generally ending in these shapes:
22− --
23− -- @
24− -- f (Fold m a b) -> Stream m a -> Stream m b
25− -- f (Parser a m b) -> Stream m a -> Stream m b
26− -- @
27−
28− -- ** Generic Folding
29− -- | Apply folds on a stream.
30− , foldMany
31− , foldManyPost
32− , refoldMany
33− , foldSequence
34− , foldIterateM
35− , refoldIterateM
36− , reduceIterateBfs
37−
38− -- ** Chunking
39− -- | Element unaware grouping.
40− , chunksOf
41−
42− -- ** Splitting
43− -- XXX Implement these as folds or parsers instead.
44− , splitOnSuffixSeqAny
45− , splitOnPrefix
46− , splitOnAny
47−
48− -- * Reduce By Parsers
49− -- ** Generic Parsing
50− -- | Apply parsers on a stream.
51− , parseMany
52− , parseManyD
53− , parseManyTill
54− , parseSequence
55− , parseIterate
56−
57− )
58−where
59−
60−import Control.Monad.IO.Class (MonadIO(..))
61−import Streamly.Internal.Data.Array.Type (Array)
62−import Streamly.Internal.Data.Fold.Type (Fold (..))
63−import Streamly.Internal.Data.Parser (Parser (..))
64−import Streamly.Internal.Data.Parser (ParseError)
65−import Streamly.Internal.Data.Refold.Type (Refold (..))
66−import Streamly.Internal.Data.Stream.Bottom (foldManyPost)
67−import Streamly.Internal.Data.Stream.Type (Stream, fromStreamD, toStreamD)
68−import Streamly.Internal.Data.Unbox (Unbox)
69−
70−import qualified Streamly.Internal.Data.Array.Type as Array
71−import qualified Streamly.Internal.Data.Parser as ParserD
72−import qualified Streamly.Internal.Data.Stream as D
73−
74−import Prelude hiding (concatMap, map)
75−
76−-- $setup
77−-- >>> :m
78−-- >>> import Prelude hiding (zipWith, concatMap, concat)
79−-- >>> import Streamly.Internal.Data.Stream as Stream
80−-- >>> import qualified Streamly.Data.Fold as Fold
81−-- >>> import qualified Streamly.Internal.Data.Fold as Fold
82−-- >>> import qualified Streamly.Internal.Data.Unfold as Unfold
83−-- >>> import qualified Streamly.Internal.Data.Parser as Parser
84−-- >>> import qualified Streamly.Data.Array as Array
85−
86−------------------------------------------------------------------------------
87−-- Trimming
88−------------------------------------------------------------------------------
89−
90−-- | Drop prefix from the input stream if present.
91−--
92−-- Space: @O(1)@
93−--
94−-- /Unimplemented/
95−{-# INLINE dropPrefix #-}
96−dropPrefix ::
97− -- (Monad m, Eq a) =>
98− Stream m a -> Stream m a -> Stream m a
99−dropPrefix = error "Not implemented yet!"
100−
101−-- | Drop all matching infix from the input stream if present. Infix stream
102−-- may be consumed multiple times.
103−--
104−-- Space: @O(n)@ where n is the length of the infix.
105−--
106−-- /Unimplemented/
107−{-# INLINE dropInfix #-}
108−dropInfix ::
109− -- (Monad m, Eq a) =>
110− Stream m a -> Stream m a -> Stream m a
111−dropInfix = error "Not implemented yet!"
112−
113−-- | Drop suffix from the input stream if present. Suffix stream may be
114−-- consumed multiple times.
115−--
116−-- Space: @O(n)@ where n is the length of the suffix.
117−--
118−-- /Unimplemented/
119−{-# INLINE dropSuffix #-}
120−dropSuffix ::
121− -- (Monad m, Eq a) =>
122− Stream m a -> Stream m a -> Stream m a
123−dropSuffix = error "Not implemented yet!"
124−
125−------------------------------------------------------------------------------
126−-- Folding
127−------------------------------------------------------------------------------
128−
129−-- | Apply a 'Fold' repeatedly on a stream and emit the results in the
130−-- output stream. Unlike 'foldManyPost' it evaluates the fold after the stream,
131−-- therefore, an empty input stream results in an empty output stream.
132−--
133−-- Definition:
134−--
135−-- >>> foldMany f = Stream.parseMany (Parser.fromFold f)
136−--
137−-- Example, empty stream:
138−--
139−-- >>> f = Fold.take 2 Fold.sum
140−-- >>> fmany = Stream.fold Fold.toList . Stream.foldMany f
141−-- >>> fmany $ Stream.fromList []
142−-- []
143−--
144−-- Example, last fold empty:
145−--
146−-- >>> fmany $ Stream.fromList [1..4]
147−-- [3,7]
148−--
149−-- Example, last fold non-empty:
150−--
151−-- >>> fmany $ Stream.fromList [1..5]
152−-- [3,7,5]
153−--
154−-- Note that using a closed fold e.g. @Fold.take 0@, would result in an
155−-- infinite stream on a non-empty input stream.
156−--
157−{-# INLINE foldMany #-}
158−foldMany
159− :: Monad m
160− => Fold m a b
161− -> Stream m a
162− -> Stream m b
163−foldMany f m = fromStreamD $ D.foldMany f (toStreamD m)
164−
165−-- | Like 'foldMany' but using the 'Refold' type instead of 'Fold'.
166−--
167−-- /Pre-release/
168−{-# INLINE refoldMany #-}
169−refoldMany :: Monad m =>
170− Refold m c a b -> m c -> Stream m a -> Stream m b
171−refoldMany f action = fromStreamD . D.refoldMany f action . toStreamD
172−
173−-- | Apply a stream of folds to an input stream and emit the results in the
174−-- output stream.
175−--
176−-- /Unimplemented/
177−--
178−{-# INLINE foldSequence #-}
179−foldSequence
180− :: -- Monad m =>
181− Stream m (Fold m a b)
182− -> Stream m a
183− -> Stream m b
184−foldSequence _f _m = undefined
185−
186−-- | Iterate a fold generator on a stream. The initial value @b@ is used to
187−-- generate the first fold, the fold is applied on the stream and the result of
188−-- the fold is used to generate the next fold and so on.
189−--
190−-- >>> import Data.Monoid (Sum(..))
191−-- >>> f x = return (Fold.take 2 (Fold.sconcat x))
192−-- >>> s = fmap Sum $ Stream.fromList [1..10]
193−-- >>> Stream.fold Fold.toList $ fmap getSum $ Stream.foldIterateM f (pure 0) s
194−-- [3,10,21,36,55,55]
195−--
196−-- This is the streaming equivalent of monad like sequenced application of
197−-- folds where next fold is dependent on the previous fold.
198−--
199−-- /Pre-release/
200−--
201−{-# INLINE foldIterateM #-}
202−foldIterateM ::
203− Monad m => (b -> m (Fold m a b)) -> m b -> Stream m a -> Stream m b
204−foldIterateM f i m = fromStreamD $ D.foldIterateM f i (toStreamD m)
205−
206−-- | Like 'foldIterateM' but using the 'Refold' type instead. This could be
207−-- much more efficient due to stream fusion.
208−--
209−-- /Internal/
210−{-# INLINE refoldIterateM #-}
211−refoldIterateM :: Monad m =>
212− Refold m b a b -> m b -> Stream m a -> Stream m b
213−refoldIterateM c i m = fromStreamD $ D.refoldIterateM c i (toStreamD m)
214−
215−-- | Binary BFS style reduce, folds a level entirely using the supplied fold
216−-- function, collecting the outputs as next level of the tree, then repeats the
217−-- same process on the next level. The last elements of a previously folded
218−-- level are folded first.
219−{-# INLINE reduceIterateBfs #-}
220−reduceIterateBfs :: Monad m =>
221− (a -> a -> m a) -> Stream m a -> m (Maybe a)
222−reduceIterateBfs f stream = D.reduceIterateBfs f (toStreamD stream)
223−
224−------------------------------------------------------------------------------
225−-- Splitting
226−------------------------------------------------------------------------------
227−
228−-- Implement this as a fold or a parser instead.
229−-- This can be implemented easily using Rabin Karp
230−-- | Split post any one of the given patterns.
231−--
232−-- /Unimplemented/
233−{-# INLINE splitOnSuffixSeqAny #-}
234−splitOnSuffixSeqAny :: -- (Monad m, Unboxed a, Integral a) =>
235− [Array a] -> Fold m a b -> Stream m a -> Stream m b
236−splitOnSuffixSeqAny _subseq _f _m = undefined
237− -- D.fromStreamD $ D.splitPostAny f subseq (D.toStreamD m)
238−
239−-- | Split on a prefixed separator element, dropping the separator. The
240−-- supplied 'Fold' is applied on the split segments.
241−--
242−-- @
243−-- > splitOnPrefix' p xs = Stream.toList $ Stream.splitOnPrefix p (Fold.toList) (Stream.fromList xs)
244−-- > splitOnPrefix' (== '.') ".a.b"
245−-- ["a","b"]
246−-- @
247−--
248−-- An empty stream results in an empty output stream:
249−-- @
250−-- > splitOnPrefix' (== '.') ""
251−-- []
252−-- @
253−--
254−-- An empty segment consisting of only a prefix is folded to the default output
255−-- of the fold:
256−--
257−-- @
258−-- > splitOnPrefix' (== '.') "."
259−-- [""]
260−--
261−-- > splitOnPrefix' (== '.') ".a.b."
262−-- ["a","b",""]
263−--
264−-- > splitOnPrefix' (== '.') ".a..b"
265−-- ["a","","b"]
266−--
267−-- @
268−--
269−-- A prefix is optional at the beginning of the stream:
270−--
271−-- @
272−-- > splitOnPrefix' (== '.') "a"
273−-- ["a"]
274−--
275−-- > splitOnPrefix' (== '.') "a.b"
276−-- ["a","b"]
277−-- @
278−--
279−-- 'splitOnPrefix' is an inverse of 'intercalatePrefix' with a single element:
280−--
281−-- > Stream.intercalatePrefix (Stream.fromPure '.') Unfold.fromList . Stream.splitOnPrefix (== '.') Fold.toList === id
282−--
283−-- Assuming the input stream does not contain the separator:
284−--
285−-- > Stream.splitOnPrefix (== '.') Fold.toList . Stream.intercalatePrefix (Stream.fromPure '.') Unfold.fromList === id
286−--
287−-- /Unimplemented/
288−{-# INLINE splitOnPrefix #-}
289−splitOnPrefix :: -- (IsStream t, MonadCatch m) =>
290− (a -> Bool) -> Fold m a b -> Stream m a -> Stream m b
291−splitOnPrefix _predicate _f = undefined
292− -- parseMany (Parser.sliceBeginBy predicate f)
293−
294−-- Int list examples for splitOn:
295−--
296−-- >>> splitList [] [1,2,3,3,4]
297−-- > [[1],[2],[3],[3],[4]]
298−--
299−-- >>> splitList [5] [1,2,3,3,4]
300−-- > [[1,2,3,3,4]]
301−--
302−-- >>> splitList [1] [1,2,3,3,4]
303−-- > [[],[2,3,3,4]]
304−--
305−-- >>> splitList [4] [1,2,3,3,4]
306−-- > [[1,2,3,3],[]]
307−--
308−-- >>> splitList [2] [1,2,3,3,4]
309−-- > [[1],[3,3,4]]
310−--
311−-- >>> splitList [3] [1,2,3,3,4]
312−-- > [[1,2],[],[4]]
313−--
314−-- >>> splitList [3,3] [1,2,3,3,4]
315−-- > [[1,2],[4]]
316−--
317−-- >>> splitList [1,2,3,3,4] [1,2,3,3,4]
318−-- > [[],[]]
319−
320−-- This can be implemented easily using Rabin Karp
321−-- | Split on any one of the given patterns.
322−--
323−-- /Unimplemented/
324−--
325−{-# INLINE splitOnAny #-}
326−splitOnAny :: -- (Monad m, Unboxed a, Integral a) =>
327− [Array a] -> Fold m a b -> Stream m a -> Stream m b
328−splitOnAny _subseq _f _m =
329− undefined -- D.fromStreamD $ D.splitOnAny f subseq (D.toStreamD m)
330−
331−------------------------------------------------------------------------------
332−-- Parsing
333−------------------------------------------------------------------------------
334−
335−-- | Apply a 'Parser' repeatedly on a stream and emit the parsed values in the
336−-- output stream.
337−--
338−-- Example:
339−--
340−-- >>> s = Stream.fromList [1..10]
341−-- >>> parser = Parser.takeBetween 0 2 Fold.sum
342−-- >>> Stream.fold Fold.toList $ Stream.parseMany parser s
343−-- [Right 3,Right 7,Right 11,Right 15,Right 19]
344−--
345−-- This is the streaming equivalent of the 'Streamly.Data.Parser.many' parse
346−-- combinator.
347−--
348−-- Known Issues: When the parser fails there is no way to get the remaining
349−-- stream.
350−--
351−{-# INLINE parseMany #-}
352−parseMany
353− :: Monad m
354− => Parser a m b
355− -> Stream m a
356− -> Stream m (Either ParseError b)
357−parseMany p m =
358− fromStreamD $ D.parseManyD p (toStreamD m)
359−
360−-- | Same as parseMany but for StreamD streams.
361−--
362−-- /Internal/
363−--
364−{-# INLINE parseManyD #-}
365−parseManyD
366− :: Monad m
367− => ParserD.Parser a m b
368− -> Stream m a
369− -> Stream m (Either ParseError b)
370−parseManyD p m =
371− fromStreamD $ D.parseManyD p (toStreamD m)
372−
373−-- | Apply a stream of parsers to an input stream and emit the results in the
374−-- output stream.
375−--
376−-- /Unimplemented/
377−--
378−{-# INLINE parseSequence #-}
379−parseSequence
380− :: -- Monad m =>
381− Stream m (Parser a m b)
382− -> Stream m a
383− -> Stream m b
384−parseSequence _f _m = undefined
385−
386−-- XXX Change the parser arguments' order
387−
388−-- | @parseManyTill collect test stream@ tries the parser @test@ on the input,
389−-- if @test@ fails it backtracks and tries @collect@, after @collect@ succeeds
390−-- @test@ is tried again and so on. The parser stops when @test@ succeeds. The
391−-- output of @test@ is discarded and the output of @collect@ is emitted in the
392−-- output stream. The parser fails if @collect@ fails.
393−--
394−-- /Unimplemented/
395−--
396−{-# INLINE parseManyTill #-}
397−parseManyTill ::
398− -- MonadThrow m =>
399− Parser a m b
400− -> Parser a m x
401− -> t m a
402− -> t m b
403−parseManyTill = undefined
404−
405−-- | Iterate a parser generating function on a stream. The initial value @b@ is
406−-- used to generate the first parser, the parser is applied on the stream and
407−-- the result is used to generate the next parser and so on.
408−--
409−-- >>> import Data.Monoid (Sum(..))
410−-- >>> s = Stream.fromList [1..10]
411−-- >>> Stream.fold Fold.toList $ fmap getSum $ Stream.catRights $ Stream.parseIterate (\b -> Parser.takeBetween 0 2 (Fold.sconcat b)) (Sum 0) $ fmap Sum s
412−-- [3,10,21,36,55,55]
413−--
414−-- This is the streaming equivalent of monad like sequenced application of
415−-- parsers where next parser is dependent on the previous parser.
416−--
417−-- /Pre-release/
418−--
419−{-# INLINE parseIterate #-}
420−parseIterate
421− :: Monad m
422− => (b -> Parser a m b)
423− -> b
424− -> Stream m a
425− -> Stream m (Either ParseError b)
426−parseIterate f i m = fromStreamD $
427− D.parseIterateD f i (toStreamD m)
428−
429−------------------------------------------------------------------------------
430−-- Chunking
431−------------------------------------------------------------------------------
432−
433−-- | @chunksOf n stream@ groups the elements in the input stream into arrays of
434−-- @n@ elements each.
435−--
436−-- Same as the following but may be more efficient:
437−--
438−-- >>> chunksOf n = Stream.foldMany (Array.writeN n)
439−--
440−-- /Pre-release/
441−{-# INLINE chunksOf #-}
442−chunksOf :: (MonadIO m, Unbox a)
443− => Int -> Stream m a -> Stream m (Array a)
444−chunksOf n = fromStreamD . Array.chunksOf n . toStreamD
core/src/Streamly/Internal/Data/Stream/StreamD/Eliminate.hs+1−1
@@ -820,7 +820,7 @@ isSuffixOfUnbox suffix stream =
820820-- stripSuffix on that especially if the elements have a Storable or Prim
821821-- instance.
822822--
823−-- See also "Streamly.Internal.Data.Stream.Reduce.dropSuffix".
823+-- See also "Streamly.Internal.Data.Stream.StreamD.Reduce.dropSuffix".
824824--
825825-- Space: @O(n)@, buffers the entire input stream as well as the suffix
826826--
core/src/Streamly/Internal/Data/Stream/StreamDK.hsdeleted−52
@@ -1,52 +0,0 @@
1−-- |
2−-- Module : Streamly.Internal.Data.Stream.StreamDK
3−-- Copyright : (c) 2019 Composewell Technologies
4−-- License : BSD-3-Clause
5−-- Maintainer : streamly@composewell.com
6−-- Stability : experimental
7−-- Portability : GHC
8−--
9−--
10−-- This module has the following problems due to rewrite rules:
11−--
12−-- * Rewrite rules lead to optimization problems, blocking fusion in some
13−-- cases, specifically when combining multiple operations e.g. (filter . drop).
14−-- * Rewrite rules lead to problems when calling a function recursively. For
15−-- example, the StreamD version of foldBreak cannot be used recursively when
16−-- wrapped in rewrite rules because each recursive call adds a roundtrip
17−-- conversion from D to K and back to D. We can use the StreamK versions of
18−-- these though because the rewrite rule gets eliminated in that case.
19−-- * If we have a unified module, we need two different versions of several
20−-- operations e.g. appendK and appendD, both are useful in different cases.
21−--
22−module Streamly.Internal.Data.Stream.StreamDK
23− ( module Streamly.Internal.Data.Stream.Type
24− , module Streamly.Internal.Data.Stream.Bottom
25− , module Streamly.Internal.Data.Stream.Eliminate
26− , module Streamly.Internal.Data.Stream.Exception
27− , module Streamly.Internal.Data.Stream.Expand
28− , module Streamly.Internal.Data.Stream.Generate
29− , module Streamly.Internal.Data.Stream.Lift
30− , module Streamly.Internal.Data.Stream.Reduce
31− , module Streamly.Internal.Data.Stream.Transform
32− , module Streamly.Internal.Data.Stream.Cross
33− , module Streamly.Internal.Data.Stream.Zip
34−
35− -- modules having dependencies on libraries other than base
36− , module Streamly.Internal.Data.Stream.Transformer
37− )
38−where
39−
40−import Streamly.Internal.Data.Stream.Bottom
41−import Streamly.Internal.Data.Stream.Cross
42−import Streamly.Internal.Data.Stream.Eliminate
43−import Streamly.Internal.Data.Stream.Exception
44−import Streamly.Internal.Data.Stream.Expand
45−import Streamly.Internal.Data.Stream.Generate
46−import Streamly.Internal.Data.Stream.Lift
47−import Streamly.Internal.Data.Stream.Reduce
48−import Streamly.Internal.Data.Stream.Transform
49−import Streamly.Internal.Data.Stream.Type
50−import Streamly.Internal.Data.Stream.Zip
51−
52−import Streamly.Internal.Data.Stream.Transformer
core/src/Streamly/Internal/Data/Stream/Transform.hsdeleted−1056
@@ -1,1056 +0,0 @@
1−-- |
2−-- Module : Streamly.Internal.Data.Stream.Transform
3−-- Copyright : (c) 2017 Composewell Technologies
4−-- License : BSD-3-Clause
5−-- Maintainer : streamly@composewell.com
6−-- Stability : experimental
7−-- Portability : GHC
8−
9−module Streamly.Internal.Data.Stream.Transform
10− (
11− -- * Piping
12− -- | Pass through a 'Pipe'.
13− transform
14−
15− -- * Folding
16− , foldrS
17−
18− -- * Mapping
19− -- | Stateless one-to-one maps.
20− , sequence
21− , mapM
22−
23− -- * Mapping Side Effects (Observation)
24− -- | See also the intersperse*_ combinators.
25− , trace
26− , trace_
27− , tap
28−
29− -- * Scanning
30− , scan
31− , scanMany
32− , postscan
33− , smapM
34− , scanlMAfter'
35−
36− -- * Filtering
37− -- | Produce a subset of the stream using criteria based on the values of
38− -- the elements. We can use a concatMap and scan for filtering but these
39− -- combinators are more efficient and convenient.
40−
41− -- mapMaybeM is a general filtering combinator as we can map the stream to
42− -- Just/Nothing using any stateful fold and then use this to filter out.
43− , mapMaybeM
44− , mapMaybe
45− , catMaybes
46− , scanMaybe
47−
48− , with
49− , deleteBy
50− , filter
51− , filterM
52−
53− -- Stateful/scanning filters
54− , uniq
55− , uniqBy
56− , prune
57− , repeated
58−
59− -- * Trimming
60− -- | Produce a subset of the stream trimmed at ends.
61−
62− , take
63− , takeWhile
64− , takeWhileM
65− , takeWhileLast
66− , takeWhileAround
67− , drop
68− , dropLast
69− , dropWhile
70− , dropWhileM
71− , dropWhileLast
72− , dropWhileAround
73−
74− -- * Position Indexing
75− , indexed
76− , indexedR
77−
78− -- * Time Indexing
79− , timestamped
80− , timestampWith
81− , timeIndexed
82− , timeIndexWith
83−
84− -- * Searching
85− , findIndices -- XXX indicesBy
86− , elemIndices -- XXX indicesOf
87−
88− -- * Rolling map
89− -- | Map using the previous element.
90− , rollingMapM
91− , rollingMap
92− , rollingMap2
93−
94− -- Merge
95−
96− -- * Inserting Elements
97− -- | Produce a superset of the stream. This is the opposite of
98− -- filtering/sampling. We can always use concatMap and scan for inserting
99− -- but these combinators are more efficient and convenient.
100−
101− -- Element agnostic (Opposite of sampling)
102− , intersperse
103− , intersperseM -- XXX naming
104− , intersperseMWith
105−
106− , intersperseMSuffix
107− , intersperseMSuffixWith
108−
109− -- , interspersePrefix
110− -- , interspersePrefixBySpan
111−
112− -- * Inserting Side Effects/Time
113− , intersperseM_ -- XXX naming
114− , delay
115− , intersperseMSuffix_
116− , delayPost
117− , intersperseMPrefix_
118− , delayPre
119−
120− -- * Element Aware Insertion
121− -- | Opposite of filtering
122− , insertBy
123− -- , intersperseByBefore
124− -- , intersperseByAfter
125−
126− -- Fold and Unfold, Buffering
127−
128− -- * Reordering
129− , reverse
130− , reverse'
131− , reassembleBy
132−
133− -- * Either Streams
134− -- Move these to Streamly.Data.Either.Stream?
135− , catLefts
136− , catRights
137− , catEithers
138− )
139−where
140−
141−#include "inline.hs"
142−
143−import Control.Concurrent (threadDelay)
144−import Control.Monad (void)
145−import Control.Monad.IO.Class (MonadIO (liftIO))
146−import Data.Either (fromLeft, isLeft, isRight, fromRight)
147−import Data.Maybe (isJust, fromJust)
148−
149−import Streamly.Internal.Data.Fold.Type (Fold)
150−import Streamly.Internal.Data.Pipe (Pipe)
151−import Streamly.Internal.Data.Time.Units (AbsTime, RelTime64)
152−
153−import qualified Streamly.Internal.Data.Fold as FL
154−-- import qualified Streamly.Internal.Data.Fold.Window as Window
155−import qualified Streamly.Internal.Data.Stream.StreamD.Transform as D
156−import qualified Streamly.Internal.Data.Stream.StreamD.Type as D
157−import qualified Streamly.Internal.Data.Stream.StreamK.Type as K
158−
159−
160−import Streamly.Internal.Data.Stream.Bottom
161−import Streamly.Internal.Data.Stream.Type
162−
163−import Prelude hiding
164− ( filter, drop, dropWhile, take, takeWhile, foldr, map, mapM, sequence
165− , reverse, foldr1 , repeat, scanl, scanl1, zipWith)
166−
167−--
168−-- $setup
169−-- >>> :m
170−-- >>> import Control.Concurrent (threadDelay)
171−-- >>> import Control.Monad (void)
172−-- >>> import Control.Monad.IO.Class (MonadIO (liftIO))
173−-- >>> import Data.Either (fromLeft, fromRight, isLeft, isRight, either)
174−-- >>> import Data.Function ((&))
175−-- >>> import Data.Maybe (fromJust, isJust)
176−-- >>> import Prelude hiding (filter, drop, dropWhile, take, takeWhile, foldr, map, mapM, sequence, reverse, foldr1 , scanl, scanl1)
177−-- >>> import Streamly.Internal.Data.Stream (Stream)
178−-- >>> import qualified Streamly.Data.Fold as Fold
179−-- >>> import qualified Streamly.Data.Unfold as Unfold
180−-- >>> import qualified Streamly.Internal.Data.Fold as Fold (filtering)
181−-- >>> import qualified Streamly.Internal.Data.Fold.Window as Window
182−-- >>> import qualified Streamly.Internal.Data.Stream as Stream
183−-- >>> import System.IO (stdout, hSetBuffering, BufferMode(LineBuffering))
184−--
185−-- >>> hSetBuffering stdout LineBuffering
186−
187−-- XXX because of the use of D.cons for appending, folds and scans have
188−-- quadratic complexity when iterated over a stream. We should use StreamK for
189−-- linear performance on iteration.
190−
191−------------------------------------------------------------------------------
192−-- Piping
193−------------------------------------------------------------------------------
194−
195−-- | Use a 'Pipe' to transform a stream.
196−--
197−-- /Pre-release/
198−--
199−{-# INLINE transform #-}
200−transform :: Monad m => Pipe m a b -> Stream m a -> Stream m b
201−transform pipe xs = fromStreamD $ D.transform pipe (toStreamD xs)
202−
203−------------------------------------------------------------------------------
204−-- Transformation Folds
205−------------------------------------------------------------------------------
206−
207−-- | Right fold to a streaming monad.
208−--
209−-- > foldrS Stream.cons Stream.nil === id
210−--
211−-- 'foldrS' can be used to perform stateless stream to stream transformations
212−-- like map and filter in general. It can be coupled with a scan to perform
213−-- stateful transformations. However, note that the custom map and filter
214−-- routines can be much more efficient than this due to better stream fusion.
215−--
216−-- >>> input = Stream.fromList [1..5]
217−-- >>> Stream.fold Fold.toList $ Stream.foldrS Stream.cons Stream.nil input
218−-- [1,2,3,4,5]
219−--
220−-- Find if any element in the stream is 'True':
221−--
222−-- >>> step x xs = if odd x then Stream.fromPure True else xs
223−-- >>> input = Stream.fromList (2:4:5:undefined) :: Stream IO Int
224−-- >>> Stream.fold Fold.toList $ Stream.foldrS step (Stream.fromPure False) input
225−-- [True]
226−--
227−-- Map (+2) on odd elements and filter out the even elements:
228−--
229−-- >>> step x xs = if odd x then (x + 2) `Stream.cons` xs else xs
230−-- >>> input = Stream.fromList [1..5] :: Stream IO Int
231−-- >>> Stream.fold Fold.toList $ Stream.foldrS step Stream.nil input
232−-- [3,5,7]
233−--
234−-- /Pre-release/
235−{-# INLINE foldrS #-}
236−foldrS ::
237− (a -> Stream m b -> Stream m b)
238− -> Stream m b
239− -> Stream m a
240− -> Stream m b
241−foldrS f z xs =
242− fromStreamK
243− $ K.foldrS
244− (\y ys -> toStreamK $ f y (fromStreamK ys))
245− (toStreamK z)
246− (toStreamK xs)
247−
248−------------------------------------------------------------------------------
249−-- Transformation by Mapping
250−------------------------------------------------------------------------------
251−
252−-- |
253−-- >>> mapM f = Stream.sequence . fmap f
254−--
255−-- Apply a monadic function to each element of the stream and replace it with
256−-- the output of the resulting action.
257−--
258−-- >>> s = Stream.fromList ["a", "b", "c"]
259−-- >>> Stream.fold Fold.drain $ Stream.mapM putStr s
260−-- abc
261−--
262−{-# INLINE mapM #-}
263−mapM :: Monad m => (a -> m b) -> Stream m a -> Stream m b
264−mapM f m = fromStreamK $ D.toStreamK $ D.mapM f $ toStreamD m
265−
266−-- |
267−-- >>> sequence = Stream.mapM id
268−--
269−-- Replace the elements of a stream of monadic actions with the outputs of
270−-- those actions.
271−--
272−-- >>> s = Stream.fromList [putStr "a", putStr "b", putStrLn "c"]
273−-- >>> Stream.fold Fold.drain $ Stream.sequence s
274−-- abc
275−--
276−{-# INLINE sequence #-}
277−sequence :: Monad m => Stream m (m a) -> Stream m a
278−sequence = mapM id
279−
280−------------------------------------------------------------------------------
281−-- Mapping side effects
282−------------------------------------------------------------------------------
283−
284−-- | Tap the data flowing through a stream into a 'Fold'. For example, you may
285−-- add a tap to log the contents flowing through the stream. The fold is used
286−-- only for effects, its result is discarded.
287−--
288−-- @
289−-- Fold m a b
290−-- |
291−-- -----stream m a ---------------stream m a-----
292−--
293−-- @
294−--
295−-- >>> s = Stream.enumerateFromTo 1 2
296−-- >>> Stream.fold Fold.drain $ Stream.tap (Fold.drainMapM print) s
297−-- 1
298−-- 2
299−--
300−-- Compare with 'trace'.
301−--
302−{-# INLINE tap #-}
303−tap :: Monad m => FL.Fold m a b -> Stream m a -> Stream m a
304−tap f xs = fromStreamD $ D.tap f (toStreamD xs)
305−
306−-- | Apply a monadic function to each element flowing through the stream and
307−-- discard the results.
308−--
309−-- >>> s = Stream.enumerateFromTo 1 2
310−-- >>> Stream.fold Fold.drain $ Stream.trace print s
311−-- 1
312−-- 2
313−--
314−-- Compare with 'tap'.
315−--
316−{-# INLINE trace #-}
317−trace :: Monad m => (a -> m b) -> Stream m a -> Stream m a
318−trace f = mapM (\x -> void (f x) >> return x)
319−
320−-- | Perform a side effect before yielding each element of the stream and
321−-- discard the results.
322−--
323−-- >>> s = Stream.enumerateFromTo 1 2
324−-- >>> Stream.fold Fold.drain $ Stream.trace_ (print "got here") s
325−-- "got here"
326−-- "got here"
327−--
328−-- Same as 'intersperseMPrefix_' but always serial.
329−--
330−-- See also: 'trace'
331−--
332−-- /Pre-release/
333−{-# INLINE trace_ #-}
334−trace_ :: Monad m => m b -> Stream m a -> Stream m a
335−trace_ eff = fromStreamD . D.mapM (\x -> eff >> return x) . toStreamD
336−
337−-------------------------------------------------------------------------------
338−-- Scanning
339−-------------------------------------------------------------------------------
340−
341−-- | @scanlMAfter' accumulate initial done stream@ is like 'scanlM'' except
342−-- that it provides an additional @done@ function to be applied on the
343−-- accumulator when the stream stops. The result of @done@ is also emitted in
344−-- the stream.
345−--
346−-- This function can be used to allocate a resource in the beginning of the
347−-- scan and release it when the stream ends or to flush the internal state of
348−-- the scan at the end.
349−--
350−-- /Pre-release/
351−--
352−{-# INLINE scanlMAfter' #-}
353−scanlMAfter' ::
354− Monad m
355− => (b -> a -> m b)
356− -> m b
357− -> (b -> m b)
358− -> Stream m a
359− -> Stream m b
360−scanlMAfter' step initial done stream =
361− fromStreamD $ D.scanlMAfter' step initial done $ toStreamD stream
362−
363−------------------------------------------------------------------------------
364−-- Scanning with a Fold
365−------------------------------------------------------------------------------
366−
367−-- XXX It may be useful to have a version of scan where we can keep the
368−-- accumulator independent of the value emitted. So that we do not necessarily
369−-- have to keep a value in the accumulator which we are not using. We can pass
370−-- an extraction function that will take the accumulator and the current value
371−-- of the element and emit the next value in the stream. That will also make it
372−-- possible to modify the accumulator after using it. In fact, the step function
373−-- can return new accumulator and the value to be emitted. The signature would
374−-- be more like mapAccumL.
375−
376−-- | Strict left scan. Scan a stream using the given monadic fold.
377−--
378−-- >>> s = Stream.fromList [1..10]
379−-- >>> Stream.fold Fold.toList $ Stream.takeWhile (< 10) $ Stream.scan Fold.sum s
380−-- [0,1,3,6]
381−--
382−-- See also: 'usingStateT'
383−--
384−
385−-- EXPLANATION:
386−-- >>> scanl' step z = Stream.scan (Fold.foldl' step z)
387−--
388−-- Like 'map', 'scanl'' too is a one to one transformation,
389−-- however it adds an extra element.
390−--
391−-- >>> s = Stream.fromList [1,2,3,4]
392−-- >>> Stream.fold Fold.toList $ scanl' (+) 0 s
393−-- [0,1,3,6,10]
394−--
395−-- >>> Stream.fold Fold.toList $ scanl' (flip (:)) [] s
396−-- [[],[1],[2,1],[3,2,1],[4,3,2,1]]
397−--
398−-- The output of 'scanl'' is the initial value of the accumulator followed by
399−-- all the intermediate steps and the final result of 'foldl''.
400−--
401−-- By streaming the accumulated state after each fold step, we can share the
402−-- state across multiple stages of stream composition. Each stage can modify or
403−-- extend the state, do some processing with it and emit it for the next stage,
404−-- thus modularizing the stream processing. This can be useful in
405−-- stateful or event-driven programming.
406−--
407−-- Consider the following monolithic example, computing the sum and the product
408−-- of the elements in a stream in one go using a @foldl'@:
409−--
410−-- >>> foldl' step z = Stream.fold (Fold.foldl' step z)
411−-- >>> foldl' (\(s, p) x -> (s + x, p * x)) (0,1) s
412−-- (10,24)
413−--
414−-- Using @scanl'@ we can make it modular by computing the sum in the first
415−-- stage and passing it down to the next stage for computing the product:
416−--
417−-- >>> :{
418−-- foldl' (\(_, p) (s, x) -> (s, p * x)) (0,1)
419−-- $ scanl' (\(s, _) x -> (s + x, x)) (0,1)
420−-- $ Stream.fromList [1,2,3,4]
421−-- :}
422−-- (10,24)
423−--
424−-- IMPORTANT: 'scanl'' evaluates the accumulator to WHNF. To avoid building
425−-- lazy expressions inside the accumulator, it is recommended that a strict
426−-- data structure is used for accumulator.
427−--
428−{-# INLINE scan #-}
429−scan :: Monad m => Fold m a b -> Stream m a -> Stream m b
430−scan fld m = fromStreamD $ D.scan fld $ toStreamD m
431−
432−-- | Like 'scan' but restarts scanning afresh when the scanning fold
433−-- terminates.
434−--
435−{-# INLINE scanMany #-}
436−scanMany :: Monad m => Fold m a b -> Stream m a -> Stream m b
437−scanMany fld m = fromStreamD $ D.scanMany fld $ toStreamD m
438−
439−------------------------------------------------------------------------------
440−-- Filtering
441−------------------------------------------------------------------------------
442−
443−-- | Modify a @Stream m a -> Stream m a@ stream transformation that accepts a
444−-- predicate @(a -> b)@ to accept @((s, a) -> b)@ instead, provided a
445−-- transformation @Stream m a -> Stream m (s, a)@. Convenient to filter with
446−-- index or time.
447−--
448−-- >>> filterWithIndex = Stream.with Stream.indexed Stream.filter
449−--
450−-- /Pre-release/
451−{-# INLINE with #-}
452−with :: Monad m =>
453− (Stream m a -> Stream m (s, a))
454− -> (((s, a) -> b) -> Stream m (s, a) -> Stream m (s, a))
455− -> (((s, a) -> b) -> Stream m a -> Stream m a)
456−with f comb g = fmap snd . comb g . f
457−
458−-- | Include only those elements that pass a predicate.
459−--
460−-- >>> filter p = Stream.filterM (return . p)
461−-- >>> filter p = Stream.mapMaybe (\x -> if p x then Just x else Nothing)
462−-- >>> filter p = Stream.scanMaybe (Fold.filtering p)
463−--
464−{-# INLINE filter #-}
465−filter :: Monad m => (a -> Bool) -> Stream m a -> Stream m a
466−-- filter p = scanMaybe (FL.filtering p)
467−filter p m = fromStreamD $ D.filter p $ toStreamD m
468−
469−-- | Same as 'filter' but with a monadic predicate.
470−--
471−-- >>> f p x = p x >>= \r -> return $ if r then Just x else Nothing
472−-- >>> filterM p = Stream.mapMaybeM (f p)
473−--
474−{-# INLINE filterM #-}
475−filterM :: Monad m => (a -> m Bool) -> Stream m a -> Stream m a
476−filterM p m = fromStreamD $ D.filterM p $ toStreamD m
477−
478−-- | Drop repeated elements that are adjacent to each other using the supplied
479−-- comparison function.
480−--
481−-- >>> uniq = Stream.uniqBy (==)
482−--
483−-- To strip duplicate path separators:
484−--
485−-- >>> input = Stream.fromList "//a//b"
486−-- >>> f x y = x == '/' && y == '/'
487−-- >>> Stream.fold Fold.toList $ Stream.uniqBy f input
488−-- "/a/b"
489−--
490−-- Space: @O(1)@
491−--
492−-- /Pre-release/
493−--
494−{-# INLINE uniqBy #-}
495−uniqBy :: Monad m =>
496− (a -> a -> Bool) -> Stream m a -> Stream m a
497−-- uniqBy eq = scanMaybe (FL.uniqBy eq)
498−uniqBy eq = catMaybes . rollingMap f
499−
500− where
501−
502− f pre curr =
503− case pre of
504− Nothing -> Just curr
505− Just x -> if x `eq` curr then Nothing else Just curr
506−
507−-- | Drop repeated elements that are adjacent to each other.
508−--
509−-- >>> uniq = Stream.uniqBy (==)
510−--
511−{-# INLINE uniq #-}
512−uniq :: (Eq a, Monad m) => Stream m a -> Stream m a
513−-- uniq = scanMaybe FL.uniq
514−uniq = fromStreamD . D.uniq . toStreamD
515−
516−-- | Strip all leading and trailing occurrences of an element passing a
517−-- predicate and make all other consecutive occurrences uniq.
518−--
519−-- >> prune p = Stream.dropWhileAround p $ Stream.uniqBy (x y -> p x && p y)
520−--
521−-- @
522−-- > Stream.prune isSpace (Stream.fromList " hello world! ")
523−-- "hello world!"
524−--
525−-- @
526−--
527−-- Space: @O(1)@
528−--
529−-- /Unimplemented/
530−{-# INLINE prune #-}
531−prune ::
532− -- (Monad m, Eq a) =>
533− (a -> Bool) -> Stream m a -> Stream m a
534−prune = error "Not implemented yet!"
535−
536−-- Possible implementation:
537−-- @repeated =
538−-- Stream.catMaybes . Stream.parseMany (Parser.groupBy (==) Fold.repeated)@
539−--
540−-- 'Fold.repeated' should return 'Just' when repeated, and 'Nothing' for a
541−-- single element.
542−
543−-- | Emit only repeated elements, once.
544−--
545−-- /Unimplemented/
546−repeated :: -- (Monad m, Eq a) =>
547− Stream m a -> Stream m a
548−repeated = undefined
549−
550−-- | Deletes the first occurrence of the element in the stream that satisfies
551−-- the given equality predicate.
552−--
553−-- >>> input = Stream.fromList [1,3,3,5]
554−-- >>> Stream.fold Fold.toList $ Stream.deleteBy (==) 3 input
555−-- [1,3,5]
556−--
557−{-# INLINE deleteBy #-}
558−deleteBy :: Monad m => (a -> a -> Bool) -> a -> Stream m a -> Stream m a
559−-- deleteBy cmp x = scanMaybe (FL.deleteBy cmp x)
560−deleteBy cmp x m = fromStreamD $ D.deleteBy cmp x (toStreamD m)
561−
562−------------------------------------------------------------------------------
563−-- Trimming
564−------------------------------------------------------------------------------
565−
566−-- | Same as 'takeWhile' but with a monadic predicate.
567−--
568−{-# INLINE takeWhileM #-}
569−takeWhileM :: Monad m => (a -> m Bool) -> Stream m a -> Stream m a
570−-- takeWhileM p = scanMaybe (FL.takingEndByM_ (\x -> not <$> p x))
571−takeWhileM p m = fromStreamD $ D.takeWhileM p $ toStreamD m
572−
573−-- | Take all consecutive elements at the end of the stream for which the
574−-- predicate is true.
575−--
576−-- O(n) space, where n is the number elements taken.
577−--
578−-- /Unimplemented/
579−{-# INLINE takeWhileLast #-}
580−takeWhileLast :: -- Monad m =>
581− (a -> Bool) -> Stream m a -> Stream m a
582−takeWhileLast = undefined -- fromStreamD $ D.takeWhileLast n $ toStreamD m
583−
584−-- | Like 'takeWhile' and 'takeWhileLast' combined.
585−--
586−-- O(n) space, where n is the number elements taken from the end.
587−--
588−-- /Unimplemented/
589−{-# INLINE takeWhileAround #-}
590−takeWhileAround :: -- Monad m =>
591− (a -> Bool) -> Stream m a -> Stream m a
592−takeWhileAround = undefined -- fromStreamD $ D.takeWhileAround n $ toStreamD m
593−
594−-- | Drop elements in the stream as long as the predicate succeeds and then
595−-- take the rest of the stream.
596−--
597−{-# INLINE dropWhile #-}
598−dropWhile :: Monad m => (a -> Bool) -> Stream m a -> Stream m a
599−-- dropWhile p = scanMaybe (FL.droppingWhile p)
600−dropWhile p m = fromStreamD $ D.dropWhile p $ toStreamD m
601−
602−-- | Same as 'dropWhile' but with a monadic predicate.
603−--
604−{-# INLINE dropWhileM #-}
605−dropWhileM :: Monad m => (a -> m Bool) -> Stream m a -> Stream m a
606−-- dropWhileM p = scanMaybe (FL.droppingWhileM p)
607−dropWhileM p m = fromStreamD $ D.dropWhileM p $ toStreamD m
608−
609−-- | Drop @n@ elements at the end of the stream.
610−--
611−-- O(n) space, where n is the number elements dropped.
612−--
613−-- /Unimplemented/
614−{-# INLINE dropLast #-}
615−dropLast :: -- Monad m =>
616− Int -> Stream m a -> Stream m a
617−dropLast = undefined -- fromStreamD $ D.dropLast n $ toStreamD m
618−
619−-- | Drop all consecutive elements at the end of the stream for which the
620−-- predicate is true.
621−--
622−-- O(n) space, where n is the number elements dropped.
623−--
624−-- /Unimplemented/
625−{-# INLINE dropWhileLast #-}
626−dropWhileLast :: -- Monad m =>
627− (a -> Bool) -> Stream m a -> Stream m a
628−dropWhileLast = undefined -- fromStreamD $ D.dropWhileLast n $ toStreamD m
629−
630−-- | Like 'dropWhile' and 'dropWhileLast' combined.
631−--
632−-- O(n) space, where n is the number elements dropped from the end.
633−--
634−-- /Unimplemented/
635−{-# INLINE dropWhileAround #-}
636−dropWhileAround :: -- Monad m =>
637− (a -> Bool) -> Stream m a -> Stream m a
638−dropWhileAround = undefined -- fromStreamD $ D.dropWhileAround n $ toStreamD m
639−
640−------------------------------------------------------------------------------
641−-- Inserting Elements
642−------------------------------------------------------------------------------
643−
644−-- | @insertBy cmp elem stream@ inserts @elem@ before the first element in
645−-- @stream@ that is less than @elem@ when compared using @cmp@.
646−--
647−-- >>> insertBy cmp x = Stream.mergeBy cmp (Stream.fromPure x)
648−--
649−-- >>> input = Stream.fromList [1,3,5]
650−-- >>> Stream.fold Fold.toList $ Stream.insertBy compare 2 input
651−-- [1,2,3,5]
652−--
653−{-# INLINE insertBy #-}
654−insertBy ::Monad m => (a -> a -> Ordering) -> a -> Stream m a -> Stream m a
655−insertBy cmp x m = fromStreamD $ D.insertBy cmp x (toStreamD m)
656−
657−-- | Insert a pure value between successive elements of a stream.
658−--
659−-- >>> input = Stream.fromList "hello"
660−-- >>> Stream.fold Fold.toList $ Stream.intersperse ',' input
661−-- "h,e,l,l,o"
662−--
663−{-# INLINE intersperse #-}
664−intersperse :: Monad m => a -> Stream m a -> Stream m a
665−intersperse a = fromStreamD . D.intersperse a . toStreamD
666−
667−-- | Insert a side effect before consuming an element of a stream except the
668−-- first one.
669−--
670−-- >>> input = Stream.fromList "hello"
671−-- >>> Stream.fold Fold.drain $ Stream.trace putChar $ Stream.intersperseM_ (putChar '.') input
672−-- h.e.l.l.o
673−--
674−-- /Pre-release/
675−{-# INLINE intersperseM_ #-}
676−intersperseM_ :: Monad m => m b -> Stream m a -> Stream m a
677−intersperseM_ m = fromStreamD . D.intersperseM_ m . toStreamD
678−
679−-- | Intersperse a monadic action into the input stream after every @n@
680−-- elements.
681−--
682−-- >> input = Stream.fromList "hello"
683−-- >> Stream.fold Fold.toList $ Stream.intersperseMWith 2 (return ',') input
684−-- "he,ll,o"
685−--
686−-- /Unimplemented/
687−{-# INLINE intersperseMWith #-}
688−intersperseMWith :: -- Monad m =>
689− Int -> m a -> Stream m a -> Stream m a
690−intersperseMWith _n _f _xs = undefined
691−
692−-- | Insert an effect and its output after consuming an element of a stream.
693−--
694−-- >>> input = Stream.fromList "hello"
695−-- >>> Stream.fold Fold.toList $ Stream.trace putChar $ Stream.intersperseMSuffix (putChar '.' >> return ',') input
696−-- h.,e.,l.,l.,o.,"h,e,l,l,o,"
697−--
698−-- /Pre-release/
699−{-# INLINE intersperseMSuffix #-}
700−intersperseMSuffix :: Monad m => m a -> Stream m a -> Stream m a
701−intersperseMSuffix m = fromStreamD . D.intersperseMSuffix m . toStreamD
702−
703−-- | Insert a side effect after consuming an element of a stream.
704−--
705−-- >>> input = Stream.fromList "hello"
706−-- >>> Stream.fold Fold.toList $ Stream.intersperseMSuffix_ (threadDelay 1000000) input
707−-- "hello"
708−--
709−-- /Pre-release/
710−--
711−{-# INLINE intersperseMSuffix_ #-}
712−intersperseMSuffix_ :: Monad m => m b -> Stream m a -> Stream m a
713−intersperseMSuffix_ m = fromStreamD . D.intersperseMSuffix_ m . toStreamD
714−
715−-- XXX Use an offset argument, like tapOffsetEvery
716−
717−-- | Like 'intersperseMSuffix' but intersperses an effectful action into the
718−-- input stream after every @n@ elements and after the last element.
719−--
720−-- >>> input = Stream.fromList "hello"
721−-- >>> Stream.fold Fold.toList $ Stream.intersperseMSuffixWith 2 (return ',') input
722−-- "he,ll,o,"
723−--
724−-- /Pre-release/
725−--
726−{-# INLINE intersperseMSuffixWith #-}
727−intersperseMSuffixWith :: Monad m
728− => Int -> m a -> Stream m a -> Stream m a
729−intersperseMSuffixWith n eff =
730− fromStreamD . D.intersperseMSuffixWith n eff . toStreamD
731−
732−-- | Insert a side effect before consuming an element of a stream.
733−--
734−-- Definition:
735−--
736−-- >>> intersperseMPrefix_ m = Stream.mapM (\x -> void m >> return x)
737−--
738−-- >>> input = Stream.fromList "hello"
739−-- >>> Stream.fold Fold.toList $ Stream.trace putChar $ Stream.intersperseMPrefix_ (putChar '.' >> return ',') input
740−-- .h.e.l.l.o"hello"
741−--
742−-- Same as 'trace_'.
743−--
744−-- /Pre-release/
745−--
746−{-# INLINE intersperseMPrefix_ #-}
747−intersperseMPrefix_ :: Monad m => m b -> Stream m a -> Stream m a
748−intersperseMPrefix_ m = mapM (\x -> void m >> return x)
749−
750−------------------------------------------------------------------------------
751−-- Inserting Time
752−------------------------------------------------------------------------------
753−
754−-- XXX This should be in Prelude, should we export this as a helper function?
755−
756−-- | Block the current thread for specified number of seconds.
757−{-# INLINE sleep #-}
758−sleep :: MonadIO m => Double -> m ()
759−sleep n = liftIO $ threadDelay $ round $ n * 1000000
760−
761−-- | Introduce a delay of specified seconds between elements of the stream.
762−--
763−-- Definition:
764−--
765−-- >>> sleep n = liftIO $ threadDelay $ round $ n * 1000000
766−-- >>> delay = Stream.intersperseM_ . sleep
767−--
768−-- Example:
769−--
770−-- >>> input = Stream.enumerateFromTo 1 3
771−-- >>> Stream.fold (Fold.drainMapM print) $ Stream.delay 1 input
772−-- 1
773−-- 2
774−-- 3
775−--
776−{-# INLINE delay #-}
777−delay :: MonadIO m => Double -> Stream m a -> Stream m a
778−delay = intersperseM_ . sleep
779−
780−-- | Introduce a delay of specified seconds after consuming an element of a
781−-- stream.
782−--
783−-- Definition:
784−--
785−-- >>> sleep n = liftIO $ threadDelay $ round $ n * 1000000
786−-- >>> delayPost = Stream.intersperseMSuffix_ . sleep
787−--
788−-- Example:
789−--
790−-- >>> input = Stream.enumerateFromTo 1 3
791−-- >>> Stream.fold (Fold.drainMapM print) $ Stream.delayPost 1 input
792−-- 1
793−-- 2
794−-- 3
795−--
796−-- /Pre-release/
797−--
798−{-# INLINE delayPost #-}
799−delayPost :: MonadIO m => Double -> Stream m a -> Stream m a
800−delayPost n = intersperseMSuffix_ $ liftIO $ threadDelay $ round $ n * 1000000
801−
802−-- | Introduce a delay of specified seconds before consuming an element of a
803−-- stream.
804−--
805−-- Definition:
806−--
807−-- >>> sleep n = liftIO $ threadDelay $ round $ n * 1000000
808−-- >>> delayPre = Stream.intersperseMPrefix_. sleep
809−--
810−-- Example:
811−--
812−-- >>> input = Stream.enumerateFromTo 1 3
813−-- >>> Stream.fold (Fold.drainMapM print) $ Stream.delayPre 1 input
814−-- 1
815−-- 2
816−-- 3
817−--
818−-- /Pre-release/
819−--
820−{-# INLINE delayPre #-}
821−delayPre :: MonadIO m => Double -> Stream m a -> Stream m a
822−delayPre = intersperseMPrefix_. sleep
823−
824−------------------------------------------------------------------------------
825−-- Reorder in sequence
826−------------------------------------------------------------------------------
827−
828−-- | Buffer until the next element in sequence arrives. The function argument
829−-- determines the difference in sequence numbers. This could be useful in
830−-- implementing sequenced streams, for example, TCP reassembly.
831−--
832−-- /Unimplemented/
833−--
834−{-# INLINE reassembleBy #-}
835−reassembleBy
836− :: -- Monad m =>
837− Fold m a b
838− -> (a -> a -> Int)
839− -> Stream m a
840− -> Stream m b
841−reassembleBy = undefined
842−
843−------------------------------------------------------------------------------
844−-- Position Indexing
845−------------------------------------------------------------------------------
846−
847−-- |
848−-- >>> f = Fold.foldl' (\(i, _) x -> (i + 1, x)) (-1,undefined)
849−-- >>> indexed = Stream.postscan f
850−-- >>> indexed = Stream.zipWith (,) (Stream.enumerateFrom 0)
851−-- >>> indexedR n = fmap (\(i, a) -> (n - i, a)) . indexed
852−--
853−-- Pair each element in a stream with its index, starting from index 0.
854−--
855−-- >>> Stream.fold Fold.toList $ Stream.indexed $ Stream.fromList "hello"
856−-- [(0,'h'),(1,'e'),(2,'l'),(3,'l'),(4,'o')]
857−--
858−{-# INLINE indexed #-}
859−indexed :: Monad m => Stream m a -> Stream m (Int, a)
860−-- indexed = scanMaybe FL.indexing
861−indexed = fromStreamD . D.indexed . toStreamD
862−
863−-- |
864−-- >>> f n = Fold.foldl' (\(i, _) x -> (i - 1, x)) (n + 1,undefined)
865−-- >>> indexedR n = Stream.postscan (f n)
866−--
867−-- >>> s n = Stream.enumerateFromThen n (n - 1)
868−-- >>> indexedR n = Stream.zipWith (,) (s n)
869−--
870−-- Pair each element in a stream with its index, starting from the
871−-- given index @n@ and counting down.
872−--
873−-- >>> Stream.fold Fold.toList $ Stream.indexedR 10 $ Stream.fromList "hello"
874−-- [(10,'h'),(9,'e'),(8,'l'),(7,'l'),(6,'o')]
875−--
876−{-# INLINE indexedR #-}
877−indexedR :: Monad m => Int -> Stream m a -> Stream m (Int, a)
878−-- indexedR n = scanMaybe (FL.indexingRev n)
879−indexedR n = fromStreamD . D.indexedR n . toStreamD
880−
881−-------------------------------------------------------------------------------
882−-- Time Indexing
883−-------------------------------------------------------------------------------
884−
885−-- Note: The timestamp stream must be the second stream in the zip so that the
886−-- timestamp is generated after generating the stream element and not before.
887−-- If we do not do that then the following example will generate the same
888−-- timestamp for first two elements:
889−--
890−-- Stream.fold Fold.toList $ Stream.timestamped $ Stream.delay $ Stream.enumerateFromTo 1 3
891−--
892−-- | Pair each element in a stream with an absolute timestamp, using a clock of
893−-- specified granularity. The timestamp is generated just before the element
894−-- is consumed.
895−--
896−-- >>> Stream.fold Fold.toList $ Stream.timestampWith 0.01 $ Stream.delay 1 $ Stream.enumerateFromTo 1 3
897−-- [(AbsTime (TimeSpec {sec = ..., nsec = ...}),1),(AbsTime (TimeSpec {sec = ..., nsec = ...}),2),(AbsTime (TimeSpec {sec = ..., nsec = ...}),3)]
898−--
899−-- /Pre-release/
900−--
901−{-# INLINE timestampWith #-}
902−timestampWith :: (MonadIO m)
903− => Double -> Stream m a -> Stream m (AbsTime, a)
904−timestampWith g stream = zipWith (flip (,)) stream (absTimesWith g)
905−
906−-- TBD: check performance vs a custom implementation without using zipWith.
907−--
908−-- /Pre-release/
909−--
910−{-# INLINE timestamped #-}
911−timestamped :: (MonadIO m)
912− => Stream m a -> Stream m (AbsTime, a)
913−timestamped = timestampWith 0.01
914−
915−-- | Pair each element in a stream with relative times starting from 0, using a
916−-- clock with the specified granularity. The time is measured just before the
917−-- element is consumed.
918−--
919−-- >>> Stream.fold Fold.toList $ Stream.timeIndexWith 0.01 $ Stream.delay 1 $ Stream.enumerateFromTo 1 3
920−-- [(RelTime64 (NanoSecond64 ...),1),(RelTime64 (NanoSecond64 ...),2),(RelTime64 (NanoSecond64 ...),3)]
921−--
922−-- /Pre-release/Monad
923−--
924−{-# INLINE timeIndexWith #-}
925−timeIndexWith :: (MonadIO m)
926− => Double -> Stream m a -> Stream m (RelTime64, a)
927−timeIndexWith g stream = zipWith (flip (,)) stream (relTimesWith g)
928−
929−-- | Pair each element in a stream with relative times starting from 0, using a
930−-- 10 ms granularity clock. The time is measured just before the element is
931−-- consumed.
932−--
933−-- >>> Stream.fold Fold.toList $ Stream.timeIndexed $ Stream.delay 1 $ Stream.enumerateFromTo 1 3
934−-- [(RelTime64 (NanoSecond64 ...),1),(RelTime64 (NanoSecond64 ...),2),(RelTime64 (NanoSecond64 ...),3)]
935−--
936−-- /Pre-release/
937−--
938−{-# INLINE timeIndexed #-}
939−timeIndexed :: (MonadIO m)
940− => Stream m a -> Stream m (RelTime64, a)
941−timeIndexed = timeIndexWith 0.01
942−
943−------------------------------------------------------------------------------
944−-- Searching
945−------------------------------------------------------------------------------
946−
947−-- | Find all the indices where the value of the element in the stream is equal
948−-- to the given value.
949−--
950−-- >>> elemIndices a = Stream.findIndices (== a)
951−--
952−{-# INLINE elemIndices #-}
953−elemIndices :: (Monad m, Eq a) => a -> Stream m a -> Stream m Int
954−elemIndices a = findIndices (== a)
955−
956−------------------------------------------------------------------------------
957−-- Rolling map
958−------------------------------------------------------------------------------
959−
960−-- XXX this is not a one-to-one map so calling it map may not be right.
961−-- We can perhaps call it zipWithTail or rollWith.
962−
963−-- | Apply a function on every two successive elements of a stream. The first
964−-- argument of the map function is the previous element and the second argument
965−-- is the current element. When the current element is the first element, the
966−-- previous element is 'Nothing'.
967−--
968−-- /Pre-release/
969−--
970−{-# INLINE rollingMap #-}
971−rollingMap :: Monad m => (Maybe a -> a -> b) -> Stream m a -> Stream m b
972−-- rollingMap f = scanMaybe (FL.slide2 $ Window.rollingMap f)
973−rollingMap f m = fromStreamD $ D.rollingMap f $ toStreamD m
974−
975−-- | Like 'rollingMap' but with an effectful map function.
976−--
977−-- /Pre-release/
978−--
979−{-# INLINE rollingMapM #-}
980−rollingMapM :: Monad m => (Maybe a -> a -> m b) -> Stream m a -> Stream m b
981−-- rollingMapM f = scanMaybe (FL.slide2 $ Window.rollingMapM f)
982−rollingMapM f m = fromStreamD $ D.rollingMapM f $ toStreamD m
983−
984−-- | Like 'rollingMap' but requires at least two elements in the stream,
985−-- returns an empty stream otherwise.
986−--
987−-- This is the stream equivalent of the list idiom @zipWith f xs (tail xs)@.
988−--
989−-- /Pre-release/
990−--
991−{-# INLINE rollingMap2 #-}
992−rollingMap2 :: Monad m => (a -> a -> b) -> Stream m a -> Stream m b
993−rollingMap2 f m = fromStreamD $ D.rollingMap2 f $ toStreamD m
994−
995−------------------------------------------------------------------------------
996−-- Maybe Streams
997−------------------------------------------------------------------------------
998−
999−-- | Map a 'Maybe' returning function to a stream, filter out the 'Nothing'
1000−-- elements, and return a stream of values extracted from 'Just'.
1001−--
1002−-- Equivalent to:
1003−--
1004−-- >>> mapMaybe f = Stream.catMaybes . fmap f
1005−--
1006−{-# INLINE mapMaybe #-}
1007−mapMaybe :: Monad m => (a -> Maybe b) -> Stream m a -> Stream m b
1008−mapMaybe f m = fromStreamD $ D.mapMaybe f $ toStreamD m
1009−
1010−-- | Like 'mapMaybe' but maps a monadic function.
1011−--
1012−-- Equivalent to:
1013−--
1014−-- >>> mapMaybeM f = Stream.catMaybes . Stream.mapM f
1015−--
1016−-- >>> mapM f = Stream.mapMaybeM (\x -> Just <$> f x)
1017−--
1018−{-# INLINE_EARLY mapMaybeM #-}
1019−mapMaybeM :: Monad m
1020− => (a -> m (Maybe b)) -> Stream m a -> Stream m b
1021−mapMaybeM f = fmap fromJust . filter isJust . mapM f
1022−
1023−------------------------------------------------------------------------------
1024−-- Either streams
1025−------------------------------------------------------------------------------
1026−
1027−-- | Discard 'Right's and unwrap 'Left's in an 'Either' stream.
1028−--
1029−-- >>> catLefts = fmap (fromLeft undefined) . Stream.filter isLeft
1030−--
1031−-- /Pre-release/
1032−--
1033−{-# INLINE catLefts #-}
1034−catLefts :: Monad m => Stream m (Either a b) -> Stream m a
1035−catLefts = fmap (fromLeft undefined) . filter isLeft
1036−
1037−-- | Discard 'Left's and unwrap 'Right's in an 'Either' stream.
1038−--
1039−-- >>> catRights = fmap (fromRight undefined) . Stream.filter isRight
1040−--
1041−-- /Pre-release/
1042−--
1043−{-# INLINE catRights #-}
1044−catRights :: Monad m => Stream m (Either a b) -> Stream m b
1045−catRights = fmap (fromRight undefined) . filter isRight
1046−
1047−-- | Remove the either wrapper and flatten both lefts and as well as rights in
1048−-- the output stream.
1049−--
1050−-- >>> catEithers = fmap (either id id)
1051−--
1052−-- /Pre-release/
1053−--
1054−{-# INLINE catEithers #-}
1055−catEithers :: Monad m => Stream m (Either a a) -> Stream m a
1056−catEithers = fmap (either id id)
core/src/Streamly/Internal/Data/Stream/Transformer.hsdeleted−135
@@ -1,135 +0,0 @@
1−-- |
2−-- Module : Streamly.Internal.Data.Stream.Transformer
3−-- Copyright : (c) 2019 Composewell Technologies
4−-- License : BSD-3-Clause
5−-- Maintainer : streamly@composewell.com
6−-- Stability : experimental
7−-- Portability : GHC
8−
9−module Streamly.Internal.Data.Stream.Transformer
10− (
11− foldlT
12− , foldrT
13−
14− , liftInner
15− , usingReaderT
16− , runReaderT
17− , evalStateT
18− , usingStateT
19− , runStateT
20− )
21−where
22−
23−import Control.Monad.Trans.Class (MonadTrans)
24−import Control.Monad.Trans.Reader (ReaderT)
25−import Control.Monad.Trans.State.Strict (StateT)
26−import Streamly.Internal.Data.Stream.Type (Stream, fromStreamD, toStreamD)
27−
28−import qualified Streamly.Internal.Data.Stream.StreamD.Transformer as D
29−
30−-- $setup
31−-- >>> :m
32−-- >>> import Control.Monad.Trans.Class (lift)
33−-- >>> import Control.Monad.Trans.Identity (runIdentityT)
34−-- >>> import qualified Streamly.Internal.Data.Stream as Stream
35−
36−-- | Lazy left fold to a transformer monad.
37−--
38−{-# INLINE foldlT #-}
39−foldlT :: (Monad m, Monad (s m), MonadTrans s)
40− => (s m b -> a -> s m b) -> s m b -> Stream m a -> s m b
41−foldlT f z s = D.foldlT f z (toStreamD s)
42−
43−-- | Right fold to a transformer monad. This is the most general right fold
44−-- function. 'foldrS' is a special case of 'foldrT', however 'foldrS'
45−-- implementation can be more efficient:
46−--
47−-- >>> foldrS = Stream.foldrT
48−--
49−-- >>> step f x xs = lift $ f x (runIdentityT xs)
50−-- >>> foldrM f z s = runIdentityT $ Stream.foldrT (step f) (lift z) s
51−--
52−-- 'foldrT' can be used to translate streamly streams to other transformer
53−-- monads e.g. to a different streaming type.
54−--
55−-- /Pre-release/
56−{-# INLINE foldrT #-}
57−foldrT :: (Monad m, Monad (s m), MonadTrans s)
58− => (a -> s m b -> s m b) -> s m b -> Stream m a -> s m b
59−foldrT f z s = D.foldrT f z (toStreamD s)
60−
61−------------------------------------------------------------------------------
62−-- Add and remove a monad transformer
63−------------------------------------------------------------------------------
64−
65−-- | Lift the inner monad @m@ of @Stream m a@ to @t m@ where @t@ is a monad
66−-- transformer.
67−--
68−{-# INLINE liftInner #-}
69−liftInner :: (Monad m, MonadTrans t, Monad (t m))
70− => Stream m a -> Stream (t m) a
71−liftInner xs = fromStreamD $ D.liftInner (toStreamD xs)
72−
73−------------------------------------------------------------------------------
74−-- Sharing read only state in a stream
75−------------------------------------------------------------------------------
76−
77−-- | Evaluate the inner monad of a stream as 'ReaderT'.
78−--
79−{-# INLINE runReaderT #-}
80−runReaderT :: Monad m => m s -> Stream (ReaderT s m) a -> Stream m a
81−runReaderT s xs = fromStreamD $ D.runReaderT s (toStreamD xs)
82−
83−-- | Run a stream transformation using a given environment.
84−--
85−-- See also: 'Serial.map'
86−--
87−-- / Internal/
88−--
89−{-# INLINE usingReaderT #-}
90−usingReaderT
91− :: Monad m
92− => m r
93− -> (Stream (ReaderT r m) a -> Stream (ReaderT r m) a)
94− -> Stream m a
95− -> Stream m a
96−usingReaderT r f xs = runReaderT r $ f $ liftInner xs
97−
98−------------------------------------------------------------------------------
99−-- Sharing read write state in a stream
100−------------------------------------------------------------------------------
101−
102−-- | Evaluate the inner monad of a stream as 'StateT'.
103−--
104−-- >>> evalStateT s = fmap snd . Stream.runStateT s
105−--
106−-- / Internal/
107−--
108−{-# INLINE evalStateT #-}
109−evalStateT :: Monad m => m s -> Stream (StateT s m) a -> Stream m a
110−-- evalStateT s = fmap snd . runStateT s
111−evalStateT s xs = fromStreamD $ D.evalStateT s (toStreamD xs)
112−
113−-- | Run a stateful (StateT) stream transformation using a given state.
114−--
115−-- >>> usingStateT s f = Stream.evalStateT s . f . Stream.liftInner
116−--
117−-- See also: 'scan'
118−--
119−-- / Internal/
120−--
121−{-# INLINE usingStateT #-}
122−usingStateT
123− :: Monad m
124− => m s
125− -> (Stream (StateT s m) a -> Stream (StateT s m) a)
126− -> Stream m a
127− -> Stream m a
128−usingStateT s f = evalStateT s . f . liftInner
129−
130−-- | Evaluate the inner monad of a stream as 'StateT' and emit the resulting
131−-- state and value pair after each step.
132−--
133−{-# INLINE runStateT #-}
134−runStateT :: Monad m => m s -> Stream (StateT s m) a -> Stream m (s, a)
135−runStateT s xs = fromStreamD $ D.runStateT s (toStreamD xs)
core/src/Streamly/Internal/Data/Stream/Type.hsdeleted−491
@@ -1,491 +0,0 @@
1−{-# LANGUAGE UndecidableInstances #-}
2−
3−-- |
4−-- Module : Streamly.Internal.Data.Stream.Type
5−-- Copyright : (c) 2017 Composewell Technologies
6−-- License : BSD-3-Clause
7−-- Maintainer : streamly@composewell.com
8−-- Stability : experimental
9−-- Portability : GHC
10−--
11−module Streamly.Internal.Data.Stream.Type
12− (
13− -- * Stream Type
14− Stream -- XXX To be removed
15− , StreamK
16−
17− -- * Type Conversion
18− , fromStreamK
19− , toStreamK
20− , fromStreamD
21− , toStreamD
22− , fromStream
23− , toStream
24− , Streamly.Internal.Data.Stream.Type.fromList
25−
26− -- * Construction
27− , cons
28− , consM
29− , nil
30− , nilM
31− , fromPure
32− , fromEffect
33−
34− -- * Applicative
35− , crossApply
36− , crossApplySnd
37− , crossApplyFst
38− , crossWith
39− , cross
40−
41− -- * Bind/Concat
42− , bindWith
43− , concatMapWith
44−
45− -- * Double folds
46− , eqBy
47− , cmpBy
48− )
49−where
50−
51−#include "inline.hs"
52−
53−import Control.Applicative (liftA2)
54−import Data.Foldable (Foldable(foldl'), fold)
55−import Data.Functor.Identity (Identity(..), runIdentity)
56−import Data.Maybe (fromMaybe)
57−import Data.Semigroup (Endo(..))
58−import GHC.Exts (IsList(..), IsString(..), oneShot)
59−import Streamly.Internal.BaseCompat ((#.))
60−import Streamly.Internal.Data.Maybe.Strict (Maybe'(..), toMaybe)
61−import Text.Read
62− ( Lexeme(Ident), lexP, parens, prec, readPrec, readListPrec
63− , readListPrecDefault)
64−
65−import qualified Streamly.Internal.Data.Stream.Common as P
66−import qualified Streamly.Internal.Data.Stream.StreamD.Type as D
67−import qualified Streamly.Internal.Data.Stream.StreamK.Type as K
68−
69−-- $setup
70−-- >>> import qualified Streamly.Data.Fold as Fold
71−-- >>> import qualified Streamly.Internal.Data.Unfold as Unfold
72−-- >>> import qualified Streamly.Internal.Data.Stream as Stream
73−
74−------------------------------------------------------------------------------
75−-- Stream
76−------------------------------------------------------------------------------
77−
78−-- | Semigroup instance appends two streams:
79−--
80−-- >>> (<>) = Stream.append
81−--
82−newtype StreamK m a = StreamK (K.StreamK m a)
83− -- XXX when deriving do we inherit an INLINE?
84− deriving (Semigroup, Monoid)
85−
86−type Stream = StreamK
87−
88−------------------------------------------------------------------------------
89−-- Conversions
90−------------------------------------------------------------------------------
91−
92−{-# INLINE_EARLY fromStreamK #-}
93−fromStreamK :: K.StreamK m a -> Stream m a
94−fromStreamK = StreamK
95−
96−{-# INLINE_EARLY toStreamK #-}
97−toStreamK :: Stream m a -> K.StreamK m a
98−toStreamK (StreamK k) = k
99−
100−{-# INLINE_EARLY fromStreamD #-}
101−fromStreamD :: Monad m => D.Stream m a -> Stream m a
102−fromStreamD = fromStreamK . D.toStreamK
103−
104−{-# INLINE_EARLY toStreamD #-}
105−toStreamD :: Applicative m => Stream m a -> D.Stream m a
106−toStreamD = D.fromStreamK . toStreamK
107−
108−{-# INLINE fromStream #-}
109−fromStream :: Monad m => D.Stream m a -> Stream m a
110−fromStream = fromStreamD
111−
112−{-# INLINE toStream #-}
113−toStream :: Applicative m => Stream m a -> D.Stream m a
114−toStream = toStreamD
115−
116−------------------------------------------------------------------------------
117−-- Generation
118−------------------------------------------------------------------------------
119−
120−-- |
121−-- >>> fromList = Prelude.foldr Stream.cons Stream.nil
122−--
123−-- Construct a stream from a list of pure values. This is more efficient than
124−-- 'fromFoldable'.
125−--
126−{-# INLINE fromList #-}
127−fromList :: Monad m => [a] -> Stream m a
128−fromList = fromStreamK . P.fromList
129−
130−------------------------------------------------------------------------------
131−-- Comparison
132−------------------------------------------------------------------------------
133−
134−-- | Compare two streams for equality
135−--
136−{-# INLINE eqBy #-}
137−eqBy :: Monad m =>
138− (a -> b -> Bool) -> Stream m a -> Stream m b -> m Bool
139−eqBy f m1 m2 = D.eqBy f (toStreamD m1) (toStreamD m2)
140−
141−-- | Compare two streams
142−--
143−{-# INLINE cmpBy #-}
144−cmpBy
145− :: Monad m
146− => (a -> b -> Ordering) -> Stream m a -> Stream m b -> m Ordering
147−cmpBy f m1 m2 = D.cmpBy f (toStreamD m1) (toStreamD m2)
148−
149−------------------------------------------------------------------------------
150−-- Functor
151−------------------------------------------------------------------------------
152−
153−instance Monad m => Functor (Stream m) where
154− {-# INLINE fmap #-}
155− -- IMPORTANT: do not use eta reduction.
156− fmap f m = fromStreamD $ D.mapM (return . f) $ toStreamD m
157−
158− {-# INLINE (<$) #-}
159− (<$) = fmap . const
160−
161−------------------------------------------------------------------------------
162−-- Lists
163−------------------------------------------------------------------------------
164−
165−-- Serial streams can act like regular lists using the Identity monad
166−
167−-- XXX Show instance is 10x slower compared to read, we can do much better.
168−-- The list show instance itself is really slow.
169−
170−-- XXX The default definitions of "<" in the Ord instance etc. do not perform
171−-- well, because they do not get inlined. Need to add INLINE in Ord class in
172−-- base?
173−
174−instance IsList (Stream Identity a) where
175− type (Item (Stream Identity a)) = a
176−
177− {-# INLINE fromList #-}
178− fromList xs = StreamK $ P.fromList xs
179−
180− {-# INLINE toList #-}
181− toList (StreamK xs) = runIdentity $ P.toList xs
182−
183−instance Eq a => Eq (Stream Identity a) where
184− {-# INLINE (==) #-}
185− (==) (StreamK xs) (StreamK ys) = runIdentity $ P.eqBy (==) xs ys
186−
187−instance Ord a => Ord (Stream Identity a) where
188− {-# INLINE compare #-}
189− compare (StreamK xs) (StreamK ys) = runIdentity $ P.cmpBy compare xs ys
190−
191− {-# INLINE (<) #-}
192− x < y =
193− case compare x y of
194− LT -> True
195− _ -> False
196−
197− {-# INLINE (<=) #-}
198− x <= y =
199− case compare x y of
200− GT -> False
201− _ -> True
202−
203− {-# INLINE (>) #-}
204− x > y =
205− case compare x y of
206− GT -> True
207− _ -> False
208−
209− {-# INLINE (>=) #-}
210− x >= y =
211− case compare x y of
212− LT -> False
213− _ -> True
214−
215− {-# INLINE max #-}
216− max x y = if x <= y then y else x
217−
218− {-# INLINE min #-}
219− min x y = if x <= y then x else y
220−
221−instance Show a => Show (Stream Identity a) where
222− showsPrec p dl = showParen (p > 10) $
223− showString "fromList " . shows (toList dl)
224−
225−instance Read a => Read (Stream Identity a) where
226− readPrec = parens $ prec 10 $ do
227− Ident "fromList" <- lexP
228− Streamly.Internal.Data.Stream.Type.fromList <$> readPrec
229−
230− readListPrec = readListPrecDefault
231−
232−instance (a ~ Char) => IsString (Stream Identity a) where
233− {-# INLINE fromString #-}
234− fromString xs = StreamK $ P.fromList xs
235−
236−-------------------------------------------------------------------------------
237−-- Foldable
238−-------------------------------------------------------------------------------
239−
240−-- The default Foldable instance has several issues:
241−-- 1) several definitions do not have INLINE on them, so we provide
242−-- re-implementations with INLINE pragmas.
243−-- 2) the definitions of sum/product/maximum/minimum are inefficient as they
244−-- use right folds, they cannot run in constant memory. We provide
245−-- implementations using strict left folds here.
246−
247−instance (Foldable m, Monad m) => Foldable (Stream m) where
248−
249− {-# INLINE foldMap #-}
250− foldMap f (StreamK xs) = fold $ P.foldr (mappend . f) mempty xs
251−
252− {-# INLINE foldr #-}
253− foldr f z t = appEndo (foldMap (Endo #. f) t) z
254−
255− {-# INLINE foldl' #-}
256− foldl' f z0 xs = foldr f' id xs z0
257− where f' x k = oneShot $ \z -> k $! f z x
258−
259− {-# INLINE length #-}
260− length = foldl' (\n _ -> n + 1) 0
261−
262− {-# INLINE elem #-}
263− elem = any . (==)
264−
265− {-# INLINE maximum #-}
266− maximum =
267− fromMaybe (errorWithoutStackTrace "maximum: empty stream")
268− . toMaybe
269− . foldl' getMax Nothing'
270−
271− where
272−
273− getMax Nothing' x = Just' x
274− getMax (Just' mx) x = Just' $! max mx x
275−
276− {-# INLINE minimum #-}
277− minimum =
278− fromMaybe (errorWithoutStackTrace "minimum: empty stream")
279− . toMaybe
280− . foldl' getMin Nothing'
281−
282− where
283−
284− getMin Nothing' x = Just' x
285− getMin (Just' mn) x = Just' $! min mn x
286−
287− {-# INLINE sum #-}
288− sum = foldl' (+) 0
289−
290− {-# INLINE product #-}
291− product = foldl' (*) 1
292−
293−-------------------------------------------------------------------------------
294−-- Traversable
295−-------------------------------------------------------------------------------
296−
297−instance Traversable (Stream Identity) where
298− {-# INLINE traverse #-}
299− traverse f (StreamK xs) =
300− fmap StreamK $ runIdentity $ P.foldr consA (pure mempty) xs
301−
302− where
303−
304− consA x ys = liftA2 K.cons (f x) ys
305−
306−-------------------------------------------------------------------------------
307−-- Construction
308−-------------------------------------------------------------------------------
309−
310−infixr 5 `cons`
311−
312−-- | A right associative prepend operation to add a pure value at the head of
313−-- an existing stream::
314−--
315−-- >>> s = 1 `Stream.cons` 2 `Stream.cons` 3 `Stream.cons` Stream.nil
316−-- >>> Stream.fold Fold.toList s
317−-- [1,2,3]
318−--
319−-- It can be used efficiently with 'Prelude.foldr':
320−--
321−-- >>> fromFoldable = Prelude.foldr Stream.cons Stream.nil
322−--
323−-- Same as the following but more efficient:
324−--
325−-- >>> cons x xs = return x `Stream.consM` xs
326−--
327−-- /CPS/
328−--
329−{-# INLINE_NORMAL cons #-}
330−cons :: a -> Stream m a -> Stream m a
331−cons x = fromStreamK . K.cons x . toStreamK
332−
333−infixr 5 `consM`
334−
335−-- | A right associative prepend operation to add an effectful value at the
336−-- head of an existing stream::
337−--
338−-- >>> s = putStrLn "hello" `consM` putStrLn "world" `consM` Stream.nil
339−-- >>> Stream.fold Fold.drain s
340−-- hello
341−-- world
342−--
343−-- It can be used efficiently with 'Prelude.foldr':
344−--
345−-- >>> fromFoldableM = Prelude.foldr Stream.consM Stream.nil
346−--
347−-- Same as the following but more efficient:
348−--
349−-- >>> consM x xs = Stream.fromEffect x `Stream.append` xs
350−--
351−-- /CPS/
352−--
353−{-# INLINE consM #-}
354−{-# SPECIALIZE consM :: IO a -> Stream IO a -> Stream IO a #-}
355−consM :: Monad m => m a -> Stream m a -> Stream m a
356−consM m = fromStreamK . K.consM m . toStreamK
357−
358−-- | A stream that terminates without producing any output or side effect.
359−--
360−-- >>> Stream.fold Fold.toList Stream.nil
361−-- []
362−--
363−{-# INLINE_NORMAL nil #-}
364−nil :: Stream m a
365−nil = fromStreamK K.nil
366−
367−-- | A stream that terminates without producing any output, but produces a side
368−-- effect.
369−--
370−-- >>> Stream.fold Fold.toList (Stream.nilM (print "nil"))
371−-- "nil"
372−-- []
373−--
374−-- /Pre-release/
375−{-# INLINE_NORMAL nilM #-}
376−nilM :: Monad m => m b -> Stream m a
377−nilM = fromStreamK . K.nilM
378−
379−-- | Create a singleton stream from a pure value.
380−--
381−-- >>> fromPure a = a `cons` Stream.nil
382−-- >>> fromPure = pure
383−-- >>> fromPure = fromEffect . pure
384−--
385−{-# INLINE_NORMAL fromPure #-}
386−fromPure :: a -> Stream m a
387−fromPure = fromStreamK . K.fromPure
388−
389−-- | Create a singleton stream from a monadic action.
390−--
391−-- >>> fromEffect m = m `consM` Stream.nil
392−-- >>> fromEffect = Stream.sequence . Stream.fromPure
393−--
394−-- >>> Stream.fold Fold.drain $ Stream.fromEffect (putStrLn "hello")
395−-- hello
396−--
397−{-# INLINE_NORMAL fromEffect #-}
398−fromEffect :: Monad m => m a -> Stream m a
399−fromEffect = fromStreamK . K.fromEffect
400−
401−-------------------------------------------------------------------------------
402−-- Applicative
403−-------------------------------------------------------------------------------
404−
405−-- | Apply a stream of functions to a stream of values and flatten the results.
406−--
407−-- Note that the second stream is evaluated multiple times.
408−--
409−-- >>> crossApply = Stream.crossWith id
410−--
411−{-# INLINE crossApply #-}
412−crossApply :: Stream m (a -> b) -> Stream m a -> Stream m b
413−crossApply m1 m2 =
414− fromStreamK $ K.crossApply (toStreamK m1) (toStreamK m2)
415−
416−{-# INLINE crossApplySnd #-}
417−crossApplySnd :: Stream m a -> Stream m b -> Stream m b
418−crossApplySnd m1 m2 =
419− fromStreamK $ K.crossApplySnd (toStreamK m1) (toStreamK m2)
420−
421−{-# INLINE crossApplyFst #-}
422−crossApplyFst :: Stream m a -> Stream m b -> Stream m a
423−crossApplyFst m1 m2 =
424− fromStreamK $ K.crossApplyFst (toStreamK m1) (toStreamK m2)
425−
426−-- |
427−-- Definition:
428−--
429−-- >>> crossWith f m1 m2 = fmap f m1 `Stream.crossApply` m2
430−--
431−-- Note that the second stream is evaluated multiple times.
432−--
433−{-# INLINE crossWith #-}
434−crossWith :: Monad m => (a -> b -> c) -> Stream m a -> Stream m b -> Stream m c
435−crossWith f m1 m2 = fmap f m1 `crossApply` m2
436−
437−-- | Given a @Stream m a@ and @Stream m b@ generate a stream with all possible
438−-- combinations of the tuple @(a, b)@.
439−--
440−-- Definition:
441−--
442−-- >>> cross = Stream.crossWith (,)
443−--
444−-- The second stream is evaluated multiple times. If that is not desired it can
445−-- be cached in an 'Data.Array.Array' and then generated from the array before
446−-- calling this function. Caching may also improve performance if the stream is
447−-- expensive to evaluate.
448−--
449−-- See 'Streamly.Internal.Data.Unfold.cross' for a much faster fused
450−-- alternative.
451−--
452−-- Time: O(m x n)
453−--
454−-- /Pre-release/
455−{-# INLINE cross #-}
456−cross :: Monad m => Stream m a -> Stream m b -> Stream m (a, b)
457−cross = crossWith (,)
458−
459−-------------------------------------------------------------------------------
460−-- Bind/Concat
461−-------------------------------------------------------------------------------
462−
463−-- |
464−--
465−-- /CPS/
466−{-# INLINE bindWith #-}
467−bindWith
468− :: (Stream m b -> Stream m b -> Stream m b)
469− -> Stream m a
470− -> (a -> Stream m b)
471− -> Stream m b
472−bindWith par m1 f =
473− fromStreamK
474− $ K.bindWith
475− (\s1 s2 -> toStreamK $ par (fromStreamK s1) (fromStreamK s2))
476− (toStreamK m1)
477− (toStreamK . f)
478−
479−-- | @concatMapWith mixer generator stream@ is a two dimensional looping
480−-- combinator. The @generator@ function is used to generate streams from the
481−-- elements in the input @stream@ and the @mixer@ function is used to merge
482−-- those streams.
483−--
484−-- /CPS/
485−{-# INLINE concatMapWith #-}
486−concatMapWith
487− :: (Stream m b -> Stream m b -> Stream m b)
488− -> (a -> Stream m b)
489− -> Stream m a
490− -> Stream m b
491−concatMapWith par f xs = bindWith par xs f
core/src/Streamly/Internal/Data/Stream/Zip.hsdeleted−91
@@ -1,91 +0,0 @@
1−{-# LANGUAGE UndecidableInstances #-}
2−
3−-- |
4−-- Module : Streamly.Internal.Data.Stream.Zip
5−-- Copyright : (c) 2017 Composewell Technologies
6−--
7−-- License : BSD3
8−-- Maintainer : streamly@composewell.com
9−-- Stability : experimental
10−-- Portability : GHC
11−--
12−-- To run examples in this module:
13−--
14−-- >>> import qualified Streamly.Data.Fold as Fold
15−-- >>> import qualified Streamly.Data.Stream as Stream
16−-- >>> import qualified Streamly.Internal.Data.Stream.Zip as Stream
17−--
18−module Streamly.Internal.Data.Stream.Zip
19− (
20− ZipStream (..)
21− , ZipSerialM
22− , ZipSerial
23− )
24−where
25−
26−import Data.Functor.Identity (Identity(..))
27−import GHC.Exts (IsList(..), IsString(..))
28−import Streamly.Internal.Data.Stream.Type (Stream)
29−import Text.Read
30− ( Lexeme(Ident), lexP, parens, prec, readPrec, readListPrec
31− , readListPrecDefault)
32−
33−import qualified Streamly.Internal.Data.Stream.Bottom as Stream
34−import qualified Streamly.Internal.Data.Stream.Generate as Stream
35−
36−-- $setup
37−-- >>> import qualified Streamly.Data.Fold as Fold
38−-- >>> import qualified Streamly.Data.Stream as Stream
39−-- >>> import qualified Streamly.Internal.Data.Stream.Zip as Stream
40−
41−------------------------------------------------------------------------------
42−-- Serially Zipping Streams
43−------------------------------------------------------------------------------
44−
45−-- | For 'ZipStream':
46−--
47−-- @
48−-- (<>) = 'Streamly.Data.Stream.append'
49−-- (\<*>) = 'Streamly.Data.Stream.zipWith' id
50−-- @
51−--
52−-- Applicative evaluates the streams being zipped serially:
53−--
54−-- >>> s1 = Stream.ZipStream $ Stream.fromFoldable [1, 2]
55−-- >>> s2 = Stream.ZipStream $ Stream.fromFoldable [3, 4]
56−-- >>> s3 = Stream.ZipStream $ Stream.fromFoldable [5, 6]
57−-- >>> s = (,,) <$> s1 <*> s2 <*> s3
58−-- >>> Stream.fold Fold.toList (Stream.unZipStream s)
59−-- [(1,3,5),(2,4,6)]
60−--
61−newtype ZipStream m a = ZipStream {unZipStream :: Stream m a}
62− deriving (Functor, Semigroup, Monoid)
63−
64−deriving instance IsList (ZipStream Identity a)
65−deriving instance (a ~ Char) => IsString (ZipStream Identity a)
66−deriving instance Eq a => Eq (ZipStream Identity a)
67−deriving instance Ord a => Ord (ZipStream Identity a)
68−deriving instance (Foldable m, Monad m) => Foldable (ZipStream m)
69−deriving instance Traversable (ZipStream Identity)
70−
71−instance Show a => Show (ZipStream Identity a) where
72− showsPrec p dl = showParen (p > 10) $
73− showString "fromList " . shows (toList dl)
74−
75−instance Read a => Read (ZipStream Identity a) where
76− readPrec = parens $ prec 10 $ do
77− Ident "fromList" <- lexP
78− fromList <$> readPrec
79− readListPrec = readListPrecDefault
80−
81−type ZipSerialM = ZipStream
82−
83−-- | An IO stream whose applicative instance zips streams serially.
84−--
85−type ZipSerial = ZipSerialM IO
86−
87−instance Monad m => Applicative (ZipStream m) where
88− pure = ZipStream . Stream.repeat
89−
90− {-# INLINE (<*>) #-}
91− ZipStream m1 <*> ZipStream m2 = ZipStream $ Stream.zipWith id m1 m2
core/src/Streamly/Internal/Data/Unfold.hs+1−1
@@ -21,7 +21,7 @@ module Streamly.Internal.Data.Unfold
2121
2222 -- * Unfolds
2323 -- One to one correspondence with
24− -- "Streamly.Internal.Data.Stream.Generate"
24+ -- "Streamly.Internal.Data.Stream.StreamD.Generate"
2525 -- ** Basic Constructors
2626 , mkUnfoldM
2727 , mkUnfoldrM
core/streamly-core.cabal−16
@@ -422,23 +422,7 @@ library
422422 if flag(dev)
423423 exposed-modules:
424424 Streamly.Internal.Data.Stream.StreamK.Alt
425− , Streamly.Internal.Data.Stream.Type
426− , Streamly.Internal.Data.Stream.Eliminate
427− , Streamly.Internal.Data.Stream.Enumerate
428− , Streamly.Internal.Data.Stream.Generate
429− , Streamly.Internal.Data.Stream.Transform
430− , Streamly.Internal.Data.Stream.Bottom
431− , Streamly.Internal.Data.Stream.Exception
432− , Streamly.Internal.Data.Stream.Expand
433− , Streamly.Internal.Data.Stream.Lift
434− , Streamly.Internal.Data.Stream.Reduce
435− , Streamly.Internal.Data.Stream.Transformer
436− , Streamly.Internal.Data.Stream.StreamDK
437− , Streamly.Internal.Data.Stream.Zip
438− , Streamly.Internal.Data.Stream.Cross
439425 , Streamly.Internal.Data.List
440− , Streamly.Data.Stream.Zip
441− --, Streamly.Internal.Data.Parser.ParserDK
442426
443427 build-depends:
444428 -- streamly-base