on master help sign in
Add enumerateTo, update documentation
9f43f1aHarendra Kumar
Changelog.md+3−3
@@ -10,9 +10,9 @@
10* Performance improvements
10* Performance improvements
11* Add the following functions to Prelude:
11* Add the following functions to Prelude:
12 * Generation: `replicate`, `fromIndices`, `fromIndicesM`
12 * Generation: `replicate`, `fromIndices`, `fromIndicesM`
13− * Enumeration: `Enumerable`, `enumerateFrom`, `enumerateFromTo`,
13+ * Enumeration: `Enumerable` type class, `enumerateFrom`, `enumerateFromTo`,
14− `enumerateFromThen`, `enumerateFromThenTo`, `enumerate`
14+ `enumerateFromThen`, `enumerateFromThenTo`, `enumerate`, `enumerateTo`
15− * Running: `runIters`, `runWhile`
15+ * Running: `runN`, `runWhile`
16 * Folds: `(!!)`, `maximumBy`, `minimumBy`, `the`
16 * Folds: `(!!)`, `maximumBy`, `minimumBy`, `the`
17 * Scans: `scanl1'`, `scanl1M'
17 * Scans: `scanl1'`, `scanl1M'
18 * Filters: `uniq`, `insertBy`, `deleteBy`, `findM`
18 * Filters: `uniq`, `insertBy`, `deleteBy`, `findM`
src/Streamly/Enumeration.hs+87−60
@@ -25,31 +25,33 @@
25module Streamly.Enumeration
25module Streamly.Enumeration
26 (
26 (
27 Enumerable (..)
27 Enumerable (..)
28+
29+ -- ** Enumerating 'Bounded' 'Enum' Types
28 , enumerate
30 , enumerate
31+ , enumerateTo
32+ , enumerateFromBounded
29
33
30− -- ** Enumerating 'Enum' Types
34+ -- ** Enumerating 'Enum' Types not larger than 'Int'
31 , enumerateFromToSmall
35 , enumerateFromToSmall
32 , enumerateFromThenToSmall
36 , enumerateFromThenToSmall
33 , enumerateFromThenSmallBounded
37 , enumerateFromThenSmallBounded
34− , enumerateFromBounded
35
38
36 -- ** Enumerating 'Bounded' 'Integral' Types
39 -- ** Enumerating 'Bounded' 'Integral' Types
37 , enumerateFromIntegral
40 , enumerateFromIntegral
38 , enumerateFromThenIntegral
41 , enumerateFromThenIntegral
39
42
40− -- ** Enumerating unbounded 'Integral' Types
43+ -- ** Enumerating 'Integral' Types
41 , enumerateFromToIntegral
44 , enumerateFromToIntegral
42 , enumerateFromThenToIntegral
45 , enumerateFromThenToIntegral
46+
47+ -- ** Enumerating unbounded 'Integral' Types
43 , enumerateFromStepIntegral
48 , enumerateFromStepIntegral
44
49
45− -- ** Enumerating unbounded 'Fractional' Types
50+ -- ** Enumerating 'Fractional' Types
46 , enumerateFromFractional
51 , enumerateFromFractional
47 , enumerateFromToFractional
52 , enumerateFromToFractional
48 , enumerateFromThenFractional
53 , enumerateFromThenFractional
49 , enumerateFromThenToFractional
54 , enumerateFromThenToFractional
50−
51− -- ** Enumerating unbounded 'Num' Types
52− , enumerateFromStepNum
53 )
55 )
54where
56where
55
57
@@ -72,8 +74,10 @@ import qualified Streamly.Streams.Serial as Serial
72--
74--
73-- | @enumerateFromStepIntegral from step@ generates an infinite stream whose
75-- | @enumerateFromStepIntegral from step@ generates an infinite stream whose
74-- first element is @from@ and the successive elements are in increments of
76-- first element is @from@ and the successive elements are in increments of
77+-- @step@.
78+--
79+-- CAUTION: This function is not safe for finite integral types. It does not
75−-- @step@. This does not check for overflow or underflow if the 'Integral' type
80+-- check for overflow, underflow or bounds.
76−-- is bounded.
77--
81--
78-- @
82-- @
79-- > S.toList $ S.take 4 $ S.enumerateFromStepIntegral 0 2
83-- > S.toList $ S.take 4 $ S.enumerateFromStepIntegral 0 2
@@ -162,30 +166,6 @@ enumerateFromThenToIntegral
162enumerateFromThenToIntegral from next to =
166enumerateFromThenToIntegral from next to =
163 fromStreamD $ D.enumerateFromThenToIntegral from next to
167 fromStreamD $ D.enumerateFromThenToIntegral from next to
164
168
165−-------------------------------------------------------------------------------
166−-- Enumeration of Num types
167−-------------------------------------------------------------------------------
168−--
169−-- | @enumerateFromStepNum from step@ generates an infinite stream whose first
170−-- element is @from@ and the successive elements are in increments of @step@.
171−-- This is numerically stable but does not check for overflow or underflow for
172−-- bounded types. Note, for 'Integral' types 'enumerateFromStepIntegral' is
173−-- faster.
174−--
175−--
176−-- @
177−-- > S.toList $ S.take 4 $ S.enumerateFromStepNum 0.1 2
178−-- [0.1,2.1,4.1,6.1]
179−-- > S.toList $ S.take 3 $ S.enumerateFromStepNum 0.1 (-2)
180−-- [0.1,-1.9,-3.9,-5.9]
181−-- @
182−--
183−-- @since 0.6.0
184−{-# INLINE enumerateFromStepNum #-}
185−enumerateFromStepNum :: (IsStream t, Monad m, Num a) => a -> a -> t m a
186−enumerateFromStepNum from stride =
187− fromStreamD $ D.enumerateFromStepNum from stride
188−
189-------------------------------------------------------------------------------
169-------------------------------------------------------------------------------
190-- Enumeration of Fractional types
170-- Enumeration of Fractional types
191-------------------------------------------------------------------------------
171-------------------------------------------------------------------------------
@@ -287,40 +267,35 @@ enumerateFromThenToFractional from next to =
287 fromStreamD $ D.enumerateFromThenToFractional from next to
267 fromStreamD $ D.enumerateFromThenToFractional from next to
288
268
289-------------------------------------------------------------------------------
269-------------------------------------------------------------------------------
290−-- Enumeration of Enum types
270+-- Enumeration of Enum types not larger than Int
291-------------------------------------------------------------------------------
271-------------------------------------------------------------------------------
292--
272--
293−-- | 'enumerateFromTo' for 'Enum' types not larger than 'Int'. This function
273+-- | 'enumerateFromTo' for 'Enum' types not larger than 'Int'.
294−-- does not check the bounds for 'Bounded' types, it assumes that the @to@
274+--
295−-- parameter is constrained by the type to be within the range representable by
275+-- @since 0.6.0
296−-- the type.
297{-# INLINE enumerateFromToSmall #-}
276{-# INLINE enumerateFromToSmall #-}
298enumerateFromToSmall :: (IsStream t, Monad m, Enum a) => a -> a -> t m a
277enumerateFromToSmall :: (IsStream t, Monad m, Enum a) => a -> a -> t m a
299enumerateFromToSmall from to = Serial.map toEnum $
278enumerateFromToSmall from to = Serial.map toEnum $
300 enumerateFromToIntegral (fromEnum from) (fromEnum to)
279 enumerateFromToIntegral (fromEnum from) (fromEnum to)
301
280
302−-- | 'enumerateFrom' for 'Bounded' 'Enum' types. This is defined in terms of
303−-- 'enumerateFromTo', therefore it will work even for types larger than 'Int'
304−-- depending on 'enumerateFromTo'.
305−{-# INLINE enumerateFromBounded #-}
306−enumerateFromBounded :: (IsStream t, Monad m, Enumerable a, Bounded a)
307− => a -> t m a
308−enumerateFromBounded from = enumerateFromTo from maxBound
309−
310−-- | 'enumerateFromThenTo' for 'Enum' types not larger than 'Int'. This
281+-- | 'enumerateFromThenTo' for 'Enum' types not larger than 'Int'.
311−-- function does not check the bounds for 'Bounded' types, it assumes that the
282+--
312−-- @to@ parameter is constrained by the type to be within the range
283+-- @since 0.6.0
313−-- representable by the type.
314{-# INLINE enumerateFromThenToSmall #-}
284{-# INLINE enumerateFromThenToSmall #-}
315enumerateFromThenToSmall :: (IsStream t, Monad m, Enum a)
285enumerateFromThenToSmall :: (IsStream t, Monad m, Enum a)
316 => a -> a -> a -> t m a
286 => a -> a -> a -> t m a
317enumerateFromThenToSmall from next to = Serial.map toEnum $
287enumerateFromThenToSmall from next to = Serial.map toEnum $
318 enumerateFromThenToIntegral (fromEnum from) (fromEnum next) (fromEnum to)
288 enumerateFromThenToIntegral (fromEnum from) (fromEnum next) (fromEnum to)
319
289
320−-- | 'enumerateFromThen' for 'Bounded' 'Enum' types not larger than 'Int'. For
290+-- | 'enumerateFromThen' for 'Enum' types not larger than 'Int'.
321−-- types smaller than 'Int' we know it is bounded though it may not have a
291+--
322−-- 'Bounded' instance. It is not necessary to require 'Bounded' instance for
292+-- Note: We convert the 'Enum' to 'Int' and enumerate the 'Int'. If a
323−-- all small types, we require it anyway because it is safe that way.
293+-- type is bounded but does not have a 'Bounded' instance then we can go on
294+-- enumerating it beyond the legal values of the type, resulting in the failure
295+-- of 'toEnum' when converting back to 'Enum'. Therefore we require a 'Bounded'
296+-- instance for this function to be safely used.
297+--
298+-- @since 0.6.0
324{-# INLINE enumerateFromThenSmallBounded #-}
299{-# INLINE enumerateFromThenSmallBounded #-}
325enumerateFromThenSmallBounded :: (IsStream t, Monad m, Enumerable a, Bounded a)
300enumerateFromThenSmallBounded :: (IsStream t, Monad m, Enumerable a, Bounded a)
326 => a -> a -> t m a
301 => a -> a -> t m a
@@ -366,6 +341,7 @@ class Enum a => Enumerable a where
366 -- [1.1,2.1,3.1,4.1]
341 -- [1.1,2.1,3.1,4.1]
367 -- @
342 -- @
368 --
343 --
344+ -- @since 0.6.0
369 enumerateFrom :: (IsStream t, Monad m) => a -> t m a
345 enumerateFrom :: (IsStream t, Monad m) => a -> t m a
370
346
371 -- | Generate a finite stream starting with the element @from@, enumerating
347 -- | Generate a finite stream starting with the element @from@, enumerating
@@ -387,6 +363,7 @@ class Enum a => Enumerable a where
387 -- [1.1,2.1,3.1,4.1,5.1]
363 -- [1.1,2.1,3.1,4.1,5.1]
388 -- @
364 -- @
389 --
365 --
366+ -- @since 0.6.0
390 enumerateFromTo :: (IsStream t, Monad m) => a -> a -> t m a
367 enumerateFromTo :: (IsStream t, Monad m) => a -> a -> t m a
391
368
392 -- | @enumerateFromThen from then@ generates a stream whose first element
369 -- | @enumerateFromThen from then@ generates a stream whose first element
@@ -402,6 +379,8 @@ class Enum a => Enumerable a where
402 -- > S.toList $ S.take 4 $ S.enumerateFromThen 0 (-2)
379 -- > S.toList $ S.take 4 $ S.enumerateFromThen 0 (-2)
403 -- [0,-2,-4,-6]
380 -- [0,-2,-4,-6]
404 -- @
381 -- @
382+ --
383+ -- @since 0.6.0
405 enumerateFromThen :: (IsStream t, Monad m) => a -> a -> t m a
384 enumerateFromThen :: (IsStream t, Monad m) => a -> a -> t m a
406
385
407 -- | @enumerateFromThenTo from then to@ generates a finite stream whose
386 -- | @enumerateFromThenTo from then to@ generates a finite stream whose
@@ -416,8 +395,60 @@ class Enum a => Enumerable a where
416 -- > S.toList $ S.enumerateFromThenTo 0 (-2) (-6)
395 -- > S.toList $ S.enumerateFromThenTo 0 (-2) (-6)
417 -- [0,-2,-4,-6]
396 -- [0,-2,-4,-6]
418 -- @
397 -- @
398+ --
399+ -- @since 0.6.0
419 enumerateFromThenTo :: (IsStream t, Monad m) => a -> a -> a -> t m a
400 enumerateFromThenTo :: (IsStream t, Monad m) => a -> a -> a -> t m a
420
401
402+-- MAYBE: Sometimes it is more convenient to know the count rather then the
403+-- ending or starting element. For those cases we can define the folllowing
404+-- APIs. All of these will work only for bounded types if we represent the
405+-- count by Int.
406+--
407+-- enumerateN
408+-- enumerateFromN
409+-- enumerateToN
410+-- enumerateFromStep
411+-- enumerateFromStepN
412+
413+-------------------------------------------------------------------------------
414+-- Convenient functions for bounded types
415+-------------------------------------------------------------------------------
416+--
417+-- |
418+-- > enumerate = enumerateFrom minBound
419+--
420+-- Enumerate a 'Bounded' type from its 'minBound' to 'maxBound'
421+--
422+-- @since 0.6.0
423+{-# INLINE enumerate #-}
424+enumerate :: (IsStream t, Monad m, Bounded a, Enumerable a) => t m a
425+enumerate = enumerateFrom minBound
426+
427+-- |
428+-- > enumerateTo = enumerateFromTo minBound
429+--
430+-- Enumerate a 'Bounded' type from its 'minBound' to specified value.
431+--
432+-- @since 0.6.0
433+{-# INLINE enumerateTo #-}
434+enumerateTo :: (IsStream t, Monad m, Bounded a, Enumerable a) => a -> t m a
435+enumerateTo = enumerateFromTo minBound
436+
437+-- |
438+-- > enumerateFromBounded = enumerateFromTo from maxBound
439+--
440+-- 'enumerateFrom' for 'Bounded' 'Enum' types.
441+--
442+-- @since 0.6.0
443+{-# INLINE enumerateFromBounded #-}
444+enumerateFromBounded :: (IsStream t, Monad m, Enumerable a, Bounded a)
445+ => a -> t m a
446+enumerateFromBounded from = enumerateFromTo from maxBound
447+
448+-------------------------------------------------------------------------------
449+-- Enumerable Instances
450+-------------------------------------------------------------------------------
451+--
421-- For Enum types smaller than or equal to Int size.
452-- For Enum types smaller than or equal to Int size.
422#define ENUMERABLE_BOUNDED_SMALL(SMALL_TYPE) \
453#define ENUMERABLE_BOUNDED_SMALL(SMALL_TYPE) \
423instance Enumerable SMALL_TYPE where { \
454instance Enumerable SMALL_TYPE where { \
@@ -506,8 +537,9 @@ instance Enumerable a => Enumerable (Identity a) where
506 enumerateFromThenTo (Identity from) (Identity next) (Identity to) =
537 enumerateFromThenTo (Identity from) (Identity next) (Identity to) =
507 Serial.map Identity $ enumerateFromThenTo from next to
538 Serial.map Identity $ enumerateFromThenTo from next to
508#endif
539#endif
509−{-
540+
510-- TODO
541-- TODO
542+{-
511instance Enumerable a => Enumerable (Last a)
543instance Enumerable a => Enumerable (Last a)
512instance Enumerable a => Enumerable (First a)
544instance Enumerable a => Enumerable (First a)
513instance Enumerable a => Enumerable (Max a)
545instance Enumerable a => Enumerable (Max a)
@@ -516,8 +548,3 @@ instance Enumerable a => Enumerable (Const a b)
516instance Enumerable (f a) => Enumerable (Alt f a)
548instance Enumerable (f a) => Enumerable (Alt f a)
517instance Enumerable (f a) => Enumerable (Ap f a)
549instance Enumerable (f a) => Enumerable (Ap f a)
518-}
550-}
519−
520−-- | Enumerate a finite ('Bounded') data type from its 'minBound' to 'maxBound'
521−{-# INLINE enumerate #-}
522−enumerate :: (IsStream t, Monad m, Bounded a, Enumerable a) => t m a
523−enumerate = enumerateFrom minBound
src/Streamly/Prelude.hs+2−1
@@ -85,6 +85,7 @@ module Streamly.Prelude
85
85
86 , Enumerable (..)
86 , Enumerable (..)
87 , enumerate
87 , enumerate
88+ , enumerateTo
88
89
89 -- ** From Generators
90 -- ** From Generators
90 -- | Generate a monadic stream from a seed value and a generator function.
91 -- | Generate a monadic stream from a seed value and a generator function.
@@ -356,7 +357,7 @@ import Prelude
356import qualified Prelude
357import qualified Prelude
357import qualified System.IO as IO
358import qualified System.IO as IO
358
359
359−import Streamly.Enumeration (Enumerable(..), enumerate)
360+import Streamly.Enumeration (Enumerable(..), enumerate, enumerateTo)
360import Streamly.SVar (MonadAsync, defState, rstState)
361import Streamly.SVar (MonadAsync, defState, rstState)
361import Streamly.Streams.Async (mkAsync')
362import Streamly.Streams.Async (mkAsync')
362import Streamly.Streams.Combinators (maxYields)
363import Streamly.Streams.Combinators (maxYields)