@@ -0,0 +1,625 @@
2+{-# LANGUAGE RankNTypes #-}
3+{-# LANGUAGE FlexibleContexts #-}
5+#if __GLASGOW_HASKELL__ >= 800
6+{-# OPTIONS_GHC -Wno-orphans #-}
9+#include "Streams/inline.hs"
12+-- Module : Streamly.Prelude
13+-- Copyright : (c) 2017 Harendra Kumar
16+-- Maintainer : harendra.kumar@gmail.com
17+-- Stability : experimental
20+-- This module is designed to be imported qualified:
23+-- import qualified Streamly.Prelude as S
26+-- Functions with the suffix @M@ are general functions that work on monadic
27+-- arguments. The corresponding functions without the suffix @M@ work on pure
28+-- arguments and can in general be derived from their monadic versions but are
29+-- provided for convenience and for consistency with other pure APIs in the
32+-- In many cases, short definitions of the combinators are provided in the
33+-- documentation for illustration. The actual implementation may differ for
34+-- performance reasons.
36+-- Functions having a 'MonadAsync' constraint work concurrently when used with
37+-- appropriate stream type combinator. Please be careful to not use 'parallely'
38+-- with infinite streams.
40+-- Deconstruction and folds accept a 'SerialT' type instead of a polymorphic
41+-- type to ensure that streams always have a concrete monomorphic type by
42+-- default, reducing type errors. In case you want to use any other type of
43+-- stream you can use one of the type combinators provided in the "Streamly"
44+-- module to convert the stream type.
46+module Streamly.Prelude
50+ -- | Primitives to construct a stream from pure values or monadic actions.
51+ -- All other stream construction and generation combinators described later
52+ -- can be expressed in terms of these primitives. However, the special
53+ -- versions provided in this module can be much more efficient in most
54+ -- cases. Users can create custom combinators using these primitives.
64+ -- | Generate a monadic stream from a seed value or values.
72+ -- Note: Using enumeration functions e.g. 'Prelude.enumFromThen' turns out
73+ -- to be slightly faster than the idioms like @[from, then..]@.
76+ -- | We can use the 'Enum' type class to enumerate a type producing a list
77+ -- and then convert it to a stream:
80+ -- 'fromList' $ 'Prelude.enumFromThen' from then
83+ -- However, this is not particularly efficient.
84+ -- The 'Enumerable' type class provides corresponding functions that
85+ -- generate a stream instead of a list, efficiently.
91+ -- ** From Generators
92+ -- | Generate a monadic stream from a seed value and a generator function.
100+ -- ** From Containers
101+ -- | Convert an input structure, container or source into a stream. All of
102+ -- these can be expressed in terms of primitives.
110+ -- ** Deconstruction
111+ -- | It is easy to express all the folds in terms of the 'uncons' primitive,
112+ -- however the specific implementations provided later are generally more
120+-- | In imperative terms a fold can be considered as a loop over the stream
121+-- that reduces the stream to a single value.
122+-- Left and right folds use a fold function @f@ and an identity element @z@
123+-- (@zero@) to recursively deconstruct a structure and then combine and reduce
124+-- the values or transform and reconstruct a new container.
126+-- In general, a right fold is suitable for transforming and reconstructing a
127+-- right associated structure (e.g. cons lists and streamly streams) and a left
128+-- fold is suitable for reducing a right associated structure. The behavior of
129+-- right and left folds are described in detail in the individual fold's
130+-- documentation. To illustrate the two folds for cons lists:
132+-- > foldr :: (a -> b -> b) -> b -> [a] -> b
133+-- > foldr f z [] = z
134+-- > foldr f z (x:xs) = x `f` foldr f z xs
136+-- > foldl :: (b -> a -> b) -> b -> [a] -> b
137+-- > foldl f z [] = z
138+-- > foldl f z (x:xs) = foldl f (z `f` x) xs
140+-- @foldr@ is conceptually equivalent to:
142+-- > foldr f z [] = z
143+-- > foldr f z [x] = f x z
144+-- > foldr f z xs = foldr f (foldr f z (tail xs)) [head xs]
146+-- @foldl@ is conceptually equivalent to:
148+-- > foldl f z [] = z
149+-- > foldl f z [x] = f z x
150+-- > foldl f z xs = foldl f (foldl f z (init xs)) [last xs]
152+-- Left and right folds are duals of each other.
155+-- foldr f z xs = foldl (flip f) z (reverse xs)
156+-- foldl f z xs = foldr (flip f) z (reverse xs)
162+-- foldr f z xs = foldl g id xs z where g k x = k . f x
163+-- foldl f z xs = foldr g id xs z where g x k = k . flip f x
167+-- As a general rule, foldr cannot have state and foldl cannot have control.
169+-- NOTE: Folds are inherently serial as each step needs to use the result of
170+-- the previous step. However, it is possible to fold parts of the stream in
171+-- parallel and then combine the results using a monoid.
184+ -- ** Composable Left Folds
190+ -- | Folds that are guaranteed to evaluate the whole stream.
192+ -- -- ** To Summary (Full Folds)
193+ -- -- | Folds that summarize the stream to a single value.
201+ -- -- ** To Summary (Maybe) (Full Folds)
202+ -- -- | Folds that summarize a non-empty stream to a 'Just' value and return
203+ -- 'Nothing' for an empty stream.
209+ -- , toListRev -- experimental
213+ -- | Folds that generate a lazy structure. Note that the generated
214+ -- structure may not be lazy if the underlying monad is strict.
216+ -- -- ** To Containers (Full Folds)
217+ -- -- | Convert or divert a stream into an output structure, container or
222+ -- | Folds that may terminate before evaluating the whole stream. These
223+ -- folds strictly evaluate the stream until the result is determined.
225+ -- -- ** To Elements (Partial Folds)
229+ -- -- | Folds that extract selected elements of a stream or their properties.
238+ -- -- ** To Boolean (Partial Folds)
239+ -- -- | Folds that summarize the stream to a boolean value.
253+ -- | In imperative terms a map operation can be considered as a loop over
254+ -- the stream that transforms the stream into another stream by performing
255+ -- an operation on each element of the stream.
257+ -- 'map' is the least powerful transformation operation with strictest
258+ -- guarantees. A map, (1) is a stateless loop which means that no state is
259+ -- allowed to be carried from one iteration to another, therefore,
260+ -- operations on different elements are guaranteed to not affect each
261+ -- other, (2) is a strictly one-to-one transformation of stream elements
262+ -- which means it guarantees that no elements can be added or removed from
263+ -- the stream, it can merely transform them.
271+ -- | A scan is more powerful than map. While a 'map' is a stateless loop, a
272+ -- @scan@ is a stateful loop which means that a state can be shared across
273+ -- all the loop iterations, therefore, future iterations can be impacted by
274+ -- the state changes made by the past iterations. A scan yields the state
275+ -- of the loop after each iteration. Like a map, a @postscan@ or @prescan@
276+ -- does not add or remove elements in the stream, it just transforms them.
277+ -- However, a @scan@ adds one extra element to the stream.
279+ -- A left associative scan, also known as a prefix sum, can be thought of
280+ -- as a stream transformation consisting of left folds of all prefixes of a
281+ -- stream. Another way of thinking about it is that it streams all the
282+ -- intermediate values of the accumulator while applying a left fold on the
283+ -- input stream. A right associative scan, on the other hand, can be
284+ -- thought of as a stream consisting of right folds of all the suffixes of
287+ -- The following equations hold for lists:
289+ -- > scanl f z xs == map (foldl f z) $ inits xs
290+ -- > scanr f z xs == map (foldr f z) $ tails xs
293+ -- > scanl (+) 0 [1,2,3,4]
297+ -- 0 + 1 + 2 + 3 = 6
298+ -- 0 + 1 + 2 + 3 + 4 = 10
300+ -- > scanr (+) 0 [1,2,3,4]
301+ -- 1 + 2 + 3 + 4 + 0 = 10
302+ -- 2 + 3 + 4 + 0 = 9
308+ -- Left and right scans are duals:
310+ -- > scanr f z xs == reverse $ scanl (flip f) z (reverse xs)
311+ -- > scanl f z xs == reverse $ scanr (flip f) z (reverse xs)
313+ -- A scan is a stateful map i.e. a combination of map and fold:
315+ -- > map f xs = tail $ scanl (\_ x -> f x) z xs
316+ -- > map f xs = reverse $ head $ scanr (\_ x -> f x) z xs
318+ -- > foldl f z xs = last $ scanl f z xs
319+ -- > foldr f z xs = head $ scanr f z xs
331+ -- ** Scan Using Fold
349+ -- , timestampedR -- timer
352+ -- | Remove some elements from the stream based on a predicate. In
353+ -- imperative terms a filter over a stream corresponds to a loop with a
354+ -- @continue@ clause for the cases when the predicate fails.
359+ -- ** Stateful Filters
373+ -- , uniqBy -- by predicate e.g. to remove duplicate "/" in a path
374+ -- , uniqOn -- to remove duplicate sequences
375+ -- , pruneBy -- dropAround + uniqBy - like words
377+ -- ** Mapping Filters
378+ -- | Mapping along with filtering
383+ -- ** Scanning Filters
384+ -- | Stateful transformation along with filtering
388+ -- , seqIndices -- search a sequence in the stream
391+ -- | Insertion adds more elements to the stream.
396+ -- , insertAfterEach
397+ -- , intersperseBySpan
398+ -- , intersperseByTime
404+ -- * Multi-Stream Operations
405+ -- | New streams can be constructed by appending, merging or zipping
406+ -- existing streams.
409+ -- | Streams form a 'Semigroup' and a 'Monoid' under the append
414+ -- -------Stream m a------|-------Stream m a------|=>----Stream m a---
419+ -- >> S.toList $ S.fromList [1,2] \<> S.fromList [3,4]
421+ -- >> S.toList $ fold $ [S.fromList [1,2], S.fromList [3,4]]
426+ -- | Streams form a commutative semigroup under the merge
431+ -- -------Stream m a------|
432+ -- |=>----Stream m a---
433+ -- -------Stream m a------|
447+ -- -------Stream m a------|
448+ -- |=>----Stream m c---
449+ -- -------Stream m b------|
457+ -- ** Nested Streams
458+ -- | Stream operations represent loops in imperative programming, streams
459+ -- of streams represent nested loops.
470+ -- , splitAt -- spanN
471+ -- , splitIn -- sessionN
474+ -- , span -- spanWhile
475+ -- , break -- breakBefore
486+ -- | Streams can be split into segments in space or in time. We use the
487+ -- term @chunk@ to refer to a spatial length of the stream (spatial window)
488+ -- and the term @session@ to refer to a length in time (time window).
490+ -- In imperative terms, grouped folding can be considered as a nested loop
491+ -- where we loop over the stream to group elements and then loop over
492+ -- individual groups to fold them to a single value that is yielded in the
504+ -- -- *** Using Element Separators
505+ -- On == Dropping the separator
510+ -- By == Keeping the separator
514+ , wordsBy -- stripAndCompactBy
516+ -- -- *** Using Sequence Separators
518+ -- , splitOnSuffixSeq
519+ -- , splitOnPrefixSeq
521+ -- Keeping the delimiters
523+ -- , splitBySeqSuffix
524+ -- , splitBySeqPrefix
527+ -- Splitting using multiple sequence separators
529+ -- , splitOnAnySuffixSeq
530+ -- , splitOnAnyPrefixSeq
542+ -- * Windowed Classification
543+ -- | Split the stream into windows or chunks in space or time. Each window
544+ -- can be associated with a key, all events associated with a particular
545+ -- key in the window can be folded to a single result. The stream is split
546+ -- into windows of specified size, the window can be terminated early if
547+ -- the closing flag is specified in the input stream.
549+ -- The term "chunk" is used for a space window and the term "session" is
550+ -- used for a time window.
552+ -- ** Tumbling Windows
553+ -- | A new window starts after the previous window is finished.
554+ -- , classifyChunksOf
555+ -- , classifySessionsOf
557+ -- ** Keep Alive Windows
558+ -- | The window size is extended if an event arrives within the specified
559+ -- window size. This can represent sessions with idle or inactive timeout.
560+ -- , classifyKeepAliveChunks
561+ -- , classifyKeepAliveSessions
564+ -- ** Sliding Windows
565+ -- | A new window starts after the specified slide from the previous
566+ -- window. Therefore windows can overlap.
567+ , classifySlidingChunks
568+ , classifySlidingSessions
570+ -- ** Sliding Window Buffers
571+ -- , slidingChunkBuffer
572+ -- , slidingSessionBuffer
575+ -- ** Containers of Streams
576+ -- | These are variants of standard 'Foldable' fold functions that use a
577+ -- polymorphic stream sum operation (e.g. 'async' or 'wSerial') to fold a
578+ -- finite container of streams.
619+ hiding (filter, drop, dropWhile, take, takeWhile, zipWith, foldr,
620+ foldl, map, mapM, mapM_, sequence, all, any, sum, product, elem,
621+ notElem, maximum, minimum, head, last, tail, length, null,
622+ reverse, iterate, init, and, or, lookup, foldr1, (!!),
623+ scanl, scanl1, repeat, replicate, concatMap, span)
625+import Streamly.Prelude.Internal