on master help sign in
Move transformation ops from IsStream's Eliminate to Transform.
dc13710Pranay Sashank
src/Streamly/Internal/Data/Stream/IsStream.hs+19
@@ -619,6 +619,7 @@ import Streamly.Internal.Data.Stream.Combinators
619 , maxRate, constRate)
619 , maxRate, constRate)
620import Streamly.Internal.Data.Stream.Parallel
620import Streamly.Internal.Data.Stream.Parallel
621 ( ParallelT, Parallel, parallely)
621 ( ParallelT, Parallel, parallely)
622+import Streamly.Internal.Data.Stream.Prelude (toStreamS)
622import Streamly.Internal.Data.Stream.StreamK (IsStream((|:), consM), adapt)
623import Streamly.Internal.Data.Stream.StreamK (IsStream((|:), consM), adapt)
623import Streamly.Internal.Data.Stream.Serial
624import Streamly.Internal.Data.Stream.Serial
624 ( SerialT, WSerialT, Serial, WSerial, serially
625 ( SerialT, WSerialT, Serial, WSerial, serially
@@ -645,6 +646,11 @@ import qualified Streamly.Internal.Data.Stream.Parallel as Par
645import qualified Streamly.Internal.Data.Stream.Zip as Z
646import qualified Streamly.Internal.Data.Stream.Zip as Z
646import qualified Data.Heap as H
647import qualified Data.Heap as H
647import qualified Data.Map.Strict as Map
648import 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
648
654
649import Prelude hiding
655import Prelude hiding
650 ( filter, drop, dropWhile, take, takeWhile, zipWith, foldr
656 ( filter, drop, dropWhile, take, takeWhile, zipWith, foldr
@@ -675,6 +681,19 @@ fromCallback setCallback = concatM $ do
675-- Specialized folds
681-- Specialized folds
676------------------------------------------------------------------------------
682------------------------------------------------------------------------------
677
683
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+
678-- |
697-- |
679-- > drainN n = drain . take n
698-- > drainN n = drain . take n
680-- > drainN n = fold (Fold.ltake n Fold.drain)
699-- > 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
17 -- ** Folding
17 -- ** Folding
18 -- ** Right Folds
18 -- ** Right Folds
19 , foldrM
19 , foldrM
20− , foldrS
21− , foldrT
22 , foldr
20 , foldr
23
21
24 -- ** Left Folds
22 -- ** Left Folds
@@ -103,9 +101,6 @@ module Streamly.Internal.Data.Stream.IsStream.Eliminate
103 -- trimming sequences
101 -- trimming sequences
104 , stripPrefix
102 , stripPrefix
105 -- , stripInfix
103 -- , stripInfix
106− , dropPrefix
107− , dropInfix
108− , dropSuffix
109
104
110 -- * Deprecated
105 -- * Deprecated
111 , foldx
106 , foldx
@@ -120,7 +115,6 @@ where
120
115
121import Control.Monad.Catch (MonadThrow)
116import Control.Monad.Catch (MonadThrow)
122import Control.Monad.IO.Class (MonadIO(..))
117import Control.Monad.IO.Class (MonadIO(..))
123−import Control.Monad.Trans.Class (MonadTrans(..))
124import Data.Functor.Identity (Identity (..))
118import Data.Functor.Identity (Identity (..))
125import Streamly.Internal.Data.Fold.Types (Fold (..))
119import Streamly.Internal.Data.Fold.Types (Fold (..))
126import Streamly.Internal.Data.Parser (Parser (..))
120import Streamly.Internal.Data.Parser (Parser (..))
@@ -198,54 +192,6 @@ uncons m = K.uncons (K.adapt m)
198foldrM :: Monad m => (a -> m b -> m b) -> m b -> SerialT m a -> m b
192foldrM :: Monad m => (a -> m b -> m b) -> m b -> SerialT m a -> m b
199foldrM = P.foldrM
193foldrM = P.foldrM
200
194
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−
249-- | Right fold, lazy for lazy monads and pure streams, and strict for strict
195-- | Right fold, lazy for lazy monads and pure streams, and strict for strict
250-- monads.
196-- monads.
251--
197--
@@ -706,41 +652,6 @@ stripPrefix
706stripPrefix m1 m2 = fmap fromStreamD <$>
652stripPrefix m1 m2 = fmap fromStreamD <$>
707 D.stripPrefix (toStreamD m1) (toStreamD m2)
653 D.stripPrefix (toStreamD m1) (toStreamD m2)
708
654
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−
744------------------------------------------------------------------------------
655------------------------------------------------------------------------------
745-- Concurrent Application
656-- Concurrent Application
746------------------------------------------------------------------------------
657------------------------------------------------------------------------------
src/Streamly/Internal/Data/Stream/IsStream/Transform.hs+94−18
@@ -19,7 +19,6 @@ module Streamly.Internal.Data.Stream.IsStream.Transform
19 -- $smapM_Notes
19 -- $smapM_Notes
20
20
21 -- ** Special Maps
21 -- ** Special Maps
22− , mapM_
23 , trace
22 , trace
24 , trace_
23 , trace_
25 , tap
24 , tap
@@ -28,6 +27,11 @@ module Streamly.Internal.Data.Stream.IsStream.Transform
28 , tapRate
27 , tapRate
29 , pollCounts
28 , pollCounts
30
29
30+ -- ** Folding
31+ -- ** Right folds
32+ , foldrS
33+ , foldrT
34+
31 -- ** Scanning
35 -- ** Scanning
32 -- ** Left scans
36 -- ** Left scans
33 , scanl'
37 , scanl'
@@ -135,6 +139,9 @@ module Streamly.Internal.Data.Stream.IsStream.Transform
135 , dropWhileM
139 , dropWhileM
136 -- , dropWhileEnd
140 -- , dropWhileEnd
137 -- , dropAround
141 -- , dropAround
142+ , dropPrefix
143+ , dropInfix
144+ , dropSuffix
138
145
139 -- ** Breaking
146 -- ** Breaking
140
147
@@ -380,23 +387,6 @@ findIndices p m = fromStreamS $ S.findIndices p (toStreamS m)
380elemIndices :: (IsStream t, Eq a, Monad m) => a -> t m a -> t m Int
387elemIndices :: (IsStream t, Eq a, Monad m) => a -> t m a -> t m Int
381elemIndices a = findIndices (== a)
388elemIndices a = findIndices (== a)
382
389
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−
400------------------------------------------------------------------------------
390------------------------------------------------------------------------------
401-- Concurrent Application
391-- Concurrent Application
402------------------------------------------------------------------------------
392------------------------------------------------------------------------------
@@ -804,6 +794,41 @@ dropWhileM p m = fromStreamD $ D.dropWhileM p $ toStreamD m
804dropByTime ::(MonadIO m, IsStream t, TimeUnit64 d) => d -> t m a -> t m a
794dropByTime ::(MonadIO m, IsStream t, TimeUnit64 d) => d -> t m a -> t m a
805dropByTime d = fromStreamD . D.dropByTime d . toStreamD
795dropByTime d = fromStreamD . D.dropByTime d . toStreamD
806
796
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+
807------------------------------------------------------------------------------
832------------------------------------------------------------------------------
808-- Transformation by Mapping
833-- Transformation by Mapping
809------------------------------------------------------------------------------
834------------------------------------------------------------------------------
@@ -2610,6 +2635,57 @@ trace f = mapM (\x -> void (f x) >> return x)
2610trace_ :: (IsStream t, Monad m) => m b -> t m a -> t m a
2635trace_ :: (IsStream t, Monad m) => m b -> t m a -> t m a
2611trace_ eff = Serial.mapM (\x -> eff >> return x)
2636trace_ eff = Serial.mapM (\x -> eff >> return x)
2612
2637
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)
2613
2689
2614------------------------------------------------------------------------------
2690------------------------------------------------------------------------------
2615-- Generalize the underlying monad
2691-- Generalize the underlying monad