on 5d096df help sign in
194 lines 5.9 kB history raw
1{-# LANGUAGE CPP #-}
2-- |
3-- Module : Streamly.Data.StreamK
4-- Copyright : (c) 2017 Composewell Technologies
5--
6-- License : BSD3
7-- Maintainer : streamly@composewell.com
8-- Stability : released
9-- Portability : GHC
10--
11-- Streams represented as chains of functions calls using Continuation Passing
12-- Style (CPS), suitable for dynamically composing potentially large number of
13-- streams.
14--
15-- Unlike the statically fused operations in "Streamly.Data.Stream", StreamK
16-- operations are less efficient, involving a function call overhead for each
17-- element, but they exhibit linear O(n) time complexity wrt to the number of
18-- stream compositions. Therefore, they are suitable for dynamically composing
19-- streams e.g. appending potentially infinite streams in recursive loops.
20-- While fused streams can be used to efficiently process elements as small as
21-- a single byte, CPS streams are typically used on bigger chunks of data to
22-- avoid the larger overhead per element. For more details See the @Stream vs
23-- StreamK@ section in the "Streamly.Data.Stream" module.
24--
25-- In addition to the combinators in this module, you can use operations from
26-- "Streamly.Data.Stream" for StreamK as well by converting StreamK to Stream
27-- ('toStream'), and vice-versa ('fromStream'). Please refer to
28-- "Streamly.Internal.Data.StreamK" for more functions that have not yet been
29-- released.
30--
31-- For documentation see the corresponding combinators in
32-- "Streamly.Data.Stream". Documentation has been omitted in this module unless
33-- there is a difference worth mentioning or if the combinator does not exist
34-- in "Streamly.Data.Stream".
36-- Notes:
37--
38-- primitive/open loop operations that can be used recursively e.g. uncons,
39-- foldBreak, parseBreak should not be converted from StreamD for use in
40-- StreamK, instead native StreamK impl should be used.
41--
42-- Closed loop operations like repeat, replicate, iterate etc can be converted
43-- from StreamD.
44--
45-- In the last phase any operation like (toStreamK . f . toStreamD) should be
46-- rewritten to a K version of f.
47-- XXX Need to add rewrite rules for all missing StreamD operations.
48--
49module Streamly.Data.StreamK
50 (
51 -- * Setup
52 -- | To execute the code examples provided in this module in ghci, please
53 -- run the following commands first.
54 --
55 -- $setup
57 -- * Overview
58 -- $overview
60 -- * Type
61 StreamK
63 -- * Construction
64 -- ** Primitives
65 -- | Primitives to construct a stream from pure values or monadic actions.
66 -- All other stream construction and generation combinators described later
67 -- can be expressed in terms of these primitives. However, the special
68 -- versions provided in this module can be much more efficient in some
69 -- cases. Users can create custom combinators using these primitives.
70 , nil
71 , nilM
72 , cons
73 , consM
75 -- ** From Values
76 , fromPure
77 , fromEffect
79 -- ** From Stream
80 -- | Please note that 'Stream' type does not observe any exceptions from
81 -- the consumer of the stream whereas 'StreamK' does.
82 , fromStream
83 , toStream
85 -- ** From Containers
86 , fromFoldable
88 -- * Elimination
90 -- ** Primitives
91 , uncons
92 , drain
94 -- -- ** Folding
95 -- , foldBreak
97 -- ** Parsing
98 , parse
99 , parseBreak
100 , parseBreakChunks
101 , parseChunks
103 -- * Transformation
104 , mapM
105 , dropWhile
106 , take
108 -- * Combining Two Streams
109 -- | Unlike the operations in "Streamly.Data.Stream", these operations can
110 -- be used to dynamically compose large number of streams e.g. using the
111 -- 'concatMapWith' and 'mergeMapWith' operations. They have a linear O(n)
112 -- time complexity wrt to the number of streams being composed.
114 -- ** Appending
115 , append
117 -- ** Interleaving
118 , interleave
120 -- ** Merging
121 , mergeBy
122 , mergeByM
124 -- ** Zipping
125 , zipWith
126 , zipWithM
128 -- ** Cross Product
129 -- XXX is "bind/concatFor" better to have than crossWith?
130 -- crossWith f xs1 xs2 = concatFor xs1 (\x -> fmap (f x) xs2)
131 , crossWith
132 -- , cross
133 -- , joinInner
134 -- , CrossStreamK (..)
136 -- * Stream of streams
137 -- | Some useful idioms:
138 --
139 -- >>> concatFoldableWith f = Prelude.foldr f StreamK.nil
140 -- >>> concatMapFoldableWith f g = Prelude.foldr (f . g) StreamK.nil
141 -- >>> concatForFoldableWith f xs g = Prelude.foldr (f . g) StreamK.nil xs
142 --
143 , concatEffect
144 -- , concatMap
145 , concatMapWith
146 , mergeMapWith
148 -- * Buffered Operations
149 , reverse
150 , sortBy
152 -- * Exceptions
153 -- | Please note that 'Stream' type does not observe any exceptions from
154 -- the consumer of the stream whereas 'StreamK' does.
155 , handle
157 -- * Resource Management
158 -- | Please note that 'Stream' type does not observe any exceptions from
159 -- the consumer of the stream whereas 'StreamK' does.
160 , bracketIO
161 )
162where
164import Streamly.Internal.Data.StreamK
165import Prelude hiding (reverse, zipWith, mapM, dropWhile, take)
167#include "DocTestDataStreamK.hs"
169-- $overview
170--
171-- Continuation passing style (CPS) stream implementation. The 'K' in 'StreamK'
172-- stands for Kontinuation.
173--
174-- StreamK can be constructed like lists, except that they use 'nil' instead of
175-- '[]' and 'cons' instead of ':'.
176--
177-- `cons` adds a pure value at the head of the stream:
178--
179-- >>> import Streamly.Data.StreamK (StreamK, cons, consM, nil)
180-- >>> stream = 1 `cons` 2 `cons` nil :: StreamK IO Int
181--
182-- You can use operations from "Streamly.Data.Stream" for StreamK as well by
183-- converting StreamK to Stream ('toStream'), and vice-versa ('fromStream').
184--
185-- >>> Stream.fold Fold.toList $ StreamK.toStream stream -- IO [Int]
186-- [1,2]
187--
188-- `consM` adds an effect at the head of the stream:
189--
190-- >>> stream = effect 1 `consM` effect 2 `consM` nil
191-- >>> Stream.fold Fold.toList $ StreamK.toStream stream
192-- 1
193-- 2
194-- [1,2]