@@ -171,6 +171,17 @@ module Streamly.Internal.Data.Fold.Types
171 Step (..)
171 Step (..)
172 , Fold (..)
172 , Fold (..)
174+ -- * Fold constructors
174 , Fold2 (..)
185 , Fold2 (..)
175 , simplify
186 , simplify
@@ -295,6 +306,96 @@ data Fold m a b =
295 -- | @Fold @ @ step @ @ initial @ @ extract@
306 -- | @Fold @ @ step @ @ initial @ @ extract@
296 forall s. Fold (s -> a -> m (Step s b)) (m (Step s b)) (s -> m b)
307 forall s. Fold (s -> a -> m (Step s b)) (m (Step s b)) (s -> m b)
309+------------------------------------------------------------------------------
310+-- Smart constructors
311+------------------------------------------------------------------------------
313+-- | Make an accumulating (non-terminating) fold using a pure step function, a
314+-- pure initial state and a pure state extraction function.
318+{-# INLINE mkAccum #-}
319+mkAccum :: Monad m => (s -> a -> s) -> s -> (s -> b) -> Fold m a b
320+mkAccum step initial extract =
322+ (\s a -> return $ Partial $ step s a)
323+ (return (Partial initial))
326+-- | Similar to 'mkAccum' but the final state extracted is identical to the
327+-- intermediate state.
331+{-# INLINE mkAccum_ #-}
332+mkAccum_ :: Monad m => (b -> a -> b) -> b -> Fold m a b
333+mkAccum_ step initial = mkAccum step initial id
335+-- | Make an accumulating (non-terminating) fold with an effectful step
336+-- function, an initial state, and a state extraction function.
340+{-# INLINE mkAccumM #-}
341+mkAccumM :: Functor m => (s -> a -> m s) -> m s -> (s -> m b) -> Fold m a b
342+mkAccumM step initial =
343+ Fold (\s a -> Partial <$> step s a) (Partial <$> initial)
345+-- | Similar to 'mkAccumM' but the final state extracted is identical to the
346+-- intermediate state.
350+{-# INLINE mkAccumM_ #-}
351+mkAccumM_ :: Monad m => (b -> a -> m b) -> m b -> Fold m a b
352+mkAccumM_ step initial = mkAccumM step initial return
354+-- | Make a terminating fold using a pure step function, a pure initial state
355+-- and a pure state extraction function.
359+{-# INLINE mkFold #-}
360+mkFold :: Monad m => (s -> a -> Step s b) -> Step s b -> (s -> b) -> Fold m a b
361+mkFold step initial extract =
362+ Fold (\s a -> return $ step s a) (return initial) (return . extract)
364+-- | Similar to 'mkFold' but the final state extracted is identical to the
365+-- intermediate state.
369+{-# INLINE mkFold_ #-}
370+mkFold_ :: Monad m => (b -> a -> Step b b) -> Step b b -> Fold m a b
371+mkFold_ step initial = mkFold step initial id
373+-- | Make a terminating fold with an effectful step function and initial state,
374+-- and a state extraction function.
378+-- We can just use 'Fold' but it is provided for completeness.
382+{-# INLINE mkFoldM #-}
383+mkFoldM :: (s -> a -> m (Step s b)) -> m (Step s b) -> (s -> m b) -> Fold m a b
386+-- | Similar to 'mkFoldM' but the final state extracted is identical to the
387+-- intermediate state.
391+{-# INLINE mkFoldM_ #-}
392+mkFoldM_ :: Monad m => (b -> a -> m (Step b b)) -> m (Step b b) -> Fold m a b
393+mkFoldM_ step initial = mkFoldM step initial return
395+------------------------------------------------------------------------------
397+------------------------------------------------------------------------------
298-- | Experimental type to provide a side input to the fold for generating the
399-- | Experimental type to provide a side input to the fold for generating the
299-- initial state. For example, if we have to fold chunks of a stream and write
400-- initial state. For example, if we have to fold chunks of a stream and write
300-- each chunk to a different file, then we can generate the file name using a
401-- each chunk to a different file, then we can generate the file name using a
@@ -309,6 +410,10 @@ simplify :: Functor m => Fold2 m c a b -> c -> Fold m a b
309simplify (Fold2 step inject extract) c =
410simplify (Fold2 step inject extract) c =
310 Fold (\x a -> Partial <$> step x a) (Partial <$> inject c) extract
411 Fold (\x a -> Partial <$> step x a) (Partial <$> inject c) extract
413+------------------------------------------------------------------------------
415+------------------------------------------------------------------------------
312-- | Maps a function on the output of the fold (the type @b@).
417-- | Maps a function on the output of the fold (the type @b@).
313instance Functor m => Functor (Fold m a) where
418instance Functor m => Functor (Fold m a) where
314 {-# INLINE fmap #-}
419 {-# INLINE fmap #-}