{-# LANGUAGE CPP #-} -- | -- Module : Streamly.Data.StreamK -- Copyright : (c) 2017 Composewell Technologies -- -- License : BSD3 -- Maintainer : streamly@composewell.com -- Stability : released -- Portability : GHC -- -- Streams represented as chains of functions calls using Continuation Passing -- Style (CPS), suitable for dynamically composing potentially large number of -- streams. -- -- Unlike the statically fused operations in "Streamly.Data.Stream", StreamK -- operations are less efficient, involving a function call overhead for each -- element, but they exhibit linear O(n) time complexity wrt to the number of -- stream compositions. Therefore, they are suitable for dynamically composing -- streams e.g. appending potentially infinite streams in recursive loops. -- While fused streams can be used to efficiently process elements as small as -- a single byte, CPS streams are typically used on bigger chunks of data to -- avoid the larger overhead per element. For more details See the @Stream vs -- StreamK@ section in the "Streamly.Data.Stream" module. -- -- In addition to the combinators in this module, you can use operations from -- "Streamly.Data.Stream" for StreamK as well by converting StreamK to Stream -- ('toStream'), and vice-versa ('fromStream'). Please refer to -- "Streamly.Internal.Data.StreamK" for more functions that have not yet been -- released. -- -- For documentation see the corresponding combinators in -- "Streamly.Data.Stream". Documentation has been omitted in this module unless -- there is a difference worth mentioning or if the combinator does not exist -- in "Streamly.Data.Stream". -- Notes: -- -- primitive/open loop operations that can be used recursively e.g. uncons, -- foldBreak, parseBreak should not be converted from StreamD for use in -- StreamK, instead native StreamK impl should be used. -- -- Closed loop operations like repeat, replicate, iterate etc can be converted -- from StreamD. -- -- In the last phase any operation like (toStreamK . f . toStreamD) should be -- rewritten to a K version of f. -- XXX Need to add rewrite rules for all missing StreamD operations. -- module Streamly.Data.StreamK ( -- * Setup -- | To execute the code examples provided in this module in ghci, please -- run the following commands first. -- -- $setup -- * Overview -- $overview -- * Type StreamK -- * Construction -- ** Primitives -- | Primitives to construct a stream from pure values or monadic actions. -- All other stream construction and generation combinators described later -- can be expressed in terms of these primitives. However, the special -- versions provided in this module can be much more efficient in some -- cases. Users can create custom combinators using these primitives. , nil , nilM , cons , consM -- ** From Values , fromPure , fromEffect -- ** From Stream -- | Please note that 'Stream' type does not observe any exceptions from -- the consumer of the stream whereas 'StreamK' does. , fromStream , toStream -- ** From Containers , fromFoldable -- * Elimination -- ** Primitives , uncons , drain -- -- ** Folding -- , foldBreak -- ** Parsing , parse , parseBreak , parseBreakChunks , parseChunks -- * Transformation , mapM , dropWhile , take -- * Combining Two Streams -- | Unlike the operations in "Streamly.Data.Stream", these operations can -- be used to dynamically compose large number of streams e.g. using the -- 'concatMapWith' and 'mergeMapWith' operations. They have a linear O(n) -- time complexity wrt to the number of streams being composed. -- ** Appending , append -- ** Interleaving , interleave -- ** Merging , mergeBy , mergeByM -- ** Zipping , zipWith , zipWithM -- ** Cross Product -- XXX is "bind/concatFor" better to have than crossWith? -- crossWith f xs1 xs2 = concatFor xs1 (\x -> fmap (f x) xs2) , crossWith -- , cross -- , joinInner -- , CrossStreamK (..) -- * Stream of streams -- | Some useful idioms: -- -- >>> concatFoldableWith f = Prelude.foldr f StreamK.nil -- >>> concatMapFoldableWith f g = Prelude.foldr (f . g) StreamK.nil -- >>> concatForFoldableWith f xs g = Prelude.foldr (f . g) StreamK.nil xs -- , concatEffect -- , concatMap , concatMapWith , mergeMapWith -- * Buffered Operations , reverse , sortBy -- * Exceptions -- | Please note that 'Stream' type does not observe any exceptions from -- the consumer of the stream whereas 'StreamK' does. , handle -- * Resource Management -- | Please note that 'Stream' type does not observe any exceptions from -- the consumer of the stream whereas 'StreamK' does. , bracketIO ) where import Streamly.Internal.Data.StreamK import Prelude hiding (reverse, zipWith, mapM, dropWhile, take) #include "DocTestDataStreamK.hs" -- $overview -- -- Continuation passing style (CPS) stream implementation. The 'K' in 'StreamK' -- stands for Kontinuation. -- -- StreamK can be constructed like lists, except that they use 'nil' instead of -- '[]' and 'cons' instead of ':'. -- -- `cons` adds a pure value at the head of the stream: -- -- >>> import Streamly.Data.StreamK (StreamK, cons, consM, nil) -- >>> stream = 1 `cons` 2 `cons` nil :: StreamK IO Int -- -- You can use operations from "Streamly.Data.Stream" for StreamK as well by -- converting StreamK to Stream ('toStream'), and vice-versa ('fromStream'). -- -- >>> Stream.fold Fold.toList $ StreamK.toStream stream -- IO [Int] -- [1,2] -- -- `consM` adds an effect at the head of the stream: -- -- >>> stream = effect 1 `consM` effect 2 `consM` nil -- >>> Stream.fold Fold.toList $ StreamK.toStream stream -- 1 -- 2 -- [1,2]