on master help sign in
Update docs, add unimplemented skeletons

And some formatting changes. There are no functionality changes in this commit.

commite19f64572b61d58223e3e510518e014185eb9e33 authorHarendra Kumar <harendra@composewell.com> dateThu 10 Dec 2020, 14:32 (6 years ago) parent927e42f
1 file changed+157−37
src/Streamly/Internal/Data/Fold/Types.hs+157−37
src/Streamly/Internal/Data/Fold/Types.hs+157−37
@@ -108,7 +108,7 @@
108108-- However, removing extract altogether may lead to less optimal code in some
109109-- cases because the driver of the fold needs to thread around the intermediate
110110-- output to return it if the stream stops before the fold could @Done@. When
111−-- using this approach, the @splitParse (FL.take filesize)@ benchmark shows a
111+-- using this approach, the @parseMany (FL.take filesize)@ benchmark shows a
112112-- 2x worse performance even after ensuring everything fuses. So we keep the
113113-- "extract" approach to ensure better perf in all cases.
114114--
@@ -118,7 +118,9 @@
118118-- completes.
119119
120120module Streamly.Internal.Data.Fold.Types
121− ( Step (..)
121+ (
122+ -- * Types
123+ Step (..)
122124 , Fold (..)
123125
124126 , Fold2 (..)
@@ -126,6 +128,11 @@ module Streamly.Internal.Data.Fold.Types
126128 , toListRevF -- experimental
127129 -- $toListRevF
128130
131+ -- * Generators
132+ , yield
133+ , yieldM
134+
135+ -- * Transformations
129136 , lmap
130137 , lmapM
131138 , lfilter
@@ -133,13 +140,22 @@ module Streamly.Internal.Data.Fold.Types
133140 , lcatMaybes
134141 , ltake
135142 , takeSepBy
143+ , takeByTime
136144
145+ -- * Distributing
137146 , teeWith
138147 , teeWithFst
139148 , teeWithMin
149+ , shortest
150+ , longest
151+
152+ -- * Serial Application
140153 , splitWith
154+ , split_
155+
156+ -- * Nested Application
157+ , concatMap
141158 , many
142− , takeByTime
143159 , lsessionsOf
144160 , lchunksOf
145161 , lchunksOf2
@@ -148,6 +164,7 @@ module Streamly.Internal.Data.Fold.Types
148164 , initialize
149165 , runStep
150166
167+ -- * Misc
151168 , GenericRunner(..) -- Is used in multiple step functions
152169 )
153170where
@@ -174,10 +191,13 @@ import Prelude hiding (concatMap)
174191-- Monadic left folds
175192------------------------------------------------------------------------------
176193
177−-- | This is the intermediate state in the workflow of a @Fold@. @Partial@
178−-- represents a new intermediate value available to be extracted. @Done@
179−-- represents that the fold has been terminated and won't be processed
180−-- further.
194+-- | Represents the result of the @step@ of a 'Fold'. 'Partial' returns an
195+-- intermediate state of the fold, the fold step can be called again with the
196+-- state or the driver can use @extract@ on the state to get the result out.
197+-- 'Done' returns the final result and the fold cannot be driven further.
198+--
199+-- /Internal/
200+--
181201{-# ANN type Step Fuse #-}
182202data Step s b
183203 = Partial !s
@@ -185,6 +205,9 @@ data Step s b
185205
186206-- | A bifunctor instance on 'Step'. @first@ maps on the value held by 'Partial'
187207-- and @second@ maps on the result held by 'Done'.
208+--
209+-- /Internal/
210+--
188211instance Bifunctor Step where
189212 {-# INLINE bimap #-}
190213 bimap f _ (Partial a) = Partial (f a)
@@ -202,17 +225,24 @@ instance Bifunctor Step where
202225-- @
203226-- fmap = 'second'
204227-- @
228+--
229+-- /Internal/
230+--
205231instance Functor (Step s) where
206232 {-# INLINE fmap #-}
207233 fmap = second
208234
209−-- | Represents a left fold over an input stream of values of type @a@ to a
210−-- single value of type @b@ in 'Monad' @m@.
235+-- | The type @Fold m a b@ having constructor @Fold step initial extract@
236+-- represents a left fold over an input stream of values of type @a@ to a
237+-- single value of type @b@ in 'Monad' @m@. The constructor is not exposed via
238+-- exposed modules, smart constructors are provided to create folds.
211239--
212−-- The fold uses an intermediate state @s@ as accumulator. The @step@ function
213−-- updates the state and returns the new state. When the fold is done
214−-- the final result of the fold is extracted from the intermediate state
215−-- using the @extract@ function.
240+-- The fold uses an intermediate state @s@ as accumulator, the type @s@ is
241+-- specific to the fold. The initial value of the fold state @s@ is returned by
242+-- @initial@. The @step@ function consumes an input and either returns the
243+-- final result @b@ if the fold is done or the next intermediate state (see
244+-- 'Step'). At any point the fold driver can extract the result from the
245+-- intermediate state using the @extract@ function.
216246--
217247-- @since 0.7.0
218248
@@ -244,14 +274,37 @@ instance Functor m => Functor (Fold m a) where
244274 step s b = fmap2 f (step1 s b)
245275 fmap2 g = fmap (fmap g)
246276
247−-- {-# ANN type Step Fuse #-}
248−-- data SeqFoldState sl f sr = SeqFoldL !sl | SeqFoldR !f !sr
277+-- This is the dual of stream "yield".
278+--
279+-- | A fold that always yields a pure value without consuming any input.
280+--
281+-- /Unimplemented/
282+--
283+{-# INLINE yield #-}
284+yield :: -- Monad m =>
285+ b -> Fold m a b
286+yield = undefined
287+
288+-- This is the dual of stream "yieldM".
289+--
290+-- | A fold that always yields the result of an effectful action without
291+-- consuming any input.
292+--
293+-- /Unimplemented/
294+--
295+{-# INLINE yieldM #-}
296+yieldM :: -- Monad m =>
297+ m b -> Fold m a b
298+yieldM = undefined
299+
300+{-# ANN type Step Fuse #-}
249301data SeqFoldState sl f sr = SeqFoldL sl | SeqFoldR f sr
250302
251303-- | Sequential fold application. Apply two folds sequentially to an input
252304-- stream. The input is provided to the first fold, when it is done the
253−-- remaining input is provided to the second fold. When the second fold is
254−-- done, the outputs of the two folds are combined using the supplied function.
305+-- remaining input is provided to the second fold. When the second fold is done
306+-- or if the input stream is over, the outputs of the two folds are combined
307+-- using the supplied function.
255308--
256309-- Note: This is a folding dual of appending streams using
257310-- 'Streamly.Prelude.serial', it splits the streams using two folds and zips
@@ -260,8 +313,7 @@ data SeqFoldState sl f sr = SeqFoldL sl | SeqFoldR f sr
260313-- /Internal/
261314--
262315{-# INLINE splitWith #-}
263−splitWith :: Monad m =>
264− (a -> b -> c) -> Fold m x a -> Fold m x b -> Fold m x c
316+splitWith :: Monad m => (a -> b -> c) -> Fold m x a -> Fold m x b -> Fold m x c
265317splitWith func (Fold stepL initialL extractL) (Fold stepR initialR extractR) =
266318 Fold step initial extract
267319
@@ -288,7 +340,17 @@ splitWith func (Fold stepL initialL extractL) (Fold stepR initialR extractR) =
288340 rR <- extractR sR
289341 return $ func rL rR
290342
291−-- {-# ANN type GenericRunner Fuse #-}
343+-- | Same as applicative '*>'. Run two folds serially one after the other
344+-- discarding the result of the first.
345+--
346+-- /Unimplemented/
347+--
348+{-# INLINE split_ #-}
349+split_ :: -- Monad m =>
350+ Fold m x a -> Fold m x b -> Fold m x b
351+split_ _f1 _f2 = undefined
352+
353+{-# ANN type GenericRunner Fuse #-}
292354data GenericRunner sL sR bL bR
293355 = RunBoth !sL !sR
294356 | RunLeft !sL !bR
@@ -299,17 +361,17 @@ data GenericRunner sL sR bL bR
299361instance Monad m => Applicative (Fold m a) where
300362 {-# INLINE pure #-}
301363 pure b = Fold (\() _ -> pure $ Done b) (pure ()) (\() -> pure b)
302− -- XXX deprecate this?
364+
303365 {-# INLINE (<*>) #-}
304366 (<*>) = teeWith ($)
305367
306−-- | @teeWith f f1 f2@ distributes its input to both @f1@ and @f2@ until both
307−-- of them terminate and combines their output using @f@.
368+-- | @teeWith k f1 f2@ distributes its input to both @f1@ and @f2@ until both
369+-- of them terminate and combines their output using @k@.
308370--
309371-- /Internal/
310372--
311373{-# INLINE teeWith #-}
312−teeWith :: Monad m => (b -> c -> d) -> Fold m a b -> Fold m a c -> Fold m a d
374+teeWith :: Monad m => (a -> b -> c) -> Fold m x a -> Fold m x b -> Fold m x c
313375teeWith f (Fold stepL beginL doneL) (Fold stepR beginR doneR) =
314376 Fold step begin done
315377
@@ -375,6 +437,42 @@ teeWithFst = undefined
375437teeWithMin :: (b -> c -> d) -> Fold m a b -> Fold m a c -> Fold m a d
376438teeWithMin = undefined
377439
440+-- | Shortest alternative. Apply both folds in parallel but choose the result
441+-- from the one which consumed least input i.e. take the shortest succeeding
442+-- fold.
443+--
444+-- /Unimplemented/
445+--
446+{-# INLINE shortest #-}
447+shortest :: -- Monad m =>
448+ Fold m x a -> Fold m x a -> Fold m x a
449+shortest _f1 _f2 = undefined
450+
451+-- | Longest alternative. Apply both folds in parallel but choose the result
452+-- from the one which consumed more input i.e. take the longest succeeding
453+-- fold.
454+--
455+-- /Unimplemented/
456+--
457+{-# INLINE longest #-}
458+longest :: -- Monad m =>
459+ Fold m x a -> Fold m x a -> Fold m x a
460+longest _f1 _f2 = undefined
461+
462+-- | Map a 'Fold' returning function on the result of a 'Fold'.
463+--
464+-- Compare with 'Monad' instance method '>>='. This implementation allows
465+-- stream fusion but has quadratic complexity. This can fuse with other
466+-- operations and can be much faster than 'Monad' instance for small number
467+-- (less than 8) of compositions.
468+--
469+-- /Unimplemented/
470+--
471+{-# INLINE concatMap #-}
472+concatMap :: -- Monad m =>
473+ (b -> Fold m a c) -> Fold m a b -> Fold m a c
474+concatMap _func _fld = undefined
475+
378476-- | Combines the outputs of the folds (the type @b@) using their 'Semigroup'
379477-- instances.
380478instance (Semigroup b, Monad m) => Semigroup (Fold m a b) where
@@ -558,8 +656,15 @@ lcatMaybes = lfilter isJust . lmap fromJust
558656-- Parsing
559657------------------------------------------------------------------------------
560658
561−-- XXX Incorrect implementation when i <= 0
562−-- | Take first @n@ elements from the stream and discard the rest.
659+-- | Take at most @n@ input elements and fold them using the supplied fold.
660+--
661+-- >>> Stream.fold (Fold.ltake 1 Fold.toList) $ Stream.fromList [1]
662+-- [1]
663+--
664+-- >>> Stream.fold (Fold.ltake (-1) Fold.toList) $ Stream.fromList [1]
665+-- []
666+--
667+-- /Internal/
563668--
564669-- @since 0.7.0
565670{-# INLINE ltake #-}
@@ -581,6 +686,7 @@ ltake n (Fold fstep finitial fextract) = Fold step initial extract
581686 then return $ Partial s1
582687 else Done <$> fextract sres
583688 Done bres -> return $ Done bres
689+ -- XXX take 0 case is broken currently
584690 | otherwise = Done <$> fextract r
585691
586692 extract (Tuple' _ r) = fextract r
@@ -652,6 +758,8 @@ runStep _ _ = undefined
652758-- the @split@ fold repeatedly on the input stream and accumulates zero or more
653759-- fold results using @collect@.
654760--
761+-- Stops when @collect@ stops.
762+--
655763-- /Internal/
656764--
657765-- /See also: Streamly.Prelude.concatMap, Streamly.Prelude.foldMany/
@@ -663,10 +771,7 @@ many (Fold fstep finitial fextract) (Fold step1 initial1 extract1) =
663771
664772 where
665773
666− initial = do
667− ps <- initial1
668− fs <- finitial
669− pure (Tuple' ps fs)
774+ initial = Tuple' <$> initial1 <*> finitial
670775
671776 {-# INLINE step #-}
672777 step (Tuple' st fs) a = do
@@ -688,11 +793,15 @@ many (Fold fstep finitial fextract) (Fold step1 initial1 extract1) =
688793 Partial s1 -> fextract s1
689794 Done x -> return x
690795
691−-- XXX Replace this with the previous implementation using `many`
692−-- XXX The only difference from the previous implementation is that the `if`
693−-- statement encompasses `collect` rather then the other way around.
694−-- | For every n input items, apply the first fold and supply the result to the
695−-- next fold.
796+-- | @lchunksOf n split collect@ repeatedly applies the @split@ fold to chunks
797+-- of @n@ items in the input stream and supplies the result to the @collect@
798+-- fold.
799+--
800+-- > lchunksOf n split collect = many collect (ltake n split)
801+--
802+-- Stops when @collect@ stops.
803+--
804+-- /Internal/
696805--
697806{-# INLINE lchunksOf #-}
698807lchunksOf :: Monad m => Int -> Fold m a b -> Fold m b c -> Fold m a c
@@ -712,7 +821,7 @@ lchunksOf2 n (Fold step1 initial1 extract1) (Fold2 step2 inject2 extract2) =
712821 then do
713822 res <- step1 r1 a
714823 case res of
715− Partial sres -> return $ Tuple3' (i + 1) sres r2
824+ Partial s -> return $ Tuple3' (i + 1) s r2
716825 Done b -> do
717826 s <- initial1
718827 r21 <- step2 r2 b
@@ -728,7 +837,13 @@ lchunksOf2 n (Fold step1 initial1 extract1) (Fold2 step2 inject2 extract2) =
728837 acc2 <- step2 r2 res
729838 extract2 acc2
730839
731−-- XXX zip the streams with timestamps
840+-- | @takeByTime n fold@ uses @fold@ to fold the input items arriving within a
841+-- window of first @n@ seconds.
842+--
843+-- Stops when @fold@ stops or when the timeout occurs.
844+--
845+-- /Internal/
846+--
732847{-# INLINE takeByTime #-}
733848takeByTime :: MonadAsync m => Double -> Fold m a b -> Fold m a b
734849takeByTime n (Fold step initial done) = Fold step' initial' done'
@@ -785,6 +900,11 @@ takeByTime n (Fold step initial done) = Fold step' initial' done'
785900-- -----Fold m a b----|-Fold n a c-|-Fold n a c-|-...-|----Fold m a c
786901--
787902-- @
903+--
904+-- > lsessionsOf n split collect = many collect (takeByTime n split)
905+--
906+-- /Internal/
907+--
788908{-# INLINE lsessionsOf #-}
789909lsessionsOf :: MonadAsync m => Double -> Fold m a b -> Fold m b c -> Fold m a c
790910lsessionsOf n split collect = many collect (takeByTime n split)