on master help sign in
Update the builder related operations
7de3189Harendra Kumar
core/src/Streamly/Data/Fold.hs+20−7
@@ -206,16 +206,29 @@ module Streamly.Data.Fold
206
206
207 -- * Running A Fold
207 -- * Running A Fold
208 , drive
208 , drive
209− , driveBreak
209+ -- XXX Should we have a stream returning function in fold module?
210+ -- , breakStream
211+
212+ -- * Incremental builders
213+ -- | Mutable arrays ("Streamly.Data.Array.Mut") are basic builders. You can
214+ -- use the 'Streamly.Data.Array.Mut.snoc' or
215+ -- 'Streamly.Data.Array.Mut.writeAppend' operations to incrementally build
216+ -- mutable arrays. The 'addOne' and 'addStream' combinators can be used to
217+ -- incrementally build any type of structure using a fold, including arrays
218+ -- or a stream of arrays.
219+ --
220+ -- Use pinned arrays if you are going to use the data for IO.
210
221
211− -- * Building Incrmentally
222+ -- XXX should rename to "extract". can use "Fold.drive Stream.nil" instead,
223+ -- for now.
212− , extractM
224+ -- , extractM
213− , reduce
225+ -- , reduce
214− , snoc
226+ , addOne
215 -- , snocl
227 -- , snocl
228+ -- XXX Can we use something like concatEffect to implement snocM?
216− , snocM
229+ -- , snocM
217 -- , snoclM
230 -- , snoclM
218− , augment
231+ , addStream
219 , duplicate
232 , duplicate
220 -- , isClosed
233 -- , isClosed
221
234
core/src/Streamly/Data/Stream.hs+2−2
@@ -246,8 +246,8 @@ module Streamly.Data.Stream
246 -- XXX We can call this just "break" and parseBreak as "munch"
246 -- XXX We can call this just "break" and parseBreak as "munch"
247 , foldBreak
247 , foldBreak
248
248
249− -- * Builders
249+ -- XXX should we have a Fold returning function in stream module?
250− , build
250+ -- , foldAdd
251 -- , buildl
251 -- , buildl
252
252
253 -- ** Parsing
253 -- ** Parsing
core/src/Streamly/Internal/Data/Fold.hs+68−15
@@ -155,7 +155,7 @@ module Streamly.Internal.Data.Fold
155
155
156 -- * Running A Fold
156 -- * Running A Fold
157 , drive
157 , drive
158− , driveBreak
158+ , breakStream
159
159
160 -- * Building Incrementally
160 -- * Building Incrementally
161 , extractM
161 , extractM
@@ -165,7 +165,9 @@ module Streamly.Internal.Data.Fold
165 , snocl
165 , snocl
166 , snocM
166 , snocM
167 , snoclM
167 , snoclM
168− , augment
168+
169+ , addOne
170+ , addStream
169
171
170 -- * Combinators
172 -- * Combinators
171 -- ** Utilities
173 -- ** Utilities
@@ -337,9 +339,11 @@ import Streamly.Internal.Data.Fold.Type
337-- >>> :m
339-- >>> :m
338-- >>> :set -package random
340-- >>> :set -package random
339-- >>> import Control.Monad (void)
341-- >>> import Control.Monad (void)
340−-- >>> import Data.Functor.Identity (runIdentity)
342+-- >>> import Data.Functor.Identity (Identity, runIdentity)
341-- >>> import Data.Maybe (isJust)
343-- >>> import Data.Maybe (isJust)
342-- >>> import Data.Monoid (Last(..), Sum(..))
344-- >>> import Data.Monoid (Last(..), Sum(..))
345+-- >>> import Streamly.Data.Array (Array)
346+-- >>> import Streamly.Data.Fold (Fold)
343-- >>> import Streamly.Data.Stream (Stream)
347-- >>> import Streamly.Data.Stream (Stream)
344-- >>> import Data.IORef (newIORef, readIORef, writeIORef)
348-- >>> import Data.IORef (newIORef, readIORef, writeIORef)
345-- >>> import qualified Streamly.Data.Array as Array
349-- >>> import qualified Streamly.Data.Array as Array
@@ -379,33 +383,82 @@ drive strm fl = StreamD.fold fl $ StreamD.fromStreamK $ Stream.toStreamK strm
379--
383--
380-- Definition:
384-- Definition:
381--
385--
382−-- >>> driveBreak = flip Stream.foldBreak
386+-- >>> breakStream = flip Stream.foldBreak
383--
387--
384-- /CPS/
388-- /CPS/
385--
389--
386−{-# INLINE driveBreak #-}
390+{-# INLINE breakStream #-}
387−driveBreak :: Monad m => Stream m a -> Fold m a b -> m (b, Stream m a)
391+breakStream :: Monad m => Stream m a -> Fold m a b -> m (b, Stream m a)
388−driveBreak strm fl = fmap f $ K.foldBreak fl (Stream.toStreamK strm)
392+breakStream strm fl = fmap f $ K.foldBreak fl (Stream.toStreamK strm)
389
393
390 where
394 where
391
395
392 f (b, str) = (b, Stream.fromStreamK str)
396 f (b, str) = (b, Stream.fromStreamK str)
393
397
394−-- | Augment a fold strictly by adding a stream to it.
398+-- | Append a stream to a fold to build the fold accumulator incrementally. We
399+-- can repeatedly call 'addStream' on the same fold to continue building the
400+-- fold and finally use 'drive' to finish the fold and extract the result. Also
401+-- see the 'Streamly.Data.Fold.addOne' operation which is a singleton version
402+-- of 'addStream'.
395--
403--
396-- Definitions:
404-- Definitions:
397--
405--
398−-- >>> augment stream = Fold.drive stream . Fold.duplicate
406+-- >>> addStream stream = Fold.drive stream . Fold.duplicate
407+--
408+-- Example, build a list incrementally:
409+--
410+-- >>> :{
411+-- pure (Fold.toList :: Fold IO Int [Int])
412+-- >>= Fold.addOne 1
413+-- >>= Fold.addStream (Stream.enumerateFromTo 2 4)
414+-- >>= Fold.drive Stream.nil
415+-- >>= print
416+-- :}
417+-- [1,2,3,4]
418+--
419+-- This can be used as an O(n) list append compared to the O(n^2) @++@ when
420+-- used for incrementally building a list.
421+--
422+-- Example, build a stream incrementally:
423+--
424+-- >>> :{
425+-- pure (Fold.toStream :: Fold IO Int (Stream Identity Int))
426+-- >>= Fold.addOne 1
427+-- >>= Fold.addStream (Stream.enumerateFromTo 2 4)
428+-- >>= Fold.drive Stream.nil
429+-- >>= print
430+-- :}
431+-- fromList [1,2,3,4]
432+--
433+-- This can be used as an O(n) stream append compared to the O(n^2) @<>@ when
434+-- used for incrementally building a stream.
435+--
436+-- Example, build an array incrementally:
437+--
438+-- >>> :{
439+-- pure (Array.write :: Fold IO Int (Array Int))
440+-- >>= Fold.addOne 1
441+-- >>= Fold.addStream (Stream.enumerateFromTo 2 4)
442+-- >>= Fold.drive Stream.nil
443+-- >>= print
444+-- :}
445+-- fromList [1,2,3,4]
446+--
447+-- Example, build an array stream incrementally:
399--
448--
400-- >>> :{
449-- >>> :{
401−-- Fold.augment (Stream.enumerateFromTo 1 10) Fold.sum
450+-- let f :: Fold IO Int (Stream Identity (Array Int))
451+-- f = Fold.chunksOf 2 (Array.writeN 3) Fold.toStream
452+-- in pure f
453+-- >>= Fold.addOne 1
402−-- >>= Fold.augment (Stream.enumerateFromTo 11 20)
454+-- >>= Fold.addStream (Stream.enumerateFromTo 2 4)
403−-- >>= Fold.drive (Stream.enumerateFromTo 21 30)
455+-- >>= Fold.drive Stream.nil
456+-- >>= print
404-- :}
457-- :}
405−-- 465
458+-- fromList [fromList [1,2],fromList [3,4]]
406--
459--
407−augment :: Monad m => Stream m a -> Fold m a b -> m (Fold m a b)
460+addStream :: Monad m => Stream m a -> Fold m a b -> m (Fold m a b)
408−augment stream = drive stream . duplicate
461+addStream stream = drive stream . duplicate
409
462
410------------------------------------------------------------------------------
463------------------------------------------------------------------------------
411-- Transformations on fold inputs
464-- Transformations on fold inputs
core/src/Streamly/Internal/Data/Fold/Type.hs+16−4
@@ -404,6 +404,7 @@ module Streamly.Internal.Data.Fold.Type
404 , extractM
404 , extractM
405 , reduce
405 , reduce
406 , snoc
406 , snoc
407+ , addOne
407 , snocM
408 , snocM
408 , snocl
409 , snocl
409 , snoclM
410 , snoclM
@@ -1497,16 +1498,18 @@ snocM (Fold step initial extract) action = do
1497 Done _ -> return res
1498 Done _ -> return res
1498 return $ Fold step (return r) extract
1499 return $ Fold step (return r) extract
1499
1500
1500−-- | Append a singleton value to the fold, in other words run a single step of
1501−-- the fold.
1502−--
1503-- Definitions:
1501-- Definitions:
1504--
1502--
1505-- >>> snoc f = Fold.reduce . Fold.snocl f
1503-- >>> snoc f = Fold.reduce . Fold.snocl f
1506-- >>> snoc f = Fold.snocM f . return
1504-- >>> snoc f = Fold.snocM f . return
1505+
1506+-- | Append a singleton value to the fold, in other words run a single step of
1507+-- the fold.
1508+--
1509+-- Example:
1507--
1510--
1508-- >>> import qualified Data.Foldable as Foldable
1511-- >>> import qualified Data.Foldable as Foldable
1509−-- >>> Foldable.foldlM Fold.snoc Fold.toList [1..3] >>= Fold.extractM
1512+-- >>> Foldable.foldlM Fold.snoc Fold.toList [1..3] >>= Fold.drive Stream.nil
1510-- [1,2,3]
1513-- [1,2,3]
1511--
1514--
1512-- /Pre-release/
1515-- /Pre-release/
@@ -1519,6 +1522,15 @@ snoc (Fold step initial extract) a = do
1519 Done _ -> return res
1522 Done _ -> return res
1520 return $ Fold step (return r) extract
1523 return $ Fold step (return r) extract
1521
1524
1525+-- | Append a singleton value to the fold.
1526+--
1527+-- See examples under 'addStream'.
1528+--
1529+-- /Pre-release/
1530+{-# INLINE addOne #-}
1531+addOne :: Monad m => a -> Fold m a b -> m (Fold m a b)
1532+addOne = flip snoc
1533+
1522-- Similar to the comonad "extract" operation.
1534-- Similar to the comonad "extract" operation.
1523-- XXX rename to extract. We can use "extr" for the fold extract function.
1535-- XXX rename to extract. We can use "extr" for the fold extract function.
1524
1536
core/src/Streamly/Internal/Data/Stream/Bottom.hs+23−28
@@ -28,8 +28,8 @@ module Streamly.Internal.Data.Stream.Bottom
28 , foldConcat
28 , foldConcat
29
29
30 -- * Builders
30 -- * Builders
31− , build
31+ , foldAdd
32− , buildl
32+ , foldAddLazy
33
33
34 -- * Scans
34 -- * Scans
35 , smapM
35 , smapM
@@ -91,13 +91,19 @@ import Streamly.Internal.Data.Stream.Type
91-- >>> :m
91-- >>> :m
92-- >>> import Control.Monad (join, (>=>), (<=<))
92-- >>> import Control.Monad (join, (>=>), (<=<))
93-- >>> import Data.Function (fix, (&))
93-- >>> import Data.Function (fix, (&))
94+-- >>> import Data.Functor.Identity (Identity)
94-- >>> import Data.Maybe (fromJust, isJust)
95-- >>> import Data.Maybe (fromJust, isJust)
95-- >>> import Prelude hiding (take, takeWhile, drop, reverse)
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)
96-- >>> import System.IO.Unsafe (unsafePerformIO)
100-- >>> import System.IO.Unsafe (unsafePerformIO)
97-- >>> import qualified Streamly.Data.Array as Array
101-- >>> import qualified Streamly.Data.Array as Array
102+-- >>> import qualified Streamly.Data.Array.Mut as MArray
98-- >>> import qualified Streamly.Data.Fold as Fold
103-- >>> import qualified Streamly.Data.Fold as Fold
99-- >>> import qualified Streamly.Data.Parser as Parser
104-- >>> import qualified Streamly.Data.Parser as Parser
100-- >>> import qualified Streamly.Data.Unfold as Unfold
105-- >>> import qualified Streamly.Data.Unfold as Unfold
106+-- >>> import qualified Streamly.Internal.Data.Fold as Fold (toStream)
101-- >>> import Streamly.Internal.Data.Stream as Stream
107-- >>> import Streamly.Internal.Data.Stream as Stream
102
108
103------------------------------------------------------------------------------
109------------------------------------------------------------------------------
@@ -174,33 +180,25 @@ relTimesWith = fmap snd . timesWith
174-- Example, to continue folding a list of streams on the same sum fold:
180-- Example, to continue folding a list of streams on the same sum fold:
175--
181--
176-- >>> streams = [Stream.fromList [1..5], Stream.fromList [6..10]]
182-- >>> streams = [Stream.fromList [1..5], Stream.fromList [6..10]]
177−-- >>> f = Prelude.foldl Stream.buildl Fold.sum streams
183+-- >>> f = Prelude.foldl Stream.foldAddLazy Fold.sum streams
178−-- >>> Fold.extractM f
184+-- >>> Stream.fold f Stream.nil
179-- 55
185-- 55
180--
186--
181−{-# INLINE buildl #-}
187+{-# INLINE foldAddLazy #-}
182−buildl :: Monad m => Fold m a b -> Stream m a -> Fold m a b
188+foldAddLazy :: Monad m => Fold m a b -> Stream m a -> Fold m a b
183−buildl f s = D.foldContinue f $ toStreamD s
189+foldAddLazy f s = D.foldContinue f $ toStreamD s
184
190
185−-- | Append a stream to a fold strictly to build an accumulator incrementally.
191+-- >>> foldAdd f = Stream.foldAddLazy f >=> Fold.reduce
186−--
192+
187−-- Definitions:
193+-- |
188−--
194+-- >>> foldAdd = flip Fold.addStream
189−-- >>> build f = Stream.fold (Fold.duplicate f)
190−-- >>> build f = Stream.buildl f >=> Fold.reduce
191−--
192−-- Example:
193−--
194−-- >>> :{
195−-- do
196−-- sum1 <- Stream.build Fold.sum (Stream.enumerateFromTo 1 10)
197−-- sum2 <- Stream.build sum1 (Stream.enumerateFromTo 11 20)
198−-- Stream.fold sum2 (Stream.enumerateFromTo 21 30)
199−-- :}
200−-- 465
201--
195--
202−build :: Monad m => Fold m a b -> Stream m a -> m (Fold m a b)
196+foldAdd :: Monad m => Fold m a b -> Stream m a -> m (Fold m a b)
203−build f = fold (Fold.duplicate f)
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
204
202
205-- | Fold a stream using the supplied left 'Fold' and reducing the resulting
203-- | Fold a stream using the supplied left 'Fold' and reducing the resulting
206-- expression strictly at each step. The behavior is similar to 'foldl''. A
204-- expression strictly at each step. The behavior is similar to 'foldl''. A
@@ -211,9 +209,6 @@ build f = fold (Fold.duplicate f)
211--
209--
212-- >>> fold f = fmap fst . Stream.foldBreak f
210-- >>> fold f = fmap fst . Stream.foldBreak f
213-- >>> fold f = Stream.parse (Parser.fromFold f)
211-- >>> fold f = Stream.parse (Parser.fromFold f)
214−-- >>> fold f = Stream.fold Fold.one . Stream.foldManyPost f
215−-- >>> fold f = Fold.extractM . Stream.buildl f
216−-- >>> fold f = Fold.extractM <=< Stream.build f
217--
212--
218-- Example:
213-- Example:
219--
214--
core/src/Streamly/Internal/Data/Stream/Eliminate.hs+2−2
@@ -30,8 +30,8 @@ module Streamly.Internal.Data.Stream.Eliminate
30 , foldConcat
30 , foldConcat
31
31
32 -- * Builders
32 -- * Builders
33− , build
33+ , foldAdd
34− , buildl
34+ , foldAddLazy
35
35
36 -- * Running a 'Parser'
36 -- * Running a 'Parser'
37 -- "Streamly.Internal.Data.Parser".
37 -- "Streamly.Internal.Data.Parser".
src/Streamly/Internal/Network/Inet/TCP.hs+2−2
@@ -122,7 +122,7 @@ import qualified Streamly.Data.Fold as FL
122import qualified Streamly.Data.Unfold as UF
122import qualified Streamly.Data.Unfold as UF
123import qualified Streamly.Internal.Data.Unfold as UF (first, bracketIO)
123import qualified Streamly.Internal.Data.Unfold as UF (first, bracketIO)
124import qualified Streamly.Internal.Data.Stream.Chunked as AS
124import qualified Streamly.Internal.Data.Stream.Chunked as AS
125−import qualified Streamly.Internal.Data.Fold.Type as FL (Step(..))
125+import qualified Streamly.Internal.Data.Fold.Type as FL (Step(..), reduce)
126import qualified Streamly.Internal.Data.Stream as S
126import qualified Streamly.Internal.Data.Stream as S
127import qualified Streamly.Internal.Data.Stream.Exception.Lifted as S
127import qualified Streamly.Internal.Data.Stream.Exception.Lifted as S
128import qualified Streamly.Internal.Network.Socket as ISK
128import qualified Streamly.Internal.Network.Socket as ISK
@@ -358,7 +358,7 @@ writeChunks addr port = Fold step initial extract
358 `MC.onException` liftIO (Net.close skt)
358 `MC.onException` liftIO (Net.close skt)
359 return $ FL.Partial (Tuple' fld skt)
359 return $ FL.Partial (Tuple' fld skt)
360 step (Tuple' fld skt) x = do
360 step (Tuple' fld skt) x = do
361− r <- FL.snoc fld x `MC.onException` liftIO (Net.close skt)
361+ r <- FL.addOne x fld `MC.onException` liftIO (Net.close skt)
362 return $ FL.Partial (Tuple' r skt)
362 return $ FL.Partial (Tuple' r skt)
363 extract (Tuple' (Fold _ initial1 extract1) skt) = do
363 extract (Tuple' (Fold _ initial1 extract1) skt) = do
364 liftIO $ Net.close skt
364 liftIO $ Net.close skt