on master help sign in
Add filter, list, foldWith to Serial.hs
5a10fb9Harendra Kumar
core/src/Streamly/Internal/Data/Stream/Serial.hs+59−1
@@ -1,4 +1,5 @@
1{-# LANGUAGE UndecidableInstances #-}
1{-# LANGUAGE UndecidableInstances #-}
2+{-# OPTIONS_GHC -Wno-orphans #-}
2
3
3-- |
4-- |
4-- Module : Streamly.Internal.Data.Stream.Serial
5-- Module : Streamly.Internal.Data.Stream.Serial
@@ -35,13 +36,16 @@ module Streamly.Internal.Data.Stream.Serial
35 , repeat
36 , repeat
36 , unfoldrM
37 , unfoldrM
37 , fromList
38 , fromList
39+ , list
38
40
39 -- * Elimination
41 -- * Elimination
40 , toList
42 , toList
43+ , foldWith
41
44
42 -- * Transformation
45 -- * Transformation
43 , map
46 , map
44 , mapM
47 , mapM
48+ , filter
45 , foldFilter
49 , foldFilter
46 )
50 )
47where
51where
@@ -77,7 +81,7 @@ import qualified Streamly.Internal.Data.Stream.StreamD.Transform as D
77import qualified Streamly.Internal.Data.Stream.StreamD.Type as D
81import qualified Streamly.Internal.Data.Stream.StreamD.Type as D
78import qualified Streamly.Internal.Data.Stream.StreamK.Type as K
82import qualified Streamly.Internal.Data.Stream.StreamK.Type as K
79
83
80−import Prelude hiding (map, mapM, repeat)
84+import Prelude hiding (map, mapM, repeat, filter)
81
85
82#include "Instances.hs"
86#include "Instances.hs"
83#include "inline.hs"
87#include "inline.hs"
@@ -256,6 +260,14 @@ toStreamD (SerialT m) = D.fromStreamK m
256fromStreamD :: Monad m => D.Stream m a -> SerialT m a
260fromStreamD :: Monad m => D.Stream m a -> SerialT m a
257fromStreamD m = SerialT $ D.toStreamK m
261fromStreamD m = SerialT $ D.toStreamK m
258
262
263+-- XXX We should only export generation and combinators from this module.
264+--
265+-- | Include only those elements that pass a predicate.
266+--
267+{-# INLINE filter #-}
268+filter :: Monad m => (a -> Bool) -> SerialT m a -> SerialT m a
269+filter p = fromStreamD . D.filter p . toStreamD
270+
259-- | Use a filtering fold on a stream.
271-- | Use a filtering fold on a stream.
260--
272--
261-- > Stream.sum $ Stream.foldFilter (Fold.satisfy (> 5)) $ Stream.fromList [1..10]
273-- > Stream.sum $ Stream.foldFilter (Fold.satisfy (> 5)) $ Stream.fromList [1..10]
@@ -265,6 +277,52 @@ fromStreamD m = SerialT $ D.toStreamK m
265foldFilter :: Monad m => Fold m a (Maybe b) -> SerialT m a -> SerialT m b
277foldFilter :: Monad m => Fold m a (Maybe b) -> SerialT m a -> SerialT m b
266foldFilter p = fromStreamD . D.foldFilter p . toStreamD
278foldFilter p = fromStreamD . D.foldFilter p . toStreamD
267
279
280+-- XXX Renamed to foldWith because SerialT has a Foldable instance having
281+-- method fold.
282+--
283+-- | Fold a stream using the supplied left 'Fold' and reducing the resulting
284+-- expression strictly at each step. The behavior is similar to 'foldl''. A
285+-- 'Fold' can terminate early without consuming the full stream. See the
286+-- documentation of individual 'Fold's for termination behavior.
287+--
288+-- >>> Stream.foldWith Fold.sum (Stream.enumerateFromTo 1 100)
289+-- 5050
290+--
291+-- Folds never fail, therefore, they produce a default value even when no input
292+-- is provided. It means we can always fold an empty stream and get a valid
293+-- result. For example:
294+--
295+-- >>> Stream.foldWith Fold.sum Stream.nil
296+-- 0
297+--
298+-- However, 'foldMany' on an empty stream results in an empty stream.
299+-- Therefore, @Stream.foldWith f@ is not the same as @Stream.head . Stream.foldMany
300+-- f@.
301+--
302+-- @foldWith f = Stream.parse (Parser.fromFold f)@
303+--
304+-- /Pre-release/
305+{-# INLINE foldWith #-}
306+foldWith :: Monad m => Fold m a b -> SerialT m a -> m b
307+foldWith fld m = D.fold fld $ toStreamD m
308+
309+-- XXX Renamed to "list" because fromList is present in IsList instance.
310+--
311+-- |
312+-- @
313+-- fromList = 'Prelude.foldr' 'K.cons' 'K.nil'
314+-- @
315+--
316+-- Construct a stream from a list of pure values. This is more efficient than
317+-- 'K.fromFoldable' for serial streams.
318+--
319+-- @since 0.4.0
320+{-# INLINE_EARLY list #-}
321+list :: Monad m => [a] -> SerialT m a
322+list = fromStreamD . D.fromList
323+{-# RULES "list fallback to StreamK" [1]
324+ forall a. D.toStreamK (D.fromList a) = K.fromFoldable a #-}
325+
268------------------------------------------------------------------------------
326------------------------------------------------------------------------------
269-- WSerialT
327-- WSerialT
270------------------------------------------------------------------------------
328------------------------------------------------------------------------------