@@ -19,7 +19,6 @@ module Streamly.Internal.Data.Stream.IsStream.Transform
1919 -- $smapM_Notes
2020
2121 -- ** Special Maps
22− , mapM_
2322 , trace
2423 , trace_
2524 , tap
@@ -28,6 +27,11 @@ module Streamly.Internal.Data.Stream.IsStream.Transform
2827 , tapRate
2928 , pollCounts
3029
30+ -- ** Folding
31+ -- ** Right folds
32+ , foldrS
33+ , foldrT
34+
3135 -- ** Scanning
3236 -- ** Left scans
3337 , scanl'
@@ -135,6 +139,9 @@ module Streamly.Internal.Data.Stream.IsStream.Transform
135139 , dropWhileM
136140 -- , dropWhileEnd
137141 -- , dropAround
142+ , dropPrefix
143+ , dropInfix
144+ , dropSuffix
138145
139146 -- ** Breaking
140147
@@ -380,23 +387,6 @@ findIndices p m = fromStreamS $ S.findIndices p (toStreamS m)
380387elemIndices :: (IsStream t, Eq a, Monad m) => a -> t m a -> t m Int
381388elemIndices a = findIndices (== a)
382389
383−------------------------------------------------------------------------------
384−-- Map and Fold
385−------------------------------------------------------------------------------
386−
387−-- XXX this can utilize parallel mapping if we implement it as drain . mapM
388−-- |
389−-- > mapM_ = drain . mapM
390−--
391−-- Apply a monadic action to each element of the stream and discard the output
392−-- of the action. This is not really a pure transformation operation but a
393−-- transformation followed by fold.
394−--
395−-- @since 0.1.0
396−{-# INLINE mapM_ #-}
397−mapM_ :: Monad m => (a -> m b) -> SerialT m a -> m ()
398−mapM_ f m = S.mapM_ f $ toStreamS m
399−
400390------------------------------------------------------------------------------
401391-- Concurrent Application
402392------------------------------------------------------------------------------
@@ -804,6 +794,41 @@ dropWhileM p m = fromStreamD $ D.dropWhileM p $ toStreamD m
804794dropByTime ::(MonadIO m, IsStream t, TimeUnit64 d) => d -> t m a -> t m a
805795dropByTime d = fromStreamD . D.dropByTime d . toStreamD
806796
797+-- | Drop prefix from the input stream if present.
798+--
799+-- Space: @O(1)@
800+--
801+-- /Unimplemented/ - Help wanted.
802+{-# INLINE dropPrefix #-}
803+dropPrefix ::
804+ -- (Eq a, IsStream t, Monad m) =>
805+ t m a -> t m a -> t m a
806+dropPrefix = error "Not implemented yet!"
807+
808+-- | Drop all matching infix from the input stream if present. Infix stream
809+-- may be consumed multiple times.
810+--
811+-- Space: @O(n)@ where n is the length of the infix.
812+--
813+-- /Unimplemented/ - Help wanted.
814+{-# INLINE dropInfix #-}
815+dropInfix ::
816+ -- (Eq a, IsStream t, Monad m) =>
817+ t m a -> t m a -> t m a
818+dropInfix = error "Not implemented yet!"
819+
820+-- | Drop suffix from the input stream if present. Suffix stream may be
821+-- consumed multiple times.
822+--
823+-- Space: @O(n)@ where n is the length of the suffix.
824+--
825+-- /Unimplemented/ - Help wanted.
826+{-# INLINE dropSuffix #-}
827+dropSuffix ::
828+ -- (Eq a, IsStream t, Monad m) =>
829+ t m a -> t m a -> t m a
830+dropSuffix = error "Not implemented yet!"
831+
807832------------------------------------------------------------------------------
808833-- Transformation by Mapping
809834------------------------------------------------------------------------------
@@ -2610,6 +2635,57 @@ trace f = mapM (\x -> void (f x) >> return x)
26102635trace_ :: (IsStream t, Monad m) => m b -> t m a -> t m a
26112636trace_ eff = Serial.mapM (\x -> eff >> return x)
26122637
2638+------------------------------------------------------------------------------
2639+-- Folding transformations
2640+------------------------------------------------------------------------------
2641+
2642+-- | Right fold to a streaming monad.
2643+--
2644+-- > foldrS S.cons S.nil === id
2645+--
2646+-- 'foldrS' can be used to perform stateless stream to stream transformations
2647+-- like map and filter in general. It can be coupled with a scan to perform
2648+-- stateful transformations. However, note that the custom map and filter
2649+-- routines can be much more efficient than this due to better stream fusion.
2650+--
2651+-- >>> S.toList $ S.foldrS S.cons S.nil $ S.fromList [1..5]
2652+-- > [1,2,3,4,5]
2653+--
2654+-- Find if any element in the stream is 'True':
2655+--
2656+-- >>> S.toList $ S.foldrS (\x xs -> if odd x then return True else xs) (return False) $ (S.fromList (2:4:5:undefined) :: SerialT IO Int)
2657+-- > [True]
2658+--
2659+-- Map (+2) on odd elements and filter out the even elements:
2660+--
2661+-- >>> S.toList $ S.foldrS (\x xs -> if odd x then (x + 2) `S.cons` xs else xs) S.nil $ (S.fromList [1..5] :: SerialT IO Int)
2662+-- > [3,5,7]
2663+--
2664+-- 'foldrM' can also be represented in terms of 'foldrS', however, the former
2665+-- is much more efficient:
2666+--
2667+-- > foldrM f z s = runIdentityT $ foldrS (\x xs -> lift $ f x (runIdentityT xs)) (lift z) s
2668+--
2669+-- /Internal/
2670+{-# INLINE foldrS #-}
2671+foldrS :: IsStream t => (a -> t m b -> t m b) -> t m b -> t m a -> t m b
2672+foldrS = K.foldrS
2673+
2674+-- | Right fold to a transformer monad. This is the most general right fold
2675+-- function. 'foldrS' is a special case of 'foldrT', however 'foldrS'
2676+-- implementation can be more efficient:
2677+--
2678+-- > foldrS = foldrT
2679+-- > foldrM f z s = runIdentityT $ foldrT (\x xs -> lift $ f x (runIdentityT xs)) (lift z) s
2680+--
2681+-- 'foldrT' can be used to translate streamly streams to other transformer
2682+-- monads e.g. to a different streaming type.
2683+--
2684+-- /Internal/
2685+{-# INLINE foldrT #-}
2686+foldrT :: (IsStream t, Monad m, Monad (s m), MonadTrans s)
2687+ => (a -> s m b -> s m b) -> s m b -> t m a -> s m b
2688+foldrT f z s = S.foldrT f z (toStreamS s)
26132689
26142690------------------------------------------------------------------------------
26152691-- Generalize the underlying monad