on master help sign in
Move transformation ops from IsStream's Eliminate to Transform.

- Moved foldrS, foldrT, dropPrefix, dropInfix, dropSuffix to Tranform - Moved mapM_ to IsStream.

commitdc13710177d5a041904a7dc4ccdd121e6c0d7eb6 authorPranay Sashank <pranaysashank@composewell.com> dateSat 2 Jan 2021, 21:20 (6 years ago) parentc339342
3 files changed+113−107
src/Streamly/Internal/Data/Stream/IsStream.hs+19 src/Streamly/Internal/Data/Stream/IsStream/Eliminate.hs−89 src/Streamly/Internal/Data/Stream/IsStream/Transform.hs+94−18
src/Streamly/Internal/Data/Stream/IsStream.hs+19
@@ -619,6 +619,7 @@ import Streamly.Internal.Data.Stream.Combinators
619619 , maxRate, constRate)
620620import Streamly.Internal.Data.Stream.Parallel
621621 ( ParallelT, Parallel, parallely)
622+import Streamly.Internal.Data.Stream.Prelude (toStreamS)
622623import Streamly.Internal.Data.Stream.StreamK (IsStream((|:), consM), adapt)
623624import Streamly.Internal.Data.Stream.Serial
624625 ( SerialT, WSerialT, Serial, WSerial, serially
@@ -645,6 +646,11 @@ import qualified Streamly.Internal.Data.Stream.Parallel as Par
645646import qualified Streamly.Internal.Data.Stream.Zip as Z
646647import qualified Data.Heap as H
647648import qualified Data.Map.Strict as Map
649+#ifdef USE_STREAMK_ONLY
650+import qualified Streamly.Internal.Data.Stream.StreamK as S
651+#else
652+import qualified Streamly.Internal.Data.Stream.StreamD as S
653+#endif
648654
649655import Prelude hiding
650656 ( filter, drop, dropWhile, take, takeWhile, zipWith, foldr
@@ -675,6 +681,19 @@ fromCallback setCallback = concatM $ do
675681-- Specialized folds
676682------------------------------------------------------------------------------
677683
684+-- XXX this can utilize parallel mapping if we implement it as drain . mapM
685+-- |
686+-- > mapM_ = drain . mapM
687+--
688+-- Apply a monadic action to each element of the stream and discard the output
689+-- of the action. This is not really a pure transformation operation but a
690+-- transformation followed by fold.
691+--
692+-- @since 0.1.0
693+{-# INLINE mapM_ #-}
694+mapM_ :: Monad m => (a -> m b) -> SerialT m a -> m ()
695+mapM_ f m = S.mapM_ f $ toStreamS m
696+
678697-- |
679698-- > drainN n = drain . take n
680699-- > drainN n = fold (Fold.ltake n Fold.drain)
src/Streamly/Internal/Data/Stream/IsStream/Eliminate.hs−89
@@ -17,8 +17,6 @@ module Streamly.Internal.Data.Stream.IsStream.Eliminate
1717 -- ** Folding
1818 -- ** Right Folds
1919 , foldrM
20− , foldrS
21− , foldrT
2220 , foldr
2321
2422 -- ** Left Folds
@@ -103,9 +101,6 @@ module Streamly.Internal.Data.Stream.IsStream.Eliminate
103101 -- trimming sequences
104102 , stripPrefix
105103 -- , stripInfix
106− , dropPrefix
107− , dropInfix
108− , dropSuffix
109104
110105 -- * Deprecated
111106 , foldx
@@ -120,7 +115,6 @@ where
120115
121116import Control.Monad.Catch (MonadThrow)
122117import Control.Monad.IO.Class (MonadIO(..))
123−import Control.Monad.Trans.Class (MonadTrans(..))
124118import Data.Functor.Identity (Identity (..))
125119import Streamly.Internal.Data.Fold.Types (Fold (..))
126120import Streamly.Internal.Data.Parser (Parser (..))
@@ -198,54 +192,6 @@ uncons m = K.uncons (K.adapt m)
198192foldrM :: Monad m => (a -> m b -> m b) -> m b -> SerialT m a -> m b
199193foldrM = P.foldrM
200194
201−-- | Right fold to a streaming monad.
202−--
203−-- > foldrS S.cons S.nil === id
204−--
205−-- 'foldrS' can be used to perform stateless stream to stream transformations
206−-- like map and filter in general. It can be coupled with a scan to perform
207−-- stateful transformations. However, note that the custom map and filter
208−-- routines can be much more efficient than this due to better stream fusion.
209−--
210−-- >>> S.toList $ S.foldrS S.cons S.nil $ S.fromList [1..5]
211−-- > [1,2,3,4,5]
212−--
213−-- Find if any element in the stream is 'True':
214−--
215−-- >>> 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)
216−-- > [True]
217−--
218−-- Map (+2) on odd elements and filter out the even elements:
219−--
220−-- >>> 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)
221−-- > [3,5,7]
222−--
223−-- 'foldrM' can also be represented in terms of 'foldrS', however, the former
224−-- is much more efficient:
225−--
226−-- > foldrM f z s = runIdentityT $ foldrS (\x xs -> lift $ f x (runIdentityT xs)) (lift z) s
227−--
228−-- /Internal/
229−{-# INLINE foldrS #-}
230−foldrS :: IsStream t => (a -> t m b -> t m b) -> t m b -> t m a -> t m b
231−foldrS = K.foldrS
232−
233−-- | Right fold to a transformer monad. This is the most general right fold
234−-- function. 'foldrS' is a special case of 'foldrT', however 'foldrS'
235−-- implementation can be more efficient:
236−--
237−-- > foldrS = foldrT
238−-- > foldrM f z s = runIdentityT $ foldrT (\x xs -> lift $ f x (runIdentityT xs)) (lift z) s
239−--
240−-- 'foldrT' can be used to translate streamly streams to other transformer
241−-- monads e.g. to a different streaming type.
242−--
243−-- /Internal/
244−{-# INLINE foldrT #-}
245−foldrT :: (IsStream t, Monad m, Monad (s m), MonadTrans s)
246− => (a -> s m b -> s m b) -> s m b -> t m a -> s m b
247−foldrT f z s = S.foldrT f z (toStreamS s)
248−
249195-- | Right fold, lazy for lazy monads and pure streams, and strict for strict
250196-- monads.
251197--
@@ -706,41 +652,6 @@ stripPrefix
706652stripPrefix m1 m2 = fmap fromStreamD <$>
707653 D.stripPrefix (toStreamD m1) (toStreamD m2)
708654
709−-- | Drop prefix from the input stream if present.
710−--
711−-- Space: @O(1)@
712−--
713−-- /Unimplemented/ - Help wanted.
714−{-# INLINE dropPrefix #-}
715−dropPrefix ::
716− -- (Eq a, IsStream t, Monad m) =>
717− t m a -> t m a -> t m a
718−dropPrefix = error "Not implemented yet!"
719−
720−-- | Drop all matching infix from the input stream if present. Infix stream
721−-- may be consumed multiple times.
722−--
723−-- Space: @O(n)@ where n is the length of the infix.
724−--
725−-- /Unimplemented/ - Help wanted.
726−{-# INLINE dropInfix #-}
727−dropInfix ::
728− -- (Eq a, IsStream t, Monad m) =>
729− t m a -> t m a -> t m a
730−dropInfix = error "Not implemented yet!"
731−
732−-- | Drop suffix from the input stream if present. Suffix stream may be
733−-- consumed multiple times.
734−--
735−-- Space: @O(n)@ where n is the length of the suffix.
736−--
737−-- /Unimplemented/ - Help wanted.
738−{-# INLINE dropSuffix #-}
739−dropSuffix ::
740− -- (Eq a, IsStream t, Monad m) =>
741− t m a -> t m a -> t m a
742−dropSuffix = error "Not implemented yet!"
743−
744655------------------------------------------------------------------------------
745656-- Concurrent Application
746657------------------------------------------------------------------------------
src/Streamly/Internal/Data/Stream/IsStream/Transform.hs+94−18
@@ -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