on master help sign in
implement direct style mapMaybe and mapMaybeM
162cb8bHarendra Kumar
src/Streamly/Prelude.hs+44−37
@@ -172,6 +172,18 @@ import qualified Streamly.Streams.StreamK as K
172import qualified Streamly.Streams.StreamD as D
172import qualified Streamly.Streams.StreamD as D
173import qualified Streamly.Streams.Serial as Serial
173import qualified Streamly.Streams.Serial as Serial
174
174
175+------------------------------------------------------------------------------
176+-- Conversion to and from direct style stream
177+------------------------------------------------------------------------------
178+
179+{-# INLINE fromStreamD #-}
180+fromStreamD :: (IsStream t, Monad m) => D.Stream m a -> t m a
181+fromStreamD = fromStream . D.toStreamK
182+
183+{-# INLINE toStreamD #-}
184+toStreamD :: (IsStream t, Monad m) => t m a -> D.Stream m a
185+toStreamD = D.fromStreamK . toStream
186+
175------------------------------------------------------------------------------
187------------------------------------------------------------------------------
176-- Deconstruction
188-- Deconstruction
177------------------------------------------------------------------------------
189------------------------------------------------------------------------------
@@ -211,7 +223,7 @@ uncons m =
211-- @since 0.1.0
223-- @since 0.1.0
212{-# INLINE_EARLY unfoldr #-}
224{-# INLINE_EARLY unfoldr #-}
213unfoldr :: (Monad m, IsStream t) => (b -> Maybe (a, b)) -> b -> t m a
225unfoldr :: (Monad m, IsStream t) => (b -> Maybe (a, b)) -> b -> t m a
214−unfoldr step seed = fromStream $ D.toStreamK (D.unfoldr step seed)
226+unfoldr step seed = fromStreamD (D.unfoldr step seed)
215{-# RULES "unfoldr fallback to StreamK" [1]
227{-# RULES "unfoldr fallback to StreamK" [1]
216 forall a b. D.toStreamK (D.unfoldr a b) = K.unfoldr a b #-}
228 forall a b. D.toStreamK (D.unfoldr a b) = K.unfoldr a b #-}
217
229
@@ -253,7 +265,7 @@ unfoldrM = K.unfoldrM
253{-# RULES "unfoldrM serial" unfoldrM = unfoldrMSerial #-}
265{-# RULES "unfoldrM serial" unfoldrM = unfoldrMSerial #-}
254{-# INLINE_EARLY unfoldrMSerial #-}
266{-# INLINE_EARLY unfoldrMSerial #-}
255unfoldrMSerial :: MonadAsync m => (b -> m (Maybe (a, b))) -> b -> SerialT m a
267unfoldrMSerial :: MonadAsync m => (b -> m (Maybe (a, b))) -> b -> SerialT m a
256−unfoldrMSerial step seed = fromStream $ D.toStreamK (D.unfoldrM step seed)
268+unfoldrMSerial step seed = fromStreamD (D.unfoldrM step seed)
257
269
258------------------------------------------------------------------------------
270------------------------------------------------------------------------------
259-- Specialized Generation
271-- Specialized Generation
@@ -333,7 +345,7 @@ iterateM step = go
333-- @since 0.4.0
345-- @since 0.4.0
334{-# INLINE_EARLY fromList #-}
346{-# INLINE_EARLY fromList #-}
335fromList :: (Monad m, IsStream t) => [a] -> t m a
347fromList :: (Monad m, IsStream t) => [a] -> t m a
336−fromList = fromStream . D.toStreamK . D.fromList
348+fromList = fromStreamD . D.fromList
337{-# RULES "fromList fallback to StreamK" [1]
349{-# RULES "fromList fallback to StreamK" [1]
338 forall a. D.toStreamK (D.fromList a) = K.fromFoldable a #-}
350 forall a. D.toStreamK (D.fromList a) = K.fromFoldable a #-}
339
351
@@ -344,7 +356,7 @@ fromList = fromStream . D.toStreamK . D.fromList
344-- @since 0.4.0
356-- @since 0.4.0
345{-# INLINE_EARLY fromListM #-}
357{-# INLINE_EARLY fromListM #-}
346fromListM :: (MonadAsync m, IsStream t) => [m a] -> t m a
358fromListM :: (MonadAsync m, IsStream t) => [m a] -> t m a
347−fromListM = fromStream . D.toStreamK . D.fromListM
359+fromListM = fromStreamD . D.fromListM
348{-# RULES "fromListM fallback to StreamK" [1]
360{-# RULES "fromListM fallback to StreamK" [1]
349 forall a. D.toStreamK (D.fromListM a) = fromFoldableM a #-}
361 forall a. D.toStreamK (D.fromListM a) = fromFoldableM a #-}
350
362
@@ -388,6 +400,19 @@ fromHandle h = fromStream go
388-- Elimination by Folding
400-- Elimination by Folding
389------------------------------------------------------------------------------
401------------------------------------------------------------------------------
390
402
403+-- | Lazy right fold with a monadic step function. For example, to fold a
404+-- stream into a list:
405+--
406+-- @
407+-- >> runIdentity $ foldrM (\\x xs -> return (x : xs)) [] (serially $ fromFoldable [1,2,3])
408+-- [1,2,3]
409+-- @
410+--
411+-- @since 0.2.0
412+{-# INLINE foldrM #-}
413+foldrM :: Monad m => (a -> b -> m b) -> b -> SerialT m a -> m b
414+foldrM step acc m = D.foldrM step acc $ toStreamD m
415+
391-- | Lazy right associative fold. For example, to fold a stream into a list:
416-- | Lazy right associative fold. For example, to fold a stream into a list:
392--
417--
393-- @
418-- @
@@ -402,19 +427,6 @@ foldr :: Monad m => (a -> b -> b) -> b -> SerialT m a -> m b
402-- foldr step acc m = D.foldr step acc $ D.fromStreamK (toStream m)
427-- foldr step acc m = D.foldr step acc $ D.fromStreamK (toStream m)
403foldr f = foldrM (\a b -> return (f a b))
428foldr f = foldrM (\a b -> return (f a b))
404
429
405−-- | Lazy right fold with a monadic step function. For example, to fold a
406−-- stream into a list:
407−--
408−-- @
409−-- >> runIdentity $ foldrM (\\x xs -> return (x : xs)) [] (serially $ fromFoldable [1,2,3])
410−-- [1,2,3]
411−-- @
412−--
413−-- @since 0.2.0
414−{-# INLINE foldrM #-}
415−foldrM :: Monad m => (a -> b -> m b) -> b -> SerialT m a -> m b
416−foldrM step acc m = D.foldrM step acc $ D.fromStreamK (toStream m)
417−
418-- | Strict left fold with an extraction function. Like the standard strict
430-- | Strict left fold with an extraction function. Like the standard strict
419-- left fold, but applies a user supplied extraction function (the third
431-- left fold, but applies a user supplied extraction function (the third
420-- argument) to the folded value at the end. This is designed to work with the
432-- argument) to the folded value at the end. This is designed to work with the
@@ -436,7 +448,7 @@ foldl = foldx
436-- @since 0.2.0
448-- @since 0.2.0
437{-# INLINE foldl' #-}
449{-# INLINE foldl' #-}
438foldl' :: Monad m => (b -> a -> b) -> b -> SerialT m a -> m b
450foldl' :: Monad m => (b -> a -> b) -> b -> SerialT m a -> m b
439−foldl' step begin m = D.foldl' step begin $ D.fromStreamK (toStream m)
451+foldl' step begin m = D.foldl' step begin $ toStreamD m
440
452
441-- XXX replace the recursive "go" with explicit continuations.
453-- XXX replace the recursive "go" with explicit continuations.
442-- | Like 'foldx', but with a monadic step function.
454-- | Like 'foldx', but with a monadic step function.
@@ -455,7 +467,7 @@ foldlM = foldxM
455--
467--
456-- @since 0.2.0
468-- @since 0.2.0
457foldlM' :: Monad m => (b -> a -> m b) -> b -> SerialT m a -> m b
469foldlM' :: Monad m => (b -> a -> m b) -> b -> SerialT m a -> m b
458−foldlM' step begin m = D.foldlM' step begin $ D.fromStreamK (toStream m)
470+foldlM' step begin m = D.foldlM' step begin $ toStreamD m
459
471
460------------------------------------------------------------------------------
472------------------------------------------------------------------------------
461-- Specialized folds
473-- Specialized folds
@@ -512,7 +524,7 @@ tail m =
512-- @since 0.1.1
524-- @since 0.1.1
513{-# INLINE last #-}
525{-# INLINE last #-}
514last :: Monad m => SerialT m a -> m (Maybe a)
526last :: Monad m => SerialT m a -> m (Maybe a)
515−last m = D.last $ D.fromStreamK (toStream m)
527+last m = D.last $ toStreamD m
516
528
517-- | Determine whether the stream is empty.
529-- | Determine whether the stream is empty.
518--
530--
@@ -602,7 +614,7 @@ maximum m = go Nothing (toStream m)
602-- @since 0.1.0
614-- @since 0.1.0
603{-# INLINE mapM_ #-}
615{-# INLINE mapM_ #-}
604mapM_ :: Monad m => (a -> m b) -> SerialT m a -> m ()
616mapM_ :: Monad m => (a -> m b) -> SerialT m a -> m ()
605−mapM_ f m = D.mapM_ f $ D.fromStreamK (toStream m)
617+mapM_ f m = D.mapM_ f $ toStreamD m
606
618
607------------------------------------------------------------------------------
619------------------------------------------------------------------------------
608-- Conversions
620-- Conversions
@@ -613,7 +625,7 @@ mapM_ f m = D.mapM_ f $ D.fromStreamK (toStream m)
613-- @since 0.1.0
625-- @since 0.1.0
614{-# INLINE toList #-}
626{-# INLINE toList #-}
615toList :: Monad m => SerialT m a -> m [a]
627toList :: Monad m => SerialT m a -> m [a]
616−toList m = D.toList $ D.fromStreamK (toStream m)
628+toList m = D.toList $ toStreamD m
617
629
618-- | Write a stream of Strings to an IO Handle.
630-- | Write a stream of Strings to an IO Handle.
619--
631--
@@ -652,8 +664,7 @@ scan = scanx
652-- @since 0.4.0
664-- @since 0.4.0
653{-# INLINE scanlM' #-}
665{-# INLINE scanlM' #-}
654scanlM' :: (IsStream t, Monad m) => (b -> a -> m b) -> b -> t m a -> t m b
666scanlM' :: (IsStream t, Monad m) => (b -> a -> m b) -> b -> t m a -> t m b
655−scanlM' step begin m = fromStream $ D.toStreamK $
667+scanlM' step begin m = fromStreamD $ D.scanlM' step begin $ toStreamD m
656− D.scanlM' step begin $ D.fromStreamK (toStream m)
657
668
658-- | Strict left scan. Like 'foldl'', but returns the folded value at each
669-- | Strict left scan. Like 'foldl'', but returns the folded value at each
659-- step, generating a stream of all intermediate fold results. The first
670-- step, generating a stream of all intermediate fold results. The first
@@ -676,7 +687,7 @@ scanl' step = scanlM' (\a b -> return (step a b))
676#if __GLASGOW_HASKELL__ != 802
687#if __GLASGOW_HASKELL__ != 802
677-- GHC 8.2.2 crashes with this code, when used with "stack"
688-- GHC 8.2.2 crashes with this code, when used with "stack"
678filter :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> t m a
689filter :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> t m a
679−filter p m = fromStream $ D.toStreamK $ D.filter p (D.fromStreamK $ toStream m)
690+filter p m = fromStreamD $ D.filter p $ toStreamD m
680#else
691#else
681filter :: IsStream t => (a -> Bool) -> t m a -> t m a
692filter :: IsStream t => (a -> Bool) -> t m a -> t m a
682filter = K.filter
693filter = K.filter
@@ -687,30 +698,28 @@ filter = K.filter
687-- @since 0.1.0
698-- @since 0.1.0
688{-# INLINE take #-}
699{-# INLINE take #-}
689take :: (IsStream t, Monad m) => Int -> t m a -> t m a
700take :: (IsStream t, Monad m) => Int -> t m a -> t m a
690−take n m = fromStream $ D.toStreamK $ D.take n (D.fromStreamK $ toStream m)
701+take n m = fromStreamD $ D.take n $ toStreamD m
691
702
692-- | End the stream as soon as the predicate fails on an element.
703-- | End the stream as soon as the predicate fails on an element.
693--
704--
694-- @since 0.1.0
705-- @since 0.1.0
695{-# INLINE takeWhile #-}
706{-# INLINE takeWhile #-}
696takeWhile :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> t m a
707takeWhile :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> t m a
697−takeWhile p m = fromStream $ D.toStreamK $
708+takeWhile p m = fromStreamD $ D.takeWhile p $ toStreamD m
698− D.takeWhile p (D.fromStreamK $ toStream m)
699
709
700-- | Same as 'takeWhile' but with a monadic predicate.
710-- | Same as 'takeWhile' but with a monadic predicate.
701--
711--
702-- @since 0.4.0
712-- @since 0.4.0
703{-# INLINE takeWhileM #-}
713{-# INLINE takeWhileM #-}
704takeWhileM :: (IsStream t, Monad m) => (a -> m Bool) -> t m a -> t m a
714takeWhileM :: (IsStream t, Monad m) => (a -> m Bool) -> t m a -> t m a
705−takeWhileM p m = fromStream $ D.toStreamK $
715+takeWhileM p m = fromStreamD $ D.takeWhileM p $ toStreamD m
706− D.takeWhileM p (D.fromStreamK $ toStream m)
707
716
708-- | Discard first 'n' elements from the stream and take the rest.
717-- | Discard first 'n' elements from the stream and take the rest.
709--
718--
710-- @since 0.1.0
719-- @since 0.1.0
711{-# INLINE drop #-}
720{-# INLINE drop #-}
712drop :: (IsStream t, Monad m) => Int -> t m a -> t m a
721drop :: (IsStream t, Monad m) => Int -> t m a -> t m a
713−drop n m = fromStream $ D.toStreamK $ D.drop n (D.fromStreamK $ toStream m)
722+drop n m = fromStreamD $ D.drop n $ toStreamD m
714
723
715-- | Drop elements in the stream as long as the predicate succeeds and then
724-- | Drop elements in the stream as long as the predicate succeeds and then
716-- take the rest of the stream.
725-- take the rest of the stream.
@@ -718,16 +727,14 @@ drop n m = fromStream $ D.toStreamK $ D.drop n (D.fromStreamK $ toStream m)
718-- @since 0.1.0
727-- @since 0.1.0
719{-# INLINE dropWhile #-}
728{-# INLINE dropWhile #-}
720dropWhile :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> t m a
729dropWhile :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> t m a
721−dropWhile p m = fromStream $ D.toStreamK $
730+dropWhile p m = fromStreamD $ D.dropWhile p $ toStreamD m
722− D.dropWhile p (D.fromStreamK $ toStream m)
723
731
724-- | Same as 'dropWhile' but with a monadic predicate.
732-- | Same as 'dropWhile' but with a monadic predicate.
725--
733--
726-- @since 0.4.0
734-- @since 0.4.0
727{-# INLINE dropWhileM #-}
735{-# INLINE dropWhileM #-}
728dropWhileM :: (IsStream t, Monad m) => (a -> m Bool) -> t m a -> t m a
736dropWhileM :: (IsStream t, Monad m) => (a -> m Bool) -> t m a -> t m a
729−dropWhileM p m = fromStream $ D.toStreamK $
737+dropWhileM p m = fromStreamD $ D.dropWhileM p $ toStreamD m
730− D.dropWhileM p (D.fromStreamK $ toStream m)
731
738
732------------------------------------------------------------------------------
739------------------------------------------------------------------------------
733-- Transformation by Mapping
740-- Transformation by Mapping
@@ -783,8 +790,8 @@ sequence = K.sequence
783--
790--
784-- @since 0.3.0
791-- @since 0.3.0
785{-# INLINE mapMaybe #-}
792{-# INLINE mapMaybe #-}
786−mapMaybe :: IsStream t => (a -> Maybe b) -> t m a -> t m b
793+mapMaybe :: (IsStream t, Monad m) => (a -> Maybe b) -> t m a -> t m b
787−mapMaybe = K.mapMaybe
794+mapMaybe f m = fromStreamD $ D.mapMaybe f $ toStreamD m
788
795
789-- | Like 'mapMaybe' but maps a monadic function.
796-- | Like 'mapMaybe' but maps a monadic function.
790--
797--
src/Streamly/Streams/StreamD.hs+17
@@ -101,9 +101,14 @@ module Streamly.Streams.StreamD
101 -- * Mapping
101 -- * Mapping
102 , map
102 , map
103 , mapM
103 , mapM
104+
105+ -- ** Map and Filter
106+ , mapMaybe
107+ , mapMaybeM
104 )
108 )
105where
109where
106
110
111+import Data.Maybe (fromJust, isJust)
107import GHC.Types ( SPEC(..) )
112import GHC.Types ( SPEC(..) )
108import Prelude
113import Prelude
109 hiding (map, mapM, mapM_, repeat, foldr, last, take, filter,
114 hiding (map, mapM, mapM_, repeat, foldr, last, take, filter,
@@ -495,6 +500,18 @@ mapM f (Stream step state) = Stream step' state
495map :: Monad m => (a -> b) -> Stream m a -> Stream m b
500map :: Monad m => (a -> b) -> Stream m a -> Stream m b
496map f = mapM (return . f)
501map f = mapM (return . f)
497
502
503+------------------------------------------------------------------------------
504+-- Transformation by Map and Filter
505+------------------------------------------------------------------------------
506+
507+{-# INLINE_NORMAL mapMaybe #-}
508+mapMaybe :: Monad m => (a -> Maybe b) -> Stream m a -> Stream m b
509+mapMaybe f = fmap fromJust . filter isJust . map f
510+
511+{-# INLINE_NORMAL mapMaybeM #-}
512+mapMaybeM :: Monad m => (a -> m (Maybe b)) -> Stream m a -> Stream m b
513+mapMaybeM f = fmap fromJust . filter isJust . mapM f
514+
498------------------------------------------------------------------------------
515------------------------------------------------------------------------------
499-- Instances
516-- Instances
500------------------------------------------------------------------------------
517------------------------------------------------------------------------------