2-- Module : Streamly.Internal.Data.Stream.StreamD.Generate
3-- Copyright : (c) 2020 Composewell Technologies and Contributors
4-- (c) Roman Leshchinskiy 2008-2010
5-- License : BSD-3-Clause
6-- Maintainer : streamly@composewell.com
7-- Stability : experimental
10-- Prefer unfolds ("Streamly.Internal.Data.Unfold") over the combinators in
11-- this module. They are more powerful and efficient as they can be transformed
12-- and composed on the input side efficiently and they can fuse in nested
13-- operations (e.g. unfoldMany). All the combinators in this module can be
14-- expressed using unfolds with the same efficiency.
16-- Operations in this module that are not in "Streamly.Internal.Data.Unfold":
17-- generate, times, fromPrimIORef.
19-- We should plan to replace this module with "Streamly.Internal.Data.Unfold"
22-- A few combinators in this module have been adapted from the vector package
23-- (c) Roman Leshchinskiy. See the notes in specific combinators.
25module Streamly.Internal.Data.Stream.StreamD.Generate
49 , enumerateFromStepIntegral
50 , enumerateFromIntegral
51 , enumerateFromThenIntegral
52 , enumerateFromToIntegral
53 , enumerateFromThenToIntegral
55 , enumerateFromStepNum
57 , enumerateFromThenNum
58 , enumerateFromToFractional
59 , enumerateFromThenToFractional
65 -- | Generate a monadic stream from a seed.
76 -- | Transform an input structure into a stream.
78 -- Note: Direct style stream does not support @fromFoldable@.
92#include "ArrayMacros.h"
94import Control.Monad.IO.Class (MonadIO(..))
95import Foreign.Ptr (Ptr, plusPtr)
96import Foreign.Storable (Storable (peek), sizeOf)
97import Streamly.Internal.Data.Time.Clock
98 (Clock(Monotonic), asyncClock, readClock)
99import Streamly.Internal.Data.Time.Units
100 (toAbsTime, AbsTime, toRelTime64, RelTime64)
102#ifdef USE_UNFOLDS_EVERYWHERE
103import qualified Streamly.Internal.Data.Unfold as Unfold
104import qualified Streamly.Internal.Data.Unfold.Enumeration as Unfold
107import Prelude hiding (iterate, repeat, replicate, takeWhile)
108import Streamly.Internal.Data.Stream.StreamD.Type
110------------------------------------------------------------------------------
112------------------------------------------------------------------------------
114-- | An empty 'Stream'.
115{-# INLINE_NORMAL nil #-}
116nil :: Monad m => Stream m a
117nil = Stream (\_ _ -> return Stop) ()
119-- XXX implement in terms of consM?
120-- cons x = consM (return x)
122-- | Can fuse but has O(n^2) complexity.
123{-# INLINE_NORMAL cons #-}
124cons :: Monad m => a -> Stream m a -> Stream m a
125cons x (Stream step state) = Stream step1 Nothing
127 {-# INLINE_LATE step1 #-}
128 step1 _ Nothing = return $ Yield x (Just state)
129 step1 gst (Just st) = do
133 Yield a s -> Yield a (Just s)
134 Skip s -> Skip (Just s)
137------------------------------------------------------------------------------
139------------------------------------------------------------------------------
141-- Adapted from vector package
142{-# INLINE_NORMAL unfoldrM #-}
143unfoldrM :: Monad m => (s -> m (Maybe (a, s))) -> s -> Stream m a
144#ifdef USE_UNFOLDS_EVERYWHERE
145unfoldrM next = unfold (Unfold.unfoldrM next)
147unfoldrM next = Stream step
149 {-# INLINE_LATE step #-}
153 Just (x, s) -> Yield x s
157{-# INLINE_LATE unfoldr #-}
158unfoldr :: Monad m => (s -> Maybe (a, s)) -> s -> Stream m a
159unfoldr f = unfoldrM (return . f)
161------------------------------------------------------------------------------
163------------------------------------------------------------------------------
165{-# INLINE_NORMAL repeatM #-}
166repeatM :: Monad m => m a -> Stream m a
167#ifdef USE_UNFOLDS_EVERYWHERE
168repeatM = unfold Unfold.repeatM
170repeatM x = Stream (\_ _ -> x >>= \r -> return $ Yield r ()) ()
173{-# INLINE_NORMAL repeat #-}
174repeat :: Monad m => a -> Stream m a
175#ifdef USE_UNFOLDS_EVERYWHERE
176repeat x = repeatM (pure x)
178repeat x = Stream (\_ _ -> return $ Yield x ()) ()
181-- Adapted from the vector package
182{-# INLINE_NORMAL replicateM #-}
183replicateM :: forall m a. Monad m => Int -> m a -> Stream m a
184#ifdef USE_UNFOLDS_EVERYWHERE
185replicateM n p = unfold Unfold.replicateM (n, p)
187replicateM n p = Stream step n
189 {-# INLINE_LATE step #-}
191 | i <= 0 = return Stop
194 return $ Yield x (i - 1)
197{-# INLINE_NORMAL replicate #-}
198replicate :: Monad m => Int -> a -> Stream m a
199replicate n x = replicateM n (return x)
201------------------------------------------------------------------------------
203------------------------------------------------------------------------------
205-- | For floating point numbers if the increment is less than the precision then
206-- it just gets lost. Therefore we cannot always increment it correctly by just
208-- 9007199254740992 + 1 + 1 :: Double => 9.007199254740992e15
209-- 9007199254740992 + 2 :: Double => 9.007199254740994e15
211-- Instead we accumulate the increment counter and compute the increment
212-- every time before adding it to the starting number.
214-- This works for Integrals as well as floating point numbers, but
215-- enumerateFromStepIntegral is faster for integrals.
216{-# INLINE_NORMAL enumerateFromStepNum #-}
217enumerateFromStepNum :: (Monad m, Num a) => a -> a -> Stream m a
218#ifdef USE_UNFOLDS_EVERYWHERE
219enumerateFromStepNum from stride =
220 unfold Unfold.enumerateFromStepNum (from, stride)
222enumerateFromStepNum from stride = Stream step 0
224 {-# INLINE_LATE step #-}
225 step _ !i = return $ (Yield $! (from + i * stride)) $! (i + 1)
228{-# INLINE_NORMAL enumerateFromNum #-}
229enumerateFromNum :: (Monad m, Num a) => a -> Stream m a
230enumerateFromNum from = enumerateFromStepNum from 1
232{-# INLINE_NORMAL enumerateFromThenNum #-}
233enumerateFromThenNum :: (Monad m, Num a) => a -> a -> Stream m a
234enumerateFromThenNum from next = enumerateFromStepNum from (next - from)
236------------------------------------------------------------------------------
237-- Enumeration of Integrals
238------------------------------------------------------------------------------
240#ifndef USE_UNFOLDS_EVERYWHERE
241data EnumState a = EnumInit | EnumYield a a a | EnumStop
243{-# INLINE_NORMAL enumerateFromThenToIntegralUp #-}
244enumerateFromThenToIntegralUp
245 :: (Monad m, Integral a)
246 => a -> a -> a -> Stream m a
247enumerateFromThenToIntegralUp from next to = Stream step EnumInit
249 {-# INLINE_LATE step #-}
255 else Yield from EnumStop
256 else -- from <= next <= to
257 let stride = next - from
258 in Skip $ EnumYield from stride (to - stride)
260 step _ (EnumYield x stride toMinus) =
263 then Yield x EnumStop
264 else Yield x $ EnumYield (x + stride) stride toMinus
266 step _ EnumStop = return Stop
268{-# INLINE_NORMAL enumerateFromThenToIntegralDn #-}
269enumerateFromThenToIntegralDn
270 :: (Monad m, Integral a)
271 => a -> a -> a -> Stream m a
272enumerateFromThenToIntegralDn from next to = Stream step EnumInit
274 {-# INLINE_LATE step #-}
276 return $ if to > next
279 else Yield from EnumStop
280 else -- from >= next >= to
281 let stride = next - from
282 in Skip $ EnumYield from stride (to - stride)
284 step _ (EnumYield x stride toMinus) =
287 then Yield x EnumStop
288 else Yield x $ EnumYield (x + stride) stride toMinus
290 step _ EnumStop = return Stop
293-- XXX This can perhaps be simplified and written in terms of
294-- enumeratFromStepIntegral as we have done in unfolds. But anyway we should be
295-- replacing the stream generation module with unfolds.
296{-# INLINE_NORMAL enumerateFromThenToIntegral #-}
297enumerateFromThenToIntegral
298 :: (Monad m, Integral a)
299 => a -> a -> a -> Stream m a
300#ifdef USE_UNFOLDS_EVERYWHERE
301enumerateFromThenToIntegral from next to =
302 unfold Unfold.enumerateFromThenToIntegral (from, next, to)
304enumerateFromThenToIntegral from next to
305 | next >= from = enumerateFromThenToIntegralUp from next to
306 | otherwise = enumerateFromThenToIntegralDn from next to
309{-# INLINE_NORMAL enumerateFromThenIntegral #-}
310enumerateFromThenIntegral
311 :: (Monad m, Integral a, Bounded a)
312 => a -> a -> Stream m a
313#ifdef USE_UNFOLDS_EVERYWHERE
314enumerateFromThenIntegral from next =
315 unfold Unfold.enumerateFromThenIntegralBounded (from, next)
317enumerateFromThenIntegral from next =
319 then enumerateFromThenToIntegralUp from next maxBound
320 else enumerateFromThenToIntegralDn from next minBound
323-- | Can be used to enumerate unbounded integrals. This does not check for
324-- overflow or underflow for bounded integrals.
326{-# INLINE_NORMAL enumerateFromStepIntegral #-}
327enumerateFromStepIntegral :: (Integral a, Monad m) => a -> a -> Stream m a
328#ifdef USE_UNFOLDS_EVERYWHERE
329enumerateFromStepIntegral from stride =
330 unfold Unfold.enumerateFromStepIntegral (from, stride)
332enumerateFromStepIntegral from stride =
333 from `seq` stride `seq` Stream step from
335 {-# INLINE_LATE step #-}
336 step _ !x = return $ Yield x $! (x + stride)
339-- | Enumerate upwards from @from@ to @to@. We are assuming that "to" is
340-- constrained by the type to be within max/min bounds.
341{-# INLINE enumerateFromToIntegral #-}
342enumerateFromToIntegral :: (Monad m, Integral a) => a -> a -> Stream m a
343enumerateFromToIntegral from to =
344 takeWhile (<= to) $ enumerateFromStepIntegral from 1
346{-# INLINE enumerateFromIntegral #-}
347enumerateFromIntegral :: (Monad m, Integral a, Bounded a) => a -> Stream m a
348enumerateFromIntegral from = enumerateFromToIntegral from maxBound
350------------------------------------------------------------------------------
351-- Enumeration of Fractionals
352------------------------------------------------------------------------------
354-- | We cannot write a general function for Num. The only way to write code
355-- portable between the two is to use a 'Real' constraint and convert between
356-- Fractional and Integral using fromRational which is horribly slow.
357{-# INLINE_NORMAL enumerateFromToFractional #-}
358enumerateFromToFractional
359 :: (Monad m, Fractional a, Ord a)
360 => a -> a -> Stream m a
361enumerateFromToFractional from to =
362 takeWhile (<= to + 1 / 2) $ enumerateFromStepNum from 1
364{-# INLINE_NORMAL enumerateFromThenToFractional #-}
365enumerateFromThenToFractional
366 :: (Monad m, Fractional a, Ord a)
367 => a -> a -> a -> Stream m a
368enumerateFromThenToFractional from next to =
369 takeWhile predicate $ enumerateFromThenNum from next
371 mid = (next - from) / 2
372 predicate | next >= from = (<= to + mid)
373 | otherwise = (>= to + mid)
375------------------------------------------------------------------------------
377------------------------------------------------------------------------------
379{-# INLINE_NORMAL times #-}
380times :: MonadIO m => Double -> Stream m (AbsTime, RelTime64)
381times g = Stream step Nothing
385 {-# INLINE_LATE step #-}
387 clock <- liftIO $ asyncClock Monotonic g
388 a <- liftIO $ readClock clock
389 return $ Skip $ Just (clock, a)
391 step _ s@(Just (clock, t0)) = do
392 a <- liftIO $ readClock clock
393 -- XXX we can perhaps use an AbsTime64 using a 64 bit Int for
394 -- efficiency. or maybe we can use a representation using Double for
395 -- floating precision time
396 return $ Yield (toAbsTime t0, toRelTime64 (a - t0)) s
398-------------------------------------------------------------------------------
400-------------------------------------------------------------------------------
402{-# INLINE_NORMAL fromIndicesM #-}
403fromIndicesM :: Monad m => (Int -> m a) -> Stream m a
404#ifdef USE_UNFOLDS_EVERYWHERE
405fromIndicesM gen = unfold (Unfold.fromIndicesM gen) 0
407fromIndicesM gen = Stream step 0
409 {-# INLINE_LATE step #-}
412 return $ Yield x (i + 1)
415{-# INLINE fromIndices #-}
416fromIndices :: Monad m => (Int -> a) -> Stream m a
417fromIndices gen = fromIndicesM (return . gen)
419-- Adapted from the vector package
420{-# INLINE_NORMAL generateM #-}
421generateM :: Monad m => Int -> (Int -> m a) -> Stream m a
422generateM n gen = n `seq` Stream step 0
424 {-# INLINE_LATE step #-}
425 step _ i | i < n = do
427 return $ Yield x (i + 1)
428 | otherwise = return Stop
430{-# INLINE generate #-}
431generate :: Monad m => Int -> (Int -> a) -> Stream m a
432generate n gen = generateM n (return . gen)
434-------------------------------------------------------------------------------
436-------------------------------------------------------------------------------
438{-# INLINE_NORMAL iterateM #-}
439iterateM :: Monad m => (a -> m a) -> m a -> Stream m a
440#ifdef USE_UNFOLDS_EVERYWHERE
441iterateM step = unfold (Unfold.iterateM step)
443iterateM step = Stream (\_ st -> st >>= \(!x) -> return $ Yield x (step x))
446{-# INLINE_NORMAL iterate #-}
447iterate :: Monad m => (a -> a) -> a -> Stream m a
448iterate step st = iterateM (return . step) (return st)
450-------------------------------------------------------------------------------
452-------------------------------------------------------------------------------
454-- | Convert a list of monadic actions to a 'Stream'
455{-# INLINE_LATE fromListM #-}
456fromListM :: Monad m => [m a] -> Stream m a
457#ifdef USE_UNFOLDS_EVERYWHERE
458fromListM = unfold Unfold.fromListM
460fromListM = Stream step
462 {-# INLINE_LATE step #-}
463 step _ (m:ms) = m >>= \x -> return $ Yield x ms
464 step _ [] = return Stop
467-------------------------------------------------------------------------------
469-------------------------------------------------------------------------------
471-- | Read an infinite stream from a pointer, advancing the pointer as needed.
472-- The caller is responsible to end the stream safely.
473{-# INLINE fromPtr #-}
474fromPtr :: forall m a. (MonadIO m, Storable a) => Ptr a -> Stream m a
479 {-# INLINE_LATE step #-}
482 return $ Yield x (PTR_NEXT(p, a))
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list