@@ -1,7 +1,7 @@
11-- |
22-- Module : Streamly.Internal.Data.Unfold.Enumeration
3−-- Copyright : (c) 2019 Composewell Technologies
4−-- License : BSD3
3+-- Copyright : (c) 2019, 2021 Composewell Technologies
4+-- License : BSD-3-Clause
55-- Maintainer : streamly@composewell.com
66-- Stability : experimental
77-- Portability : GHC
@@ -61,8 +61,8 @@ import Data.Ratio
6161import Data.Word
6262import Numeric.Natural
6363import Data.Functor.Identity (Identity(..))
64−import Streamly.Internal.Data.Unfold.Type
6564import Streamly.Internal.Data.Stream.StreamD.Step (Step(..))
65+import Streamly.Internal.Data.Unfold.Type
6666import Prelude
6767 hiding (map, mapM, takeWhile, take, filter, const, zipWith
6868 , drop, dropWhile)
@@ -71,34 +71,18 @@ import Prelude
7171-- Enumeration of Num
7272------------------------------------------------------------------------------
7373
74−-- | Generate an infinite stream starting from a starting value with default
75−-- stride of value 1. The implementation is numerically stable for floating
76−-- point values.
74+-- | Unfolds @(from, next)@ generating an infinite stream starting from @from@
75+-- and @next@ values with a stride of @(next - from)@. After the value
76+-- overflows it keeps enumerating in a cycle:
7777--
78−-- Note 'enumerateFromStepIntegral' is faster for integrals.
78+-- >>> Stream.toList $ Stream.take 10 $ Stream.unfold Unfold.enumerateFromThenNum (255::Word8,0)
79+-- [255,0,1,2,3,4,5,6,7,8]
7980--
80−-- /Pre-release/
81−--
82−{-# INLINE enumerateFromNum #-}
83−enumerateFromNum :: (Monad m, Num a) => Unfold m a a
84−enumerateFromNum = Unfold step inject
85−
86− where
87−
88− inject !from = return (from, 1, 0)
89−
90− {-# INLINE_LATE step #-}
91− step (from, stride, i) =
92− return $
93− (Yield $! (from + i * stride)) $! (from, stride, i + 1)
94−
95−-- | Generate an infinite stream starting from a from and next values with
96−-- stride of (next-from). The implementation is numerically stable for
97−-- floating point values.
81+-- The implementation is numerically stable for floating point values.
9882--
9983-- Note 'enumerateFromStepIntegral' is faster for integrals.
10084--
101−-- /Pre-release/
85+-- /Internal/
10286--
10387{-# INLINE enumerateFromThenNum #-}
10488enumerateFromThenNum :: (Monad m, Num a) => Unfold m (a, a) a
@@ -108,18 +92,32 @@ enumerateFromThenNum = Unfold step inject
10892
10993 inject (!from, !next) = return (from, next - from, 0)
11094
95+ -- Note that the counter "i" is the same type as the type being enumerated.
96+ -- It may overflow, for example, if we are enumerating Word8, after 255 the
97+ -- counter will become 0, but the overflow does not affect the enumeration
98+ -- behavior.
11199 {-# INLINE_LATE step #-}
112100 step (from, stride, i) =
113101 return $
114102 (Yield $! (from + i * stride)) $! (from, stride, i + 1)
115103
104+-- | Same as 'enumerateFromThenNum' using a stride of 1.
105+--
106+-- >>> enumerateFromNum = lmap (\from -> (from, from + 1)) enumerateFromThenNum
107+--
108+-- /Internal/
109+--
110+{-# INLINE enumerateFromNum #-}
111+enumerateFromNum :: (Monad m, Num a) => Unfold m a a
112+enumerateFromNum = lmap (\from -> (from, from + 1)) enumerateFromThenNum
113+
116114-- | Generate a finite stream starting from a from and next values with
117115-- stride of (next-from) till to value. The implementation is numerically
118116-- stable for floating point values.
119117--
120118-- Note 'enumerateFromStepIntegral' is faster for integrals.
121119--
122−-- /Pre-release/
120+-- /Internal/
123121--
124122{-# INLINE enumerateFromThenToNumBounded #-}
125123enumerateFromThenToNumBounded :: (Monad m, Ord a, Fractional a) =>
@@ -151,7 +149,7 @@ enumerateFromThenToNumBounded = Unfold step inject
151149--
152150-- Note 'enumerateFromStepIntegralBounded' is faster for integrals.
153151--
154−-- /Pre-release/
152+-- /Internal/
155153--
156154{-# INLINE enumerateFromToNumBounded #-}
157155enumerateFromToNumBounded :: (Monad m, Ord a, Fractional a) =>
@@ -174,6 +172,8 @@ enumerateFromToNumBounded = Unfold step inject
174172
175173-- | Can be used to enumerate unbounded integrals. This does not check for
176174-- overflow or underflow for bounded integrals.
175+--
176+-- /Internal/
177177{-# INLINE_NORMAL enumerateFromStepIntegral #-}
178178enumerateFromStepIntegral :: (Integral a, Monad m) => Unfold m (a, a) a
179179enumerateFromStepIntegral = Unfold step inject
@@ -185,7 +185,8 @@ enumerateFromStepIntegral = Unfold step inject
185185-- | Can be used to enumerate bounded integrals from starting from with
186186-- stride of (next-from) . This check for overflow or underflow for
187187-- bounded integrals.
188−-- /Pre-release/
188+--
189+-- /Internal/
189190--
190191{-# INLINE_NORMAL enumerateFromStepIntegralBounded #-}
191192enumerateFromStepIntegralBounded ::
@@ -215,7 +216,8 @@ enumerateFromStepIntegralBounded = Unfold step inject
215216-- | Can be used to enumerate bounded integrals from starting from with
216217-- stride of (next-from) till to value. This check for overflow or underflow
217218-- for bounded integrals.
218−-- /Pre-release/
219+--
220+-- /Internal/
219221--
220222{-# INLINE_NORMAL enumerateFromToStepIntegralBounded #-}
221223enumerateFromToStepIntegralBounded ::
@@ -244,7 +246,8 @@ enumerateFromToStepIntegralBounded = Unfold step inject
244246
245247-- | Can be used to enumerate unbounded integrals. Startting with value from
246248-- with stride of next-from till value of to.
247−-- /Pre-release/
249+--
250+-- /Internal/
248251--
249252{-# INLINE_NORMAL enumerateFromToStepIntegral #-}
250253enumerateFromToStepIntegral :: (Integral a, Monad m) =>
@@ -335,6 +338,7 @@ enumerateFromThenToFractional = enumerateFromThenToNumBounded
335338-------------------------------------------------------------------------------
336339-- Enumerable type class
337340-------------------------------------------------------------------------------
341+
338342-- | Types that can be enumerated as a stream. The operations in this type
339343-- class are equivalent to those in the 'Enum' type class, except that these
340344-- generate a stream instead of a list. Use the functions in
@@ -343,98 +347,97 @@ enumerateFromThenToFractional = enumerateFromThenToNumBounded
343347-- /Pre-release/
344348class Enum a => Enumerable a where
345349
346−-- @enumerateFrom from@ generates a stream starting with the element
347−-- @from@, enumerating up to 'maxBound' when the type is 'Bounded' or
348−-- generating an infinite stream when the type is not 'Bounded'.
349−--
350−-- @
351−-- >>> Stream.toList $ Stream.take 4 $ Stream.unfold Unfold.enumerateFrom (0 :: Int)
352−-- [0,1,2,3]
353−--
354−-- @
355−--
356−-- For 'Fractional' types, enumeration is numerically stable. However, no
357−-- overflow or underflow checks are performed.
358−--
359−-- @
360−-- >>> Stream.toList $ Stream.take 4 $ Stream.unfold Unfold.enumerateFrom 1.1
361−-- [1.1,2.1,3.1,4.1]
362−--
363−-- @
364−--
365−-- /Pre-release/
366−--
350+ -- | Unfolds @from@ generating a stream starting with the element
351+ -- @from@, enumerating up to 'maxBound' when the type is 'Bounded' or
352+ -- generating an infinite stream when the type is not 'Bounded'.
353+ --
354+ -- @
355+ -- >>> Stream.toList $ Stream.take 4 $ Stream.unfold Unfold.enumerateFrom (0 :: Int)
356+ -- [0,1,2,3]
357+ --
358+ -- @
359+ --
360+ -- For 'Fractional' types, enumeration is numerically stable. However, no
361+ -- overflow or underflow checks are performed.
362+ --
363+ -- @
364+ -- >>> Stream.toList $ Stream.take 4 $ Stream.unfold Unfold.enumerateFrom 1.1
365+ -- [1.1,2.1,3.1,4.1]
366+ --
367+ -- @
368+ --
369+ -- /Pre-release/
370+ --
367371 enumerateFrom :: Monad m => Unfold m a a
368372
369−-- Generate a finite stream starting with the element @from@, enumerating
370−-- the type up to the value @to@. If @to@ is smaller than @from@ then an
371−-- empty stream is returned.
372−--
373−-- @
374−-- >>> Stream.toList $ Stream.unfold (Unfold.enumerateFromTo 4) 0
375−-- [0,1,2,3,4]
376−--
377−-- @
378−--
379−-- For 'Fractional' types, the last element is equal to the specified @to@
380−-- value after rounding to the nearest integral value.
381−--
382−-- @
383−-- >>> Stream.toList $ Stream.unfold (Unfold.enumerateFromTo 4) 1.1
384−-- [1.1,2.1,3.1,4.1]
385−--
386−-- >>> Stream.toList $ Stream.unfold (Unfold.enumerateFromTo 4.6) 1.1
387−-- [1.1,2.1,3.1,4.1,5.1]
388−--
389−-- @
390−--
391−-- /Pre-release/
373+ -- | Unfolds @(from, to)@ generating a finite stream starting with the element
374+ -- @from@, enumerating the type up to the value @to@. If @to@ is smaller than
375+ -- @from@ then an empty stream is returned.
376+ --
377+ -- @
378+ -- >>> Stream.toList $ Stream.unfold (Unfold.enumerateFromTo 4) 0
379+ -- [0,1,2,3,4]
380+ --
381+ -- @
382+ --
383+ -- For 'Fractional' types, the last element is equal to the specified @to@
384+ -- value after rounding to the nearest integral value.
385+ --
386+ -- @
387+ -- >>> Stream.toList $ Stream.unfold (Unfold.enumerateFromTo 4) 1.1
388+ -- [1.1,2.1,3.1,4.1]
389+ --
390+ -- >>> Stream.toList $ Stream.unfold (Unfold.enumerateFromTo 4.6) 1.1
391+ -- [1.1,2.1,3.1,4.1,5.1]
392+ --
393+ -- @
394+ --
395+ -- /Pre-release/
392396 enumerateFromTo :: Monad m => Unfold m (a, a) a
393397
394−-- @enumerateFromThen from then@ generates a stream whose first element
395−-- is @from@ and the successive elements are
396−-- in increments of @then@. Enumeration can occur downwards or
397−-- upwards depending on whether @then@ comes before or after @from@. For
398−-- 'Bounded' types the stream ends when 'maxBound' is reached, for
399−-- unbounded types it keeps enumerating infinitely.
400−--
401−-- @
402−-- >>> Stream.toList $ Stream.take 4 $ Stream.unfold (Unfold.enumerateFromThen 2) 0
403−-- [0,2,4,6]
404−--
405−-- >>> Stream.toList $ Stream.take 4 $ Stream.unfold (Unfold.enumerateFromThen (-2)) 0
406−-- [0,-2,-4,-6]
407−--
408−-- @
409−--
410−-- /Pre-release/
398+ -- | Unfolds @(from, then)@ generating a stream whose first element is
399+ -- @from@ and the successive elements are in increments of @then@. Enumeration
400+ -- can occur downwards or upwards depending on whether @then@ comes before or
401+ -- after @from@. For 'Bounded' types the stream ends when 'maxBound' is
402+ -- reached, for unbounded types it keeps enumerating infinitely.
403+ --
404+ -- @
405+ -- >>> Stream.toList $ Stream.take 4 $ Stream.unfold (Unfold.enumerateFromThen 2) 0
406+ -- [0,2,4,6]
407+ --
408+ -- >>> Stream.toList $ Stream.take 4 $ Stream.unfold (Unfold.enumerateFromThen (-2)) 0
409+ -- [0,-2,-4,-6]
410+ --
411+ -- @
412+ --
413+ -- /Pre-release/
411414 enumerateFromThen :: Monad m => Unfold m (a, a) a
412415
413−-- @enumerateFromThenTo from then to@ generates a finite stream whose
414−-- first element is @from@ and the successive elements are in
415−-- increments of @then@ up to @to@. Enumeration can
416−-- occur downwards or upwards depending on whether @then@ comes before or
417−-- after @from@.
418−--
419−-- @
420−-- >>> Stream.toList $ Stream.unfold (Unfold.enumerateFromThenTo 2 6) 0
421−-- [0,2,4,6]
422−--
423−-- >>> Stream.toList $ Stream.unfold (Unfold.enumerateFromThenTo (-2) (-6)) 0
424−-- [0,-2,-4,-6]
425−--
426−-- @
427−--
428−-- /Pre-release/
416+ -- | Unfolds @(from, then, to)@ generating a finite stream whose first element
417+ -- is @from@ and the successive elements are in increments of @then@ up to
418+ -- @to@. Enumeration can occur downwards or upwards depending on whether @then@
419+ -- comes before or after @from@.
420+ --
421+ -- @
422+ -- >>> Stream.toList $ Stream.unfold (Unfold.enumerateFromThenTo 2 6) 0
423+ -- [0,2,4,6]
424+ --
425+ -- >>> Stream.toList $ Stream.unfold (Unfold.enumerateFromThenTo (-2) (-6)) 0
426+ -- [0,-2,-4,-6]
427+ --
428+ -- @
429+ --
430+ -- /Pre-release/
429431 enumerateFromThenTo :: Monad m => Unfold m (a, a, a) a
430432
431433-------------------------------------------------------------------------------
432434-- Enumeration of Enum types not larger than Int
433435-------------------------------------------------------------------------------
434436
435−-- Enumerate from given starting Enum value 'from' with stride of 1 till
437+-- | Enumerate from given starting Enum value 'from' with stride of 1 till
436438-- maxBound
437−-- /Pre-release/
439+--
440+-- /Internal/
438441--
439442{-# INLINE enumerateFromSmall #-}
440443enumerateFromSmall :: forall a m. (Monad m, Bounded a, Enum a) => Unfold m a a
@@ -448,9 +451,10 @@ enumerateFromSmall = map toEnum $
448451 step (x, stride, to) = return $
449452 if x <= to then Yield x $! (x + stride, stride, to) else Stop
450453
451−-- Enumerate from given starting Enum value 'from' and next Enum value 'next'
454+-- | Enumerate from given starting Enum value 'from' and next Enum value 'next'
452455-- with stride of (fromEnum next - fromEnum from) till maxBound.
453−-- /Pre-release/
456+--
457+-- /Internal/
454458--
455459{-# INLINE enumerateFromThenSmall #-}
456460enumerateFromThenSmall :: forall a m. (Monad m, Bounded a, Enum a) =>
@@ -483,9 +487,10 @@ enumerateFromThenSmall = map toEnum $
483487 then Yield x $! (x + stride, stride, to)
484488 else Stop
485489
486−-- Enumerate from given starting Enum value 'from' and to Enum value 'to'
490+-- | Enumerate from given starting Enum value 'from' and to Enum value 'to'
487491-- with stride of 1 till to value.
488−-- /Pre-release/
492+--
493+-- /Internal/
489494--
490495{-# INLINE enumerateFromToSmall #-}
491496enumerateFromToSmall :: (Monad m, Enum a) => Unfold m (a, a) a
@@ -500,10 +505,11 @@ enumerateFromToSmall = map toEnum $
500505 step (x, stride, to) = return $
501506 if x <= to then Yield x $! (x + stride, stride, to) else Stop
502507
503−-- Enumerate from given starting Enum value 'from' and then Enum value 'next'
508+-- | Enumerate from given starting Enum value 'from' and then Enum value 'next'
504509-- and to Enum value 'to' with stride of (fromEnum next - fromEnum from)
505510-- till to value.
506−-- /Pre-release/
511+--
512+-- /Internal/
507513--
508514{-# INLINE enumerateFromThenToSmall #-}
509515enumerateFromThenToSmall :: (Monad m, Enum a) => Unfold m (a, a, a) a