@@ -171,6 +171,17 @@ module Streamly.Internal.Data.Fold.Types
171171 Step (..)
172172 , Fold (..)
173173
174+ -- * Fold constructors
175+ , mkAccum
176+ , mkAccum_
177+ , mkAccumM
178+ , mkAccumM_
179+ , mkFold
180+ , mkFold_
181+ , mkFoldM
182+ , mkFoldM_
183+
184+ -- * Fold2
174185 , Fold2 (..)
175186 , simplify
176187
@@ -295,6 +306,96 @@ data Fold m a b =
295306 -- | @Fold @ @ step @ @ initial @ @ extract@
296307 forall s. Fold (s -> a -> m (Step s b)) (m (Step s b)) (s -> m b)
297308
309+------------------------------------------------------------------------------
310+-- Smart constructors
311+------------------------------------------------------------------------------
312+
313+-- | Make an accumulating (non-terminating) fold using a pure step function, a
314+-- pure initial state and a pure state extraction function.
315+--
316+-- /Internal/
317+--
318+{-# INLINE mkAccum #-}
319+mkAccum :: Monad m => (s -> a -> s) -> s -> (s -> b) -> Fold m a b
320+mkAccum step initial extract =
321+ Fold
322+ (\s a -> return $ Partial $ step s a)
323+ (return (Partial initial))
324+ (return . extract)
325+
326+-- | Similar to 'mkAccum' but the final state extracted is identical to the
327+-- intermediate state.
328+--
329+-- /Internal/
330+--
331+{-# INLINE mkAccum_ #-}
332+mkAccum_ :: Monad m => (b -> a -> b) -> b -> Fold m a b
333+mkAccum_ step initial = mkAccum step initial id
334+
335+-- | Make an accumulating (non-terminating) fold with an effectful step
336+-- function, an initial state, and a state extraction function.
337+--
338+-- /Internal/
339+--
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)
344+
345+-- | Similar to 'mkAccumM' but the final state extracted is identical to the
346+-- intermediate state.
347+--
348+-- /Internal/
349+--
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
353+
354+-- | Make a terminating fold using a pure step function, a pure initial state
355+-- and a pure state extraction function.
356+--
357+-- /Internal/
358+--
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)
363+
364+-- | Similar to 'mkFold' but the final state extracted is identical to the
365+-- intermediate state.
366+--
367+-- /Internal/
368+--
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
372+
373+-- | Make a terminating fold with an effectful step function and initial state,
374+-- and a state extraction function.
375+--
376+-- > mkFoldM = Fold
377+--
378+-- We can just use 'Fold' but it is provided for completeness.
379+--
380+-- /Internal/
381+--
382+{-# INLINE mkFoldM #-}
383+mkFoldM :: (s -> a -> m (Step s b)) -> m (Step s b) -> (s -> m b) -> Fold m a b
384+mkFoldM = Fold
385+
386+-- | Similar to 'mkFoldM' but the final state extracted is identical to the
387+-- intermediate state.
388+--
389+-- /Internal/
390+--
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
394+
395+------------------------------------------------------------------------------
396+-- Fold2
397+------------------------------------------------------------------------------
398+
298399-- | Experimental type to provide a side input to the fold for generating the
299400-- initial state. For example, if we have to fold chunks of a stream and write
300401-- 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
309410simplify (Fold2 step inject extract) c =
310411 Fold (\x a -> Partial <$> step x a) (Partial <$> inject c) extract
311412
413+------------------------------------------------------------------------------
414+-- Instances
415+------------------------------------------------------------------------------
416+
312417-- | Maps a function on the output of the fold (the type @b@).
313418instance Functor m => Functor (Fold m a) where
314419 {-# INLINE fmap #-}