342342-- can be expressed using 'mconcat' and a suitable 'Monoid'. Instead of
343343-- writing folds we can write Monoids and turn them into folds.
344344--
345+ -- = Initial, Final Duality
346+ --
347+ -- Currently there is a discrepancy between folds and streams, folds have an
348+ -- "initial" to initialize the fold without any input. A producer side dual
349+ -- would be a finalizer called whenever the stream stops.
350+ --
351+ -- However, the initial action in folds creates a discrepancy with the CPS
352+ -- folds, and the same may be the case if we have a stop/cleanup operation in
353+ -- streams.
354+
345355module Streamly.Internal.Data.Fold.Type
346356 (
347357 module Streamly.Internal.Data.Fold.Step
@@ -816,6 +826,8 @@ fromRefold (Refold step inject extract) c =
816826-- Basic Folds
817827------------------------------------------------------------------------------
818828
829+ -- drain is a dual of infinite streams. This is the /dev/null of folds.
830+
819831-- | A fold that drains all its input, running the effects and discarding the
820832-- results.
821833--
@@ -830,6 +842,8 @@ drain = fromScanl Scanl.drain
830842-- To Containers
831843------------------------------------------------------------------------------
832844
845+ -- toList is a dual of Stream.fromList.
846+
833847-- | Folds the input stream to a list.
834848--
835849-- /Warning!/ working on large lists accumulated as buffers in memory could be
@@ -876,6 +890,8 @@ toListRev = foldl' (flip (:)) []
876890toStreamKRev :: Monad m => Fold m a (K. StreamK n a )
877891toStreamKRev = fromScanl Scanl. toStreamKRev
878892
893+ -- toStreamK is a dual of Stream.fromStreamK
894+
879895-- | A fold that buffers its input to a pure stream.
880896--
881897-- >>> toStreamK = foldr StreamK.cons StreamK.nil
@@ -909,6 +925,9 @@ genericLength = fromScanl Scanl.genericLength
909925length :: Monad m => Fold m a Int
910926length = fromScanl Scanl. length
911927
928+ -- Naming: "last" makes better sense for folds whereas "latest" makes better
929+ -- sense for scans.
930+
912931-- | Returns the latest element of the input stream, if any.
913932--
914933-- >>> latest = Fold.foldl1' (\_ x -> x)
@@ -939,39 +958,27 @@ instance Functor m => Functor (Fold m a) where
939958 step s b = fmap2 f (step1 s b)
940959 fmap2 g = fmap (fmap g)
941960
942- -- XXX These are singleton folds that are closed for input. The correspondence
943- -- to a nil stream would be a nil fold that returns "Done" in "initial" i.e. it
944- -- does not produce any accumulator value. However, we do not have a
945- -- representation of an empty value in folds, because the Done constructor
946- -- always produces a value (Done b). We can potentially use "Partial s b" and
947- -- "Done" to make the type correspond to the stream type. That may be possible
948- -- if we introduce the "Skip" constructor as well because after the last
949- -- "Partial s b" we have to emit a "Skip to Done" state to keep cranking the
950- -- fold until it is done.
951- --
952- -- There is also the asymmetry between folds and streams because folds have an
953- -- "initial" to initialize the fold without any input. A similar concept is
954- -- possible in streams as well to stop the stream. That would be a "closing"
955- -- operation for the stream which can be called even without consuming any item
956- -- from the stream or when we are done consuming.
961+ -- NOTE: Canonical producer side dual of this is "Stream.nil" which generates a
962+ -- nil stream regardless of the seed. This folds a nil stream to some known
963+ -- value, reversing the producer side process.
957964--
958- -- However, the initial action in folds creates a discrepancy with the CPS
959- -- folds, and the same may be the case if we have a stop/cleanup operation in
960- -- streams.
965+ -- Alternate names: const
961966
962- -- | Make a fold that yields the supplied value without consuming any further
963- -- input.
964- --
965- -- /Pre-release/
967+ -- | Make a fold that immediately returns a constant output without consuming
968+ -- any input.
966969--
967970{-# INLINE fromPure #-}
968971fromPure :: Applicative m => b -> Fold m a b
969972fromPure b = Fold undefined (pure $ Done b) pure pure
970973
971- -- | Make a fold that yields the result of the supplied effectful action
972- -- without consuming any further input.
974+ -- NOTE: Canonical producer side dual of this is "Stream.nilM" which generates
975+ -- a nil stream and an effect. This folds a nil stream to some known value and
976+ -- an effect, reverse of the producer.
973977--
974- -- /Pre-release/
978+ -- Alternative names: constM
979+
980+ -- | Make a fold that immediately returns a constant output along with an
981+ -- effect without consuming any input.
975982--
976983{-# INLINE fromEffect #-}
977984fromEffect :: Applicative m => m b -> Fold m a b
@@ -980,6 +987,9 @@ fromEffect b = Fold undefined (Done <$> b) pure pure
980987{-# ANN type SeqFoldState Fuse #-}
981988data SeqFoldState sl f sr = SeqFoldL ! sl | SeqFoldR ! f ! sr
982989
990+ -- dual of Stream.append
991+ -- Alternative names: appendWith, serialWith.
992+
983993-- | Sequential fold application. Apply two folds sequentially to an input
984994-- stream. The input is provided to the first fold, when it is done - the
985995-- remaining input is provided to the second fold. When the second fold is done
@@ -2054,6 +2064,8 @@ ifThen predicate
20542064-- 'duplicate' essentially appends a stream to the fold without finishing the
20552065-- fold. Compare with 'snoc' which appends a singleton value to the fold.
20562066--
2067+ -- See 'Fold.addStream' as well.
2068+ --
20572069-- /Pre-release/
20582070{-# INLINE duplicate #-}
20592071duplicate :: Monad m => Fold m a b -> Fold m a (Fold m a b )
@@ -2086,7 +2098,7 @@ reduce (Fold step initial extract final) = do
20862098 i <- initial
20872099 return $ Fold step (return i) extract final
20882100
2089- -- This is the dual of Stream @cons@.
2101+ -- This is a fold builder equivalent of the stream builder @cons@.
20902102
20912103-- | Append an effect to the fold lazily, in other words run a single
20922104-- step of the fold.
0 commit comments