on master help sign in
Update the builder related operations

Move to fold module, rename, update docs

commit7de318924e8299b9be3318a5543fa25cc1c9a8a3 authorHarendra Kumar <harendra@composewell.com> dateWed 14 Dec 2022, 17:54 (4 years ago) parentb6185ba
7 files changed+133−60
core/src/Streamly/Data/Fold.hs+20−7 core/src/Streamly/Data/Stream.hs+2−2 core/src/Streamly/Internal/Data/Fold.hs+68−15 core/src/Streamly/Internal/Data/Fold/Type.hs+16−4 core/src/Streamly/Internal/Data/Stream/Bottom.hs+23−28 core/src/Streamly/Internal/Data/Stream/Eliminate.hs+2−2 src/Streamly/Internal/Network/Inet/TCP.hs+2−2
core/src/Streamly/Data/Fold.hs+20−7
@@ -206,16 +206,29 @@ module Streamly.Data.Fold
206206
207207 -- * Running A Fold
208208 , 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.
210221
211− -- * Building Incrmentally
212− , extractM
213− , reduce
214− , snoc
222+ -- XXX should rename to "extract". can use "Fold.drive Stream.nil" instead,
223+ -- for now.
224+ -- , extractM
225+ -- , reduce
226+ , addOne
215227 -- , snocl
216− , snocM
228+ -- XXX Can we use something like concatEffect to implement snocM?
229+ -- , snocM
217230 -- , snoclM
218− , augment
231+ , addStream
219232 , duplicate
220233 -- , isClosed
221234
core/src/Streamly/Data/Stream.hs+2−2
@@ -246,8 +246,8 @@ module Streamly.Data.Stream
246246 -- XXX We can call this just "break" and parseBreak as "munch"
247247 , foldBreak
248248
249− -- * Builders
250− , build
249+ -- XXX should we have a Fold returning function in stream module?
250+ -- , foldAdd
251251 -- , buildl
252252
253253 -- ** Parsing
core/src/Streamly/Internal/Data/Fold.hs+68−15
@@ -155,7 +155,7 @@ module Streamly.Internal.Data.Fold
155155
156156 -- * Running A Fold
157157 , drive
158− , driveBreak
158+ , breakStream
159159
160160 -- * Building Incrementally
161161 , extractM
@@ -165,7 +165,9 @@ module Streamly.Internal.Data.Fold
165165 , snocl
166166 , snocM
167167 , snoclM
168− , augment
168+
169+ , addOne
170+ , addStream
169171
170172 -- * Combinators
171173 -- ** Utilities
@@ -337,9 +339,11 @@ import Streamly.Internal.Data.Fold.Type
337339-- >>> :m
338340-- >>> :set -package random
339341-- >>> import Control.Monad (void)
340−-- >>> import Data.Functor.Identity (runIdentity)
342+-- >>> import Data.Functor.Identity (Identity, runIdentity)
341343-- >>> import Data.Maybe (isJust)
342344-- >>> import Data.Monoid (Last(..), Sum(..))
345+-- >>> import Streamly.Data.Array (Array)
346+-- >>> import Streamly.Data.Fold (Fold)
343347-- >>> import Streamly.Data.Stream (Stream)
344348-- >>> import Data.IORef (newIORef, readIORef, writeIORef)
345349-- >>> import qualified Streamly.Data.Array as Array
@@ -379,33 +383,82 @@ drive strm fl = StreamD.fold fl $ StreamD.fromStreamK $ Stream.toStreamK strm
379383--
380384-- Definition:
381385--
382−-- >>> driveBreak = flip Stream.foldBreak
386+-- >>> breakStream = flip Stream.foldBreak
383387--
384388-- /CPS/
385389--
386−{-# INLINE driveBreak #-}
387−driveBreak :: 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)
390+{-# INLINE breakStream #-}
391+breakStream :: Monad m => Stream m a -> Fold m a b -> m (b, Stream m a)
392+breakStream strm fl = fmap f $ K.foldBreak fl (Stream.toStreamK strm)
389393
390394 where
391395
392396 f (b, str) = (b, Stream.fromStreamK str)
393397
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'.
395403--
396404-- Definitions:
397405--
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:
399448--
400449-- >>> :{
401−-- Fold.augment (Stream.enumerateFromTo 1 10) Fold.sum
402−-- >>= Fold.augment (Stream.enumerateFromTo 11 20)
403−-- >>= Fold.drive (Stream.enumerateFromTo 21 30)
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
454+-- >>= Fold.addStream (Stream.enumerateFromTo 2 4)
455+-- >>= Fold.drive Stream.nil
456+-- >>= print
404457-- :}
405−-- 465
458+-- fromList [fromList [1,2],fromList [3,4]]
406459--
407−augment :: Monad m => Stream m a -> Fold m a b -> m (Fold m a b)
408−augment stream = drive stream . duplicate
460+addStream :: Monad m => Stream m a -> Fold m a b -> m (Fold m a b)
461+addStream stream = drive stream . duplicate
409462
410463------------------------------------------------------------------------------
411464-- Transformations on fold inputs
core/src/Streamly/Internal/Data/Fold/Type.hs+16−4
@@ -404,6 +404,7 @@ module Streamly.Internal.Data.Fold.Type
404404 , extractM
405405 , reduce
406406 , snoc
407+ , addOne
407408 , snocM
408409 , snocl
409410 , snoclM
@@ -1497,16 +1498,18 @@ snocM (Fold step initial extract) action = do
14971498 Done _ -> return res
14981499 return $ Fold step (return r) extract
14991500
1500−-- | Append a singleton value to the fold, in other words run a single step of
1501−-- the fold.
1502−--
15031501-- Definitions:
15041502--
15051503-- >>> snoc f = Fold.reduce . Fold.snocl f
15061504-- >>> 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:
15071510--
15081511-- >>> 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
15101513-- [1,2,3]
15111514--
15121515-- /Pre-release/
@@ -1519,6 +1522,15 @@ snoc (Fold step initial extract) a = do
15191522 Done _ -> return res
15201523 return $ Fold step (return r) extract
15211524
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+
15221534-- Similar to the comonad "extract" operation.
15231535-- XXX rename to extract. We can use "extr" for the fold extract function.
15241536
core/src/Streamly/Internal/Data/Stream/Bottom.hs+23−28
@@ -28,8 +28,8 @@ module Streamly.Internal.Data.Stream.Bottom
2828 , foldConcat
2929
3030 -- * Builders
31− , build
32− , buildl
31+ , foldAdd
32+ , foldAddLazy
3333
3434 -- * Scans
3535 , smapM
@@ -91,13 +91,19 @@ import Streamly.Internal.Data.Stream.Type
9191-- >>> :m
9292-- >>> import Control.Monad (join, (>=>), (<=<))
9393-- >>> import Data.Function (fix, (&))
94+-- >>> import Data.Functor.Identity (Identity)
9495-- >>> import Data.Maybe (fromJust, isJust)
9596-- >>> 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)
96100-- >>> import System.IO.Unsafe (unsafePerformIO)
97101-- >>> import qualified Streamly.Data.Array as Array
102+-- >>> import qualified Streamly.Data.Array.Mut as MArray
98103-- >>> import qualified Streamly.Data.Fold as Fold
99104-- >>> import qualified Streamly.Data.Parser as Parser
100105-- >>> import qualified Streamly.Data.Unfold as Unfold
106+-- >>> import qualified Streamly.Internal.Data.Fold as Fold (toStream)
101107-- >>> import Streamly.Internal.Data.Stream as Stream
102108
103109------------------------------------------------------------------------------
@@ -174,33 +180,25 @@ relTimesWith = fmap snd . timesWith
174180-- Example, to continue folding a list of streams on the same sum fold:
175181--
176182-- >>> streams = [Stream.fromList [1..5], Stream.fromList [6..10]]
177−-- >>> f = Prelude.foldl Stream.buildl Fold.sum streams
178−-- >>> Fold.extractM f
183+-- >>> f = Prelude.foldl Stream.foldAddLazy Fold.sum streams
184+-- >>> Stream.fold f Stream.nil
179185-- 55
180186--
181−{-# INLINE buildl #-}
182−buildl :: Monad m => Fold m a b -> Stream m a -> Fold m a b
183−buildl f s = D.foldContinue f $ toStreamD s
187+{-# INLINE foldAddLazy #-}
188+foldAddLazy :: Monad m => Fold m a b -> Stream m a -> Fold m a b
189+foldAddLazy f s = D.foldContinue f $ toStreamD s
184190
185−-- | Append a stream to a fold strictly to build an accumulator incrementally.
186−--
187−-- Definitions:
188−--
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
191+-- >>> foldAdd f = Stream.foldAddLazy f >=> Fold.reduce
192+
193+-- |
194+-- >>> foldAdd = flip Fold.addStream
201195--
202−build :: Monad m => Fold m a b -> Stream m a -> m (Fold m a b)
203−build f = fold (Fold.duplicate f)
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
204202
205203-- | Fold a stream using the supplied left 'Fold' and reducing the resulting
206204-- expression strictly at each step. The behavior is similar to 'foldl''. A
@@ -211,9 +209,6 @@ build f = fold (Fold.duplicate f)
211209--
212210-- >>> fold f = fmap fst . Stream.foldBreak f
213211-- >>> 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
217212--
218213-- Example:
219214--
core/src/Streamly/Internal/Data/Stream/Eliminate.hs+2−2
@@ -30,8 +30,8 @@ module Streamly.Internal.Data.Stream.Eliminate
3030 , foldConcat
3131
3232 -- * Builders
33− , build
34− , buildl
33+ , foldAdd
34+ , foldAddLazy
3535
3636 -- * Running a 'Parser'
3737 -- "Streamly.Internal.Data.Parser".
src/Streamly/Internal/Network/Inet/TCP.hs+2−2
@@ -122,7 +122,7 @@ import qualified Streamly.Data.Fold as FL
122122import qualified Streamly.Data.Unfold as UF
123123import qualified Streamly.Internal.Data.Unfold as UF (first, bracketIO)
124124import 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)
126126import qualified Streamly.Internal.Data.Stream as S
127127import qualified Streamly.Internal.Data.Stream.Exception.Lifted as S
128128import qualified Streamly.Internal.Network.Socket as ISK
@@ -358,7 +358,7 @@ writeChunks addr port = Fold step initial extract
358358 `MC.onException` liftIO (Net.close skt)
359359 return $ FL.Partial (Tuple' fld skt)
360360 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)
362362 return $ FL.Partial (Tuple' r skt)
363363 extract (Tuple' (Fold _ initial1 extract1) skt) = do
364364 liftIO $ Net.close skt