on master help sign in
Add flag to switch stream backend to streamk
c7d2f9eHarendra Kumar
.travis.yml+3
@@ -117,6 +117,9 @@ matrix:
117 - env: BUILD=cabal-new GHCVER=8.4.3 GHC_OPTIONS=""
117 - env: BUILD=cabal-new GHCVER=8.4.3 GHC_OPTIONS=""
118 addons: {apt: {packages: [cabal-install-2.2,ghc-8.4.3], sources: [hvr-ghc]}}
118 addons: {apt: {packages: [cabal-install-2.2,ghc-8.4.3], sources: [hvr-ghc]}}
119
119
120+ - env: BUILD=cabal-new GHCVER=8.4.3 GHC_OPTIONS="" CABAL_NEWBUILD_OPTIONS="--flags=streamk"
121+ addons: {apt: {packages: [cabal-install-2.2,ghc-8.4.3], sources: [hvr-ghc]}}
122+
120 - env: BUILD=cabal-new GHCVER=head GHC_OPTIONS=""
123 - env: BUILD=cabal-new GHCVER=head GHC_OPTIONS=""
121 addons: {apt: {packages: [cabal-install-head,ghc-head], sources: [hvr-ghc]}}
124 addons: {apt: {packages: [cabal-install-head,ghc-head], sources: [hvr-ghc]}}
122
125
benchmark/LinearOps.hs+2−2
@@ -112,9 +112,9 @@ sourceFromFoldableM :: (S.IsStream t, S.MonadAsync m) => Int -> t m Int
112sourceFromFoldableM n = S.fromFoldableM (Prelude.fmap return [n..n+value])
112sourceFromFoldableM n = S.fromFoldableM (Prelude.fmap return [n..n+value])
113
113
114{-# INLINE sourceFoldMapWith #-}
114{-# INLINE sourceFoldMapWith #-}
115−sourceFoldMapWith :: (S.IsStream t, Monad (t m), S.Semigroup (t m Int))
115+sourceFoldMapWith :: (S.IsStream t, S.Semigroup (t m Int))
116 => Int -> t m Int
116 => Int -> t m Int
117−sourceFoldMapWith n = S.foldMapWith (S.<>) return [n..n+value]
117+sourceFoldMapWith n = S.foldMapWith (S.<>) S.yield [n..n+value]
118
118
119{-# INLINE sourceFoldMapWithM #-}
119{-# INLINE sourceFoldMapWithM #-}
120sourceFoldMapWithM :: (S.IsStream t, Monad m, S.Semigroup (t m Int))
120sourceFoldMapWithM :: (S.IsStream t, Monad m, S.Semigroup (t m Int))
src/Streamly/Prelude.hs+44−20
@@ -71,8 +71,8 @@ module Streamly.Prelude
71
71
72 -- ** Conversions
72 -- ** Conversions
73 -- | Transform an input structure into a stream.
73 -- | Transform an input structure into a stream.
74− , K.yield
74+ , yield
75− , K.yieldM
75+ , yieldM
76 , fromList
76 , fromList
77 , fromListM
77 , fromListM
78 , K.fromFoldable
78 , K.fromFoldable
@@ -170,12 +170,28 @@ import Streamly.Streams.Zip (zipWith, zipWithM, zipAsyncWith, zipAsyncWithM)
170
170
171import qualified Streamly.Streams.StreamK as K
171import qualified Streamly.Streams.StreamK as K
172import qualified Streamly.Streams.StreamD as D
172import qualified Streamly.Streams.StreamD as D
173+
174+#ifdef USE_STREAMK_ONLY
175+import qualified Streamly.Streams.StreamK as S
176+#else
177+import qualified Streamly.Streams.StreamD as S
178+#endif
179+
173import qualified Streamly.Streams.Serial as Serial
180import qualified Streamly.Streams.Serial as Serial
174
181
175------------------------------------------------------------------------------
182------------------------------------------------------------------------------
176-- Conversion to and from direct style stream
183-- Conversion to and from direct style stream
177------------------------------------------------------------------------------
184------------------------------------------------------------------------------
178
185
186+-- These definitions are dependent on what is imported as S
187+{-# INLINE fromStreamS #-}
188+fromStreamS :: (IsStream t, Monad m) => S.Stream m a -> t m a
189+fromStreamS = fromStream . S.toStreamK
190+
191+{-# INLINE toStreamS #-}
192+toStreamS :: (IsStream t, Monad m) => t m a -> S.Stream m a
193+toStreamS = S.fromStreamK . toStream
194+
179{-# INLINE fromStreamD #-}
195{-# INLINE fromStreamD #-}
180fromStreamD :: (IsStream t, Monad m) => D.Stream m a -> t m a
196fromStreamD :: (IsStream t, Monad m) => D.Stream m a -> t m a
181fromStreamD = fromStream . D.toStreamK
197fromStreamD = fromStream . D.toStreamK
@@ -223,9 +239,9 @@ uncons m =
223-- @since 0.1.0
239-- @since 0.1.0
224{-# INLINE_EARLY unfoldr #-}
240{-# INLINE_EARLY unfoldr #-}
225unfoldr :: (Monad m, IsStream t) => (b -> Maybe (a, b)) -> b -> t m a
241unfoldr :: (Monad m, IsStream t) => (b -> Maybe (a, b)) -> b -> t m a
226−unfoldr step seed = fromStreamD (D.unfoldr step seed)
242+unfoldr step seed = fromStreamS (S.unfoldr step seed)
227{-# RULES "unfoldr fallback to StreamK" [1]
243{-# RULES "unfoldr fallback to StreamK" [1]
228− forall a b. D.toStreamK (D.unfoldr a b) = K.unfoldr a b #-}
244+ forall a b. S.toStreamK (S.unfoldr a b) = K.unfoldr a b #-}
229
245
230-- | Build a stream by unfolding a /monadic/ step function starting from a
246-- | Build a stream by unfolding a /monadic/ step function starting from a
231-- seed. The step function returns the next element in the stream and the next
247-- seed. The step function returns the next element in the stream and the next
@@ -265,12 +281,20 @@ unfoldrM = K.unfoldrM
265{-# RULES "unfoldrM serial" unfoldrM = unfoldrMSerial #-}
281{-# RULES "unfoldrM serial" unfoldrM = unfoldrMSerial #-}
266{-# INLINE_EARLY unfoldrMSerial #-}
282{-# INLINE_EARLY unfoldrMSerial #-}
267unfoldrMSerial :: MonadAsync m => (b -> m (Maybe (a, b))) -> b -> SerialT m a
283unfoldrMSerial :: MonadAsync m => (b -> m (Maybe (a, b))) -> b -> SerialT m a
268−unfoldrMSerial step seed = fromStreamD (D.unfoldrM step seed)
284+unfoldrMSerial step seed = fromStreamS (S.unfoldrM step seed)
269
285
270------------------------------------------------------------------------------
286------------------------------------------------------------------------------
271-- Specialized Generation
287-- Specialized Generation
272------------------------------------------------------------------------------
288------------------------------------------------------------------------------
273
289
290+{-# INLINE yield #-}
291+yield :: IsStream t => a -> t m a
292+yield a = K.yield a
293+
294+{-# INLINE yieldM #-}
295+yieldM :: (Monad m, IsStream t) => m a -> t m a
296+yieldM m = K.yieldM m
297+
274-- | Generate a stream by performing a monadic action @n@ times.
298-- | Generate a stream by performing a monadic action @n@ times.
275--
299--
276--
300--
@@ -345,9 +369,9 @@ iterateM step = go
345-- @since 0.4.0
369-- @since 0.4.0
346{-# INLINE_EARLY fromList #-}
370{-# INLINE_EARLY fromList #-}
347fromList :: (Monad m, IsStream t) => [a] -> t m a
371fromList :: (Monad m, IsStream t) => [a] -> t m a
348−fromList = fromStreamD . D.fromList
372+fromList = fromStreamS . S.fromList
349{-# RULES "fromList fallback to StreamK" [1]
373{-# RULES "fromList fallback to StreamK" [1]
350− forall a. D.toStreamK (D.fromList a) = K.fromFoldable a #-}
374+ forall a. S.toStreamK (S.fromList a) = K.fromFoldable a #-}
351
375
352-- | Construct a stream from a list containing monadic actions. This can be
376-- | Construct a stream from a list containing monadic actions. This can be
353-- more efficient than 'fromFoldableM' especially for serial streams as it can
377-- more efficient than 'fromFoldableM' especially for serial streams as it can
@@ -411,7 +435,7 @@ fromHandle h = fromStream go
411-- @since 0.2.0
435-- @since 0.2.0
412{-# INLINE foldrM #-}
436{-# INLINE foldrM #-}
413foldrM :: Monad m => (a -> b -> m b) -> b -> SerialT m a -> m b
437foldrM :: Monad m => (a -> b -> m b) -> b -> SerialT m a -> m b
414−foldrM step acc m = D.foldrM step acc $ toStreamD m
438+foldrM step acc m = S.foldrM step acc $ toStreamS m
415
439
416-- | Lazy right associative fold. For example, to fold a stream into a list:
440-- | Lazy right associative fold. For example, to fold a stream into a list:
417--
441--
@@ -424,7 +448,7 @@ foldrM step acc m = D.foldrM step acc $ toStreamD m
424{-# INLINE foldr #-}
448{-# INLINE foldr #-}
425foldr :: Monad m => (a -> b -> b) -> b -> SerialT m a -> m b
449foldr :: Monad m => (a -> b -> b) -> b -> SerialT m a -> m b
426-- XXX somehow this definition does not perform well, need to investigate
450-- XXX somehow this definition does not perform well, need to investigate
427−-- foldr step acc m = D.foldr step acc $ D.fromStreamK (toStream m)
451+-- foldr step acc m = S.foldr step acc $ S.fromStreamK (toStream m)
428foldr f = foldrM (\a b -> return (f a b))
452foldr f = foldrM (\a b -> return (f a b))
429
453
430-- | Strict left fold with an extraction function. Like the standard strict
454-- | Strict left fold with an extraction function. Like the standard strict
@@ -448,7 +472,7 @@ foldl = foldx
448-- @since 0.2.0
472-- @since 0.2.0
449{-# INLINE foldl' #-}
473{-# INLINE foldl' #-}
450foldl' :: Monad m => (b -> a -> b) -> b -> SerialT m a -> m b
474foldl' :: Monad m => (b -> a -> b) -> b -> SerialT m a -> m b
451−foldl' step begin m = D.foldl' step begin $ toStreamD m
475+foldl' step begin m = S.foldl' step begin $ toStreamS m
452
476
453-- XXX replace the recursive "go" with explicit continuations.
477-- XXX replace the recursive "go" with explicit continuations.
454-- | Like 'foldx', but with a monadic step function.
478-- | Like 'foldx', but with a monadic step function.
@@ -467,7 +491,7 @@ foldlM = foldxM
467--
491--
468-- @since 0.2.0
492-- @since 0.2.0
469foldlM' :: Monad m => (b -> a -> m b) -> b -> SerialT m a -> m b
493foldlM' :: Monad m => (b -> a -> m b) -> b -> SerialT m a -> m b
470−foldlM' step begin m = D.foldlM' step begin $ toStreamD m
494+foldlM' step begin m = S.foldlM' step begin $ toStreamS m
471
495
472------------------------------------------------------------------------------
496------------------------------------------------------------------------------
473-- Specialized folds
497-- Specialized folds
@@ -524,7 +548,7 @@ tail m =
524-- @since 0.1.1
548-- @since 0.1.1
525{-# INLINE last #-}
549{-# INLINE last #-}
526last :: Monad m => SerialT m a -> m (Maybe a)
550last :: Monad m => SerialT m a -> m (Maybe a)
527−last m = D.last $ toStreamD m
551+last m = S.last $ toStreamS m
528
552
529-- | Determine whether the stream is empty.
553-- | Determine whether the stream is empty.
530--
554--
@@ -614,7 +638,7 @@ maximum m = go Nothing (toStream m)
614-- @since 0.1.0
638-- @since 0.1.0
615{-# INLINE mapM_ #-}
639{-# INLINE mapM_ #-}
616mapM_ :: Monad m => (a -> m b) -> SerialT m a -> m ()
640mapM_ :: Monad m => (a -> m b) -> SerialT m a -> m ()
617−mapM_ f m = D.mapM_ f $ toStreamD m
641+mapM_ f m = S.mapM_ f $ toStreamS m
618
642
619------------------------------------------------------------------------------
643------------------------------------------------------------------------------
620-- Conversions
644-- Conversions
@@ -625,7 +649,7 @@ mapM_ f m = D.mapM_ f $ toStreamD m
625-- @since 0.1.0
649-- @since 0.1.0
626{-# INLINE toList #-}
650{-# INLINE toList #-}
627toList :: Monad m => SerialT m a -> m [a]
651toList :: Monad m => SerialT m a -> m [a]
628−toList m = D.toList $ toStreamD m
652+toList m = S.toList $ toStreamS m
629
653
630-- | Write a stream of Strings to an IO Handle.
654-- | Write a stream of Strings to an IO Handle.
631--
655--
@@ -687,7 +711,7 @@ scanl' step = scanlM' (\a b -> return (step a b))
687#if __GLASGOW_HASKELL__ != 802
711#if __GLASGOW_HASKELL__ != 802
688-- GHC 8.2.2 crashes with this code, when used with "stack"
712-- GHC 8.2.2 crashes with this code, when used with "stack"
689filter :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> t m a
713filter :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> t m a
690−filter p m = fromStreamD $ D.filter p $ toStreamD m
714+filter p m = fromStreamS $ S.filter p $ toStreamS m
691#else
715#else
692filter :: IsStream t => (a -> Bool) -> t m a -> t m a
716filter :: IsStream t => (a -> Bool) -> t m a -> t m a
693filter = K.filter
717filter = K.filter
@@ -698,14 +722,14 @@ filter = K.filter
698-- @since 0.1.0
722-- @since 0.1.0
699{-# INLINE take #-}
723{-# INLINE take #-}
700take :: (IsStream t, Monad m) => Int -> t m a -> t m a
724take :: (IsStream t, Monad m) => Int -> t m a -> t m a
701−take n m = fromStreamD $ D.take n $ toStreamD m
725+take n m = fromStreamS $ S.take n $ toStreamS m
702
726
703-- | End the stream as soon as the predicate fails on an element.
727-- | End the stream as soon as the predicate fails on an element.
704--
728--
705-- @since 0.1.0
729-- @since 0.1.0
706{-# INLINE takeWhile #-}
730{-# INLINE takeWhile #-}
707takeWhile :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> t m a
731takeWhile :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> t m a
708−takeWhile p m = fromStreamD $ D.takeWhile p $ toStreamD m
732+takeWhile p m = fromStreamS $ S.takeWhile p $ toStreamS m
709
733
710-- | Same as 'takeWhile' but with a monadic predicate.
734-- | Same as 'takeWhile' but with a monadic predicate.
711--
735--
@@ -719,7 +743,7 @@ takeWhileM p m = fromStreamD $ D.takeWhileM p $ toStreamD m
719-- @since 0.1.0
743-- @since 0.1.0
720{-# INLINE drop #-}
744{-# INLINE drop #-}
721drop :: (IsStream t, Monad m) => Int -> t m a -> t m a
745drop :: (IsStream t, Monad m) => Int -> t m a -> t m a
722−drop n m = fromStreamD $ D.drop n $ toStreamD m
746+drop n m = fromStreamS $ S.drop n $ toStreamS m
723
747
724-- | Drop elements in the stream as long as the predicate succeeds and then
748-- | Drop elements in the stream as long as the predicate succeeds and then
725-- take the rest of the stream.
749-- take the rest of the stream.
@@ -727,7 +751,7 @@ drop n m = fromStreamD $ D.drop n $ toStreamD m
727-- @since 0.1.0
751-- @since 0.1.0
728{-# INLINE dropWhile #-}
752{-# INLINE dropWhile #-}
729dropWhile :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> t m a
753dropWhile :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> t m a
730−dropWhile p m = fromStreamD $ D.dropWhile p $ toStreamD m
754+dropWhile p m = fromStreamS $ S.dropWhile p $ toStreamS m
731
755
732-- | Same as 'dropWhile' but with a monadic predicate.
756-- | Same as 'dropWhile' but with a monadic predicate.
733--
757--
@@ -791,7 +815,7 @@ sequence = K.sequence
791-- @since 0.3.0
815-- @since 0.3.0
792{-# INLINE mapMaybe #-}
816{-# INLINE mapMaybe #-}
793mapMaybe :: (IsStream t, Monad m) => (a -> Maybe b) -> t m a -> t m b
817mapMaybe :: (IsStream t, Monad m) => (a -> Maybe b) -> t m a -> t m b
794−mapMaybe f m = fromStreamD $ D.mapMaybe f $ toStreamD m
818+mapMaybe f m = fromStreamS $ S.mapMaybe f $ toStreamS m
795
819
796-- | Like 'mapMaybe' but maps a monadic function.
820-- | Like 'mapMaybe' but maps a monadic function.
797--
821--
src/Streamly/Streams/StreamK.hs+16
@@ -60,6 +60,8 @@ module Streamly.Streams.StreamK
60 , yield
60 , yield
61 , yieldM
61 , yieldM
62 , fromFoldable
62 , fromFoldable
63+ , fromList
64+ , fromStreamK
63
65
64 -- * Elimination
66 -- * Elimination
65 -- ** General Folds
67 -- ** General Folds
@@ -82,6 +84,7 @@ module Streamly.Streams.StreamK
82
84
83 -- ** Conversions
85 -- ** Conversions
84 , toList
86 , toList
87+ , toStreamK
85
88
86 -- * Transformation
89 -- * Transformation
87 -- ** By folding (scans)
90 -- ** By folding (scans)
@@ -360,6 +363,7 @@ unfoldrM step = go
360-- Faster than yieldM because there is no bind. Usually we can construct a
363-- Faster than yieldM because there is no bind. Usually we can construct a
361-- stream from a pure value using "pure" in an applicative, however in case of
364-- stream from a pure value using "pure" in an applicative, however in case of
362-- Zip streams pure creates an infinite stream.
365-- Zip streams pure creates an infinite stream.
366+--
363-- | Create a singleton stream from a pure value. In monadic streams, 'pure' or
367-- | Create a singleton stream from a pure value. In monadic streams, 'pure' or
364-- 'return' can be used in place of 'yield', however, in Zip applicative
368-- 'return' can be used in place of 'yield', however, in Zip applicative
365-- streams 'pure' is equivalent to 'repeat'.
369-- streams 'pure' is equivalent to 'repeat'.
@@ -407,6 +411,14 @@ repeat a = let x = cons a x in x
407fromFoldable :: (IsStream t, Foldable f) => f a -> t m a
411fromFoldable :: (IsStream t, Foldable f) => f a -> t m a
408fromFoldable = Prelude.foldr cons nil
412fromFoldable = Prelude.foldr cons nil
409
413
414+{-# INLINE fromList #-}
415+fromList :: IsStream t => [a] -> t m a
416+fromList = fromFoldable
417+
418+{-# INLINE fromStreamK #-}
419+fromStreamK :: Stream m a -> Stream m a
420+fromStreamK = id
421+
410-------------------------------------------------------------------------------
422-------------------------------------------------------------------------------
411-- Elimination by Folding
423-- Elimination by Folding
412-------------------------------------------------------------------------------
424-------------------------------------------------------------------------------
@@ -554,6 +566,10 @@ mapM_ f m = go (toStream m)
554toList :: (IsStream t, Monad m) => t m a -> m [a]
566toList :: (IsStream t, Monad m) => t m a -> m [a]
555toList = foldr (:) []
567toList = foldr (:) []
556
568
569+{-# INLINE toStreamK #-}
570+toStreamK :: Stream m a -> Stream m a
571+toStreamK = id
572+
557-------------------------------------------------------------------------------
573-------------------------------------------------------------------------------
558-- Transformation by folding (Scans)
574-- Transformation by folding (Scans)
559-------------------------------------------------------------------------------
575-------------------------------------------------------------------------------
streamly.cabal+8
@@ -97,6 +97,11 @@ flag no-fusion
97 manual: True
97 manual: True
98 default: False
98 default: False
99
99
100+flag streamk
101+ description: Use CPS style streams when possible
102+ manual: True
103+ default: False
104+
100flag examples
105flag examples
101 description: Build including examples
106 description: Build including examples
102 manual: True
107 manual: True
@@ -146,6 +151,9 @@ library
146 default-language: Haskell2010
151 default-language: Haskell2010
147 ghc-options: -Wall
152 ghc-options: -Wall
148
153
154+ if flag(streamk)
155+ cpp-options: -DUSE_STREAMK_ONLY
156+
149 if flag(no-fusion)
157 if flag(no-fusion)
150 cpp-options: -DDISABLE_FUSION
158 cpp-options: -DDISABLE_FUSION
151
159