on master help sign in
Move StreamD's construction ops to StreamD.Generate.

- Move takeWhileM, takeWhile to StreamD.Common.

commit34bdeccc6f2512a7d25f67016afd960164a4155c authorPranay Sashank <pranaysashank@composewell.com> dateMon 21 Dec 2020, 13:21 (6 years ago) parentab5648c
3 files changed+113−97
src/Streamly/Internal/Data/Stream/StreamD.hs+1−96 src/Streamly/Internal/Data/Stream/StreamD/Common.hs+24 src/Streamly/Internal/Data/Stream/StreamD/Generate.hs+88−1
src/Streamly/Internal/Data/Stream/StreamD.hs+1−96
@@ -333,58 +333,13 @@ import Prelude hiding
333333 , (!!), scanl, scanl1, concatMap, replicate, enumFromTo, concat
334334 , reverse, iterate, splitAt)
335335import Streamly.Internal.Data.Stream.StreamD.Type
336+import Streamly.Internal.Data.Stream.StreamD.Common (takeWhileM, takeWhile)
336337import Streamly.Internal.Data.Stream.StreamD.Generate
337338import Streamly.Internal.Data.Stream.StreamD.Eliminate
338339import Streamly.Internal.Data.Stream.StreamD.Flatten
339340import Streamly.Internal.Data.Stream.StreamD.SplitGroup
340341import Streamly.Internal.Data.SVar
341342
342−------------------------------------------------------------------------------
343−-- Construction
344−------------------------------------------------------------------------------
345−
346−-- | An empty 'Stream'.
347−{-# INLINE_NORMAL nil #-}
348−nil :: Monad m => Stream m a
349−nil = Stream (\_ _ -> return Stop) ()
350−
351−-- | An empty 'Stream' with a side effect.
352−{-# INLINE_NORMAL nilM #-}
353−nilM :: Monad m => m b -> Stream m a
354−nilM m = Stream (\_ _ -> m >> return Stop) ()
355−
356−{-# INLINE_NORMAL consM #-}
357−consM :: Monad m => m a -> Stream m a -> Stream m a
358−consM m (Stream step state) = Stream step1 Nothing
359− where
360− {-# INLINE_LATE step1 #-}
361− step1 _ Nothing = m >>= \x -> return $ Yield x (Just state)
362− step1 gst (Just st) = do
363− r <- step gst st
364− return $
365− case r of
366− Yield a s -> Yield a (Just s)
367− Skip s -> Skip (Just s)
368− Stop -> Stop
369−
370−-- XXX implement in terms of consM?
371−-- cons x = consM (return x)
372−--
373−-- | Can fuse but has O(n^2) complexity.
374−{-# INLINE_NORMAL cons #-}
375−cons :: Monad m => a -> Stream m a -> Stream m a
376−cons x (Stream step state) = Stream step1 Nothing
377− where
378− {-# INLINE_LATE step1 #-}
379− step1 _ Nothing = return $ Yield x (Just state)
380− step1 gst (Just st) = do
381− r <- step gst st
382− return $
383− case r of
384− Yield a s -> Yield a (Just s)
385− Skip s -> Skip (Just s)
386− Stop -> Stop
387−
388343-------------------------------------------------------------------------------
389344-- Deconstruction
390345-------------------------------------------------------------------------------
@@ -401,38 +356,6 @@ uncons (UnStream step state) = go state
401356 Skip s -> go s
402357 Stop -> return Nothing
403358
404−-- We are assuming that "to" is constrained by the type to be within
405−-- max/min bounds.
406−{-# INLINE enumerateFromToIntegral #-}
407−enumerateFromToIntegral :: (Monad m, Integral a) => a -> a -> Stream m a
408−enumerateFromToIntegral from to =
409− takeWhile (<= to) $ enumerateFromStepIntegral from 1
410−
411−{-# INLINE enumerateFromIntegral #-}
412−enumerateFromIntegral :: (Monad m, Integral a, Bounded a) => a -> Stream m a
413−enumerateFromIntegral from = enumerateFromToIntegral from maxBound
414−
415−-- We cannot write a general function for Num. The only way to write code
416−-- portable between the two is to use a 'Real' constraint and convert between
417−-- Fractional and Integral using fromRational which is horribly slow.
418−{-# INLINE_NORMAL enumerateFromToFractional #-}
419−enumerateFromToFractional
420− :: (Monad m, Fractional a, Ord a)
421− => a -> a -> Stream m a
422−enumerateFromToFractional from to =
423− takeWhile (<= to + 1 / 2) $ enumerateFromStepNum from 1
424−
425−{-# INLINE_NORMAL enumerateFromThenToFractional #-}
426−enumerateFromThenToFractional
427− :: (Monad m, Fractional a, Ord a)
428− => a -> a -> a -> Stream m a
429−enumerateFromThenToFractional from next to =
430− takeWhile predicate $ numFromThen from next
431− where
432− mid = (next - from) / 2
433− predicate | next >= from = (<= to + mid)
434− | otherwise = (>= to + mid)
435−
436359-------------------------------------------------------------------------------
437360-- Hoisting the inner monad
438361-------------------------------------------------------------------------------
@@ -1332,24 +1255,6 @@ rollingMap f = rollingMapM (\x y -> return $ f x y)
13321255-- Filtering
13331256-------------------------------------------------------------------------------
13341257
1335−{-# INLINE_NORMAL takeWhileM #-}
1336−takeWhileM :: Monad m => (a -> m Bool) -> Stream m a -> Stream m a
1337−takeWhileM f (Stream step state) = Stream step' state
1338− where
1339− {-# INLINE_LATE step' #-}
1340− step' gst st = do
1341− r <- step gst st
1342− case r of
1343− Yield x s -> do
1344− b <- f x
1345− return $ if b then Yield x s else Stop
1346− Skip s -> return $ Skip s
1347− Stop -> return Stop
1348−
1349−{-# INLINE takeWhile #-}
1350−takeWhile :: Monad m => (a -> Bool) -> Stream m a -> Stream m a
1351−takeWhile f = takeWhileM (return . f)
1352−
13531258{-# INLINE_NORMAL drop #-}
13541259drop :: Monad m => Int -> Stream m a -> Stream m a
13551260drop n (Stream step state) = Stream step' (state, Just n)
src/Streamly/Internal/Data/Stream/StreamD/Common.hs+24
@@ -15,6 +15,8 @@ module Streamly.Internal.Data.Stream.StreamD.Common
1515 FromSVarState (..)
1616 , fromProducer
1717 , fromPrimIORef
18+ , takeWhileM
19+ , takeWhile
1820 )
1921where
2022
@@ -86,3 +88,25 @@ fromProducer svar = Stream step (FromSVarRead svar)
8688 return Stop
8789
8890 step _ FromSVarInit = undefined
91+
92+-------------------------------------------------------------------------------
93+-- Filtering
94+-------------------------------------------------------------------------------
95+
96+{-# INLINE_NORMAL takeWhileM #-}
97+takeWhileM :: Monad m => (a -> m Bool) -> Stream m a -> Stream m a
98+takeWhileM f (Stream step state) = Stream step' state
99+ where
100+ {-# INLINE_LATE step' #-}
101+ step' gst st = do
102+ r <- step gst st
103+ case r of
104+ Yield x s -> do
105+ b <- f x
106+ return $ if b then Yield x s else Stop
107+ Skip s -> return $ Skip s
108+ Stop -> return Stop
109+
110+{-# INLINE takeWhile #-}
111+takeWhile :: Monad m => (a -> Bool) -> Stream m a -> Stream m a
112+takeWhile f = takeWhileM (return . f)
src/Streamly/Internal/Data/Stream/StreamD/Generate.hs+88−1
@@ -10,9 +10,15 @@
1010
1111module Streamly.Internal.Data.Stream.StreamD.Generate
1212 (
13+ -- * Construction
14+ nil
15+ , nilM
16+ , cons
17+ , consM
18+
1319 -- * Generation
1420 -- ** Unfolds
15− unfoldr
21+ , unfoldr
1622 , unfoldrM
1723 , unfold
1824
@@ -31,12 +37,16 @@ module Streamly.Internal.Data.Stream.StreamD.Generate
3137
3238 -- ** Enumerations
3339 , enumerateFromStepIntegral
40+ , enumerateFromIntegral
3441 , enumerateFromThenIntegral
42+ , enumerateFromToIntegral
3543 , enumerateFromThenToIntegral
3644
3745 , enumerateFromStepNum
3846 , numFrom
3947 , numFromThen
48+ , enumerateFromToFractional
49+ , enumerateFromThenToFractional
4050
4151 -- ** Time
4252 , times
@@ -88,6 +98,51 @@ import Streamly.Internal.Data.Stream.StreamD.Type
8898import Streamly.Internal.Data.Stream.StreamD.Common
8999import Streamly.Internal.Data.SVar
90100
101+------------------------------------------------------------------------------
102+-- Construction
103+------------------------------------------------------------------------------
104+
105+-- | An empty 'Stream'.
106+{-# INLINE_NORMAL nil #-}
107+nil :: Monad m => Stream m a
108+nil = Stream (\_ _ -> return Stop) ()
109+
110+-- | An empty 'Stream' with a side effect.
111+{-# INLINE_NORMAL nilM #-}
112+nilM :: Monad m => m b -> Stream m a
113+nilM m = Stream (\_ _ -> m >> return Stop) ()
114+
115+{-# INLINE_NORMAL consM #-}
116+consM :: Monad m => m a -> Stream m a -> Stream m a
117+consM m (Stream step state) = Stream step1 Nothing
118+ where
119+ {-# INLINE_LATE step1 #-}
120+ step1 _ Nothing = m >>= \x -> return $ Yield x (Just state)
121+ step1 gst (Just st) = do
122+ r <- step gst st
123+ return $
124+ case r of
125+ Yield a s -> Yield a (Just s)
126+ Skip s -> Skip (Just s)
127+ Stop -> Stop
128+
129+-- XXX implement in terms of consM?
130+-- cons x = consM (return x)
131+--
132+-- | Can fuse but has O(n^2) complexity.
133+{-# INLINE_NORMAL cons #-}
134+cons :: Monad m => a -> Stream m a -> Stream m a
135+cons x (Stream step state) = Stream step1 Nothing
136+ where
137+ {-# INLINE_LATE step1 #-}
138+ step1 _ Nothing = return $ Yield x (Just state)
139+ step1 gst (Just st) = do
140+ r <- step gst st
141+ return $
142+ case r of
143+ Yield a s -> Yield a (Just s)
144+ Skip s -> Skip (Just s)
145+ Stop -> Stop
91146
92147------------------------------------------------------------------------------
93148-- Generation by unfold
@@ -240,6 +295,38 @@ enumerateFromThenIntegral from next =
240295 then enumerateFromThenToIntegralUp from next maxBound
241296 else enumerateFromThenToIntegralDn from next minBound
242297
298+-- We are assuming that "to" is constrained by the type to be within
299+-- max/min bounds.
300+{-# INLINE enumerateFromToIntegral #-}
301+enumerateFromToIntegral :: (Monad m, Integral a) => a -> a -> Stream m a
302+enumerateFromToIntegral from to =
303+ takeWhile (<= to) $ enumerateFromStepIntegral from 1
304+
305+{-# INLINE enumerateFromIntegral #-}
306+enumerateFromIntegral :: (Monad m, Integral a, Bounded a) => a -> Stream m a
307+enumerateFromIntegral from = enumerateFromToIntegral from maxBound
308+
309+-- We cannot write a general function for Num. The only way to write code
310+-- portable between the two is to use a 'Real' constraint and convert between
311+-- Fractional and Integral using fromRational which is horribly slow.
312+{-# INLINE_NORMAL enumerateFromToFractional #-}
313+enumerateFromToFractional
314+ :: (Monad m, Fractional a, Ord a)
315+ => a -> a -> Stream m a
316+enumerateFromToFractional from to =
317+ takeWhile (<= to + 1 / 2) $ enumerateFromStepNum from 1
318+
319+{-# INLINE_NORMAL enumerateFromThenToFractional #-}
320+enumerateFromThenToFractional
321+ :: (Monad m, Fractional a, Ord a)
322+ => a -> a -> a -> Stream m a
323+enumerateFromThenToFractional from next to =
324+ takeWhile predicate $ numFromThen from next
325+ where
326+ mid = (next - from) / 2
327+ predicate | next >= from = (<= to + mid)
328+ | otherwise = (>= to + mid)
329+
243330-- For floating point numbers if the increment is less than the precision then
244331-- it just gets lost. Therefore we cannot always increment it correctly by just
245332-- repeated addition.