on master help sign in
Express enumerations in a more modular way
e996392Harendra Kumar
dev/container-api.md+1−1
@@ -85,7 +85,7 @@ the following reasons:
85 correctly. Ideally, when we know the elements then former is more
85 correctly. Ideally, when we know the elements then former is more
86 suitable while if we know the count then the latter is more suitable.
86 suitable while if we know the count then the latter is more suitable.
87
87
88−Note that in case of flaoting point numbers `FromStep` style may have an
88+Note that in case of floating point numbers `FromStep` style may have an
89advantage over `FromThen` style. Here is a quote from the documentation of
89advantage over `FromThen` style. Here is a quote from the documentation of
90`enumerateFromThenNum`:
90`enumerateFromThenNum`:
91
91
src/Streamly/Internal/Data/Stream/StreamD/Generate.hs+3
@@ -259,6 +259,9 @@ enumerateFromThenToIntegralDn from next to = Stream step EnumInit
259
259
260 step _ EnumStop = return Stop
260 step _ EnumStop = return Stop
261
261
262+-- XXX This can perhaps be simplified and written in terms of
263+-- enumeratFromStepIntegral as we have done in unfolds. But anyway we should be
264+-- replacing the stream generation module with unfolds.
262{-# INLINE_NORMAL enumerateFromThenToIntegral #-}
265{-# INLINE_NORMAL enumerateFromThenToIntegral #-}
263enumerateFromThenToIntegral
266enumerateFromThenToIntegral
264 :: (Monad m, Integral a)
267 :: (Monad m, Integral a)
src/Streamly/Internal/Data/Unfold/Enumeration.hs+92−245
@@ -27,20 +27,15 @@ module Streamly.Internal.Data.Unfold.Enumeration
27 , enumerateFromStepNum
27 , enumerateFromStepNum
28 , enumerateFromNum
28 , enumerateFromNum
29 , enumerateFromThenNum
29 , enumerateFromThenNum
30− , enumerateFromToNum
31− , enumerateFromThenToNum
32
30
33 -- ** Enumerating unbounded 'Integral' Types
31 -- ** Enumerating unbounded 'Integral' Types
34 , enumerateFromStepIntegral
32 , enumerateFromStepIntegral
35 , enumerateFromIntegral
33 , enumerateFromIntegral
36 , enumerateFromThenIntegral
34 , enumerateFromThenIntegral
37−
38− , enumerateFromToStepIntegral
39 , enumerateFromToIntegral
35 , enumerateFromToIntegral
40 , enumerateFromThenToIntegral
36 , enumerateFromThenToIntegral
41
37
42 -- ** Enumerating 'Bounded' 'Integral' Types
38 -- ** Enumerating 'Bounded' 'Integral' Types
43− , enumerateFromStepIntegralBounded
44 , enumerateFromIntegralBounded
39 , enumerateFromIntegralBounded
45 , enumerateFromThenIntegralBounded
40 , enumerateFromThenIntegralBounded
46 , enumerateFromToIntegralBounded
41 , enumerateFromToIntegralBounded
@@ -160,61 +155,6 @@ enumerateFromThenNum =
160enumerateFromNum :: (Monad m, Num a) => Unfold m a a
155enumerateFromNum :: (Monad m, Num a) => Unfold m a a
161enumerateFromNum = lmap (\from -> (from, 1)) enumerateFromStepNum
156enumerateFromNum = lmap (\from -> (from, 1)) enumerateFromStepNum
162
157
163−-- | Generate a finite stream starting from a from and next values with
164−-- stride of (next-from) up to value. The implementation is numerically
165−-- stable for floating point values.
166−--
167−-- Note that 'enumerateFromThenToIntegral' is faster for integrals.
168−--
169−-- /Internal/
170−--
171−{-# INLINE enumerateFromThenToNum #-}
172−enumerateFromThenToNum :: (Monad m, Ord a, Fractional a) =>
173− Unfold m (a, a, a) a
174−enumerateFromThenToNum = Unfold step inject
175−
176− where
177−
178− inject (!from, !next, !to) = return (from, next - from, to, 0)
179−
180− {-# INLINE_LATE step #-}
181− step (from, stride, to, !i) = return $
182− if stride == 0
183− then if from <= to then Yield from $! (from, stride, to, i + 1) else Stop
184− else
185− if stride > 0
186− then
187− if (from + i * stride) <= to + stride / 2
188− then (Yield $! (from + i * stride)) $! (from, stride, to, i + 1)
189− else Stop
190− else
191− if (from + i * stride) >= to + stride / 2
192− then (Yield $! (from + i * stride)) $! (from, stride, to, i + 1)
193− else Stop
194−
195−-- | Generate a finite stream starting from a from till to value.
196−-- stride of value 1 will be used. The implementation is numerically
197−-- stable for floating point values.
198−--
199−-- Note that 'enumerateFromToIntegral' is faster for integrals.
200−--
201−-- /Internal/
202−--
203−{-# INLINE enumerateFromToNum #-}
204−enumerateFromToNum :: (Monad m, Ord a, Fractional a) =>
205− Unfold m (a, a) a
206−enumerateFromToNum = Unfold step inject
207−
208− where
209−
210− inject (!from, !to) = return (from, 1, to, 0)
211−
212− {-# INLINE_LATE step #-}
213− step (from, !stride, to, !i) = return $
214− if (from + i * stride) <= to + stride / 2
215− then (Yield $! (from + i * stride)) $! (from, stride, to, i + 1)
216− else Stop
217−
218------------------------------------------------------------------------------
158------------------------------------------------------------------------------
219-- Enumeration of Integrals
159-- Enumeration of Integrals
220------------------------------------------------------------------------------
160------------------------------------------------------------------------------
@@ -224,147 +164,91 @@ enumerateFromToNum = Unfold step inject
224--
164--
225-- /Internal/
165-- /Internal/
226{-# INLINE_NORMAL enumerateFromStepIntegral #-}
166{-# INLINE_NORMAL enumerateFromStepIntegral #-}
227−enumerateFromStepIntegral :: (Integral a, Monad m) => Unfold m (a, a) a
167+enumerateFromStepIntegral :: (Monad m, Integral a) => Unfold m (a, a) a
228enumerateFromStepIntegral = Unfold step inject
168enumerateFromStepIntegral = Unfold step inject
229− where
230− inject (from, next) = from `seq` next `seq` return (from, next - from)
231− {-# INLINE_LATE step #-}
232− step (x, stride) = return $ Yield x $! (x + stride, stride)
233
169
234−-- | Can be used to enumerate unbounded integrals. Starting with value from
235−-- with stride of next-from till value of to.
236−--
237−-- /Internal/
238−--
239−{-# INLINE_NORMAL enumerateFromToStepIntegral #-}
240−enumerateFromToStepIntegral :: (Integral a, Monad m) =>
241− Unfold m (a, a, a) a
242−enumerateFromToStepIntegral = Unfold step inject
243 where
170 where
244− inject (from, next, to) =
245− from `seq` next `seq` to `seq` return (from, next - from, to)
246− {-# INLINE_LATE step #-}
247− step (x, stride, to) = return $
248− if stride == 0
249− then
250− if x <= to then Yield x $! (x, stride, to) else Stop
251−
252− else
253− if stride > 0
254− then
255− if x <= to
256− then Yield x $! (x + stride, stride, to)
257− else Stop
258− else
259− if x >= to
260− then Yield x $! (x + stride, stride, to)
261− else Stop
262
171
263−------------------------------------------------------------------------------
172+ inject (from, stride) = from `seq` stride `seq` return (from, stride)
264−-- Enumeration of Bounded Integrals
265−------------------------------------------------------------------------------
266
173
267−-- | Can be used to enumerate bounded integrals from starting from with
268−-- stride of (next-from) . This check for overflow or underflow for
269−-- bounded integrals.
270−--
271−-- /Internal/
272−--
273−{-# INLINE_NORMAL enumerateFromStepIntegralBounded #-}
274−enumerateFromStepIntegralBounded ::
275− forall a m. (Integral a, Bounded a, Monad m) =>
276− Unfold m (a, a) a
277−enumerateFromStepIntegralBounded = Unfold step inject
278− where
279− inject (from, next) =
280− from `seq` next `seq` return (from, next - from)
281 {-# INLINE_LATE step #-}
174 {-# INLINE_LATE step #-}
282− step (x, stride) = return $
175+ step (x, stride) = return $ Yield x $! (x + stride, stride)
283− if stride == 0
284− then
285− Yield x $! (x, stride)
286−
287− else
288− if stride > 0
289− then
290− if x <= (maxBound :: a)
291− then Yield x $! (x + stride, stride)
292− else Stop
293− else
294− if x >= (minBound :: a)
295− then Yield x $! (x + stride, stride)
296− else Stop
297−
298−-- | Can be used to enumerate bounded integrals from starting from with
299−-- stride of (next-from) till to value. This check for overflow or underflow
300−-- for bounded integrals.
301−--
302−-- /Internal/
303−--
304−{-# INLINE_NORMAL enumerateFromToStepIntegralBounded #-}
305−enumerateFromToStepIntegralBounded ::
306− forall a m. (Integral a, Bounded a, Monad m) =>
307− Unfold m (a, a, a) a
308−enumerateFromToStepIntegralBounded = Unfold step inject
309− where
310− inject (from, next, to) =
311− from `seq` next `seq` to `seq` return (from, next - from, to)
312− {-# INLINE_LATE step #-}
313− step (x, stride, to) = return $
314− if stride == 0
315− then
316− if x <= to then Yield x $! (x, stride, to) else Stop
317−
318− else
319− if stride > 0
320− then
321− if x <= to && x <= (maxBound :: a)
322− then Yield x $! (x + stride, stride, to)
323− else Stop
324− else
325− if x >= to && x >= (minBound :: a)
326− then Yield x $! (x + stride, stride, to)
327− else Stop
328
176
329-- Enumerate Unbounded Integrals ----------------------------------------------
177-- Enumerate Unbounded Integrals ----------------------------------------------
330{-# INLINE enumerateFromIntegral #-}
178{-# INLINE enumerateFromIntegral #-}
331enumerateFromIntegral :: (Monad m, Integral a) => Unfold m a a
179enumerateFromIntegral :: (Monad m, Integral a) => Unfold m a a
332−enumerateFromIntegral = lmap (\a -> (a, a + 1)) enumerateFromStepIntegral
180+enumerateFromIntegral = lmap (\from -> (from, 1)) enumerateFromStepIntegral
333
181
334{-# INLINE enumerateFromThenIntegral #-}
182{-# INLINE enumerateFromThenIntegral #-}
335enumerateFromThenIntegral :: (Monad m, Integral a ) => Unfold m (a, a) a
183enumerateFromThenIntegral :: (Monad m, Integral a ) => Unfold m (a, a) a
336−enumerateFromThenIntegral = enumerateFromStepIntegral
184+enumerateFromThenIntegral =
185+ lmap (\(from, next) -> (from, next - from)) enumerateFromStepIntegral
337
186
338{-# INLINE enumerateFromToIntegral #-}
187{-# INLINE enumerateFromToIntegral #-}
339enumerateFromToIntegral :: (Monad m, Integral a) => Unfold m (a, a) a
188enumerateFromToIntegral :: (Monad m, Integral a) => Unfold m (a, a) a
340−enumerateFromToIntegral = lmap (\(a, c) -> (a, a + 1, c)) enumerateFromToStepIntegral
189+enumerateFromToIntegral =
190+ takeWhileMWithInput (\(_, to) b -> return $ b <= to)
191+ $ lmap (\(from, _) -> (from, 1)) enumerateFromStepIntegral
341
192
342{-# INLINE enumerateFromThenToIntegral #-}
193{-# INLINE enumerateFromThenToIntegral #-}
343enumerateFromThenToIntegral :: (Monad m, Integral a) => Unfold m (a, a, a) a
194enumerateFromThenToIntegral :: (Monad m, Integral a) => Unfold m (a, a, a) a
344−enumerateFromThenToIntegral = enumerateFromToStepIntegral
195+enumerateFromThenToIntegral =
196+ takeWhileMWithInput cond $ lmap toFromStep enumerateFromStepIntegral
197+
198+ where
199+
200+ toFromStep (from, next, _) = (from, next - from)
201+
202+ cond (from, next, to) b =
203+ return
204+ $ if next >= from
205+ then b <= to
206+ else b >= to
345
207
346-- Enumerate Bounded Integrals ------------------------------------------------
208-- Enumerate Bounded Integrals ------------------------------------------------
347{-# INLINE enumerateFromIntegralBounded #-}
209{-# INLINE enumerateFromIntegralBounded #-}
348−enumerateFromIntegralBounded :: (Monad m, Bounded a, Integral a) =>
210+enumerateFromIntegralBounded :: (Monad m, Integral a, Bounded a) =>
349 Unfold m a a
211 Unfold m a a
350−enumerateFromIntegralBounded =
212+enumerateFromIntegralBounded = supplySecond maxBound enumerateFromToIntegral
351− lmap (\a -> (a, a + 1, maxBound)) enumerateFromToStepIntegralBounded
352
213
353{-# INLINE enumerateFromThenIntegralBounded #-}
214{-# INLINE enumerateFromThenIntegralBounded #-}
354−enumerateFromThenIntegralBounded :: (Monad m, Bounded a, Integral a ) =>
215+enumerateFromThenIntegralBounded :: (Monad m, Integral a, Bounded a ) =>
355 Unfold m (a, a) a
216 Unfold m (a, a) a
356−enumerateFromThenIntegralBounded = enumerateFromStepIntegralBounded
217+enumerateFromThenIntegralBounded =
218+ takeWhileMWithInput cond $ lmap toFromStep enumerateFromStepIntegral
219+
220+ where
221+
222+ toFromStep (from, next) = (from, next - from)
223+
224+ cond (from, next) b =
225+ return
226+ $ if next >= from
227+ then b <= maxBound
228+ else b >= minBound
357
229
358{-# INLINE enumerateFromToIntegralBounded #-}
230{-# INLINE enumerateFromToIntegralBounded #-}
359enumerateFromToIntegralBounded :: (Monad m, Integral a, Bounded a) =>
231enumerateFromToIntegralBounded :: (Monad m, Integral a, Bounded a) =>
360 Unfold m (a, a) a
232 Unfold m (a, a) a
361enumerateFromToIntegralBounded =
233enumerateFromToIntegralBounded =
362− lmap (\(a, c) -> (a, a + 1, c)) enumerateFromToStepIntegralBounded
234+ takeWhileMWithInput (\(_, to) b -> return $ b <= to)
235+ $ lmap fst enumerateFromIntegralBounded
363
236
364{-# INLINE enumerateFromThenToIntegralBounded #-}
237{-# INLINE enumerateFromThenToIntegralBounded #-}
365enumerateFromThenToIntegralBounded :: (Monad m, Integral a, Bounded a) =>
238enumerateFromThenToIntegralBounded :: (Monad m, Integral a, Bounded a) =>
366 Unfold m (a, a, a) a
239 Unfold m (a, a, a) a
367−enumerateFromThenToIntegralBounded = enumerateFromToStepIntegralBounded
240+enumerateFromThenToIntegralBounded =
241+ takeWhileMWithInput cond $ lmap toFromThen enumerateFromThenIntegralBounded
242+
243+ where
244+
245+ toFromThen (from, next, _) = (from, next)
246+
247+ cond (from, next, to) b =
248+ return
249+ $ if next >= from
250+ then b <= to
251+ else b >= to
368
252
369------------------------------------------------------------------------------
253------------------------------------------------------------------------------
370-- Enumeration of Fractionals
254-- Enumeration of Fractionals
@@ -378,23 +262,41 @@ enumerateFromFractional = enumerateFromNum
378enumerateFromThenFractional :: (Monad m, Fractional a) => Unfold m (a, a) a
262enumerateFromThenFractional :: (Monad m, Fractional a) => Unfold m (a, a) a
379enumerateFromThenFractional = enumerateFromThenNum
263enumerateFromThenFractional = enumerateFromThenNum
380
264
265+-- | Same as 'enumerateFromStepNum' with a step of 1 and enumerating up to the
266+-- specified upper limit rounded to the nearest integral value:
267+--
268+-- >>> enumerateFromToFractional =
269+--
270+-- /Internal/
271+--
381{-# INLINE_NORMAL enumerateFromToFractional #-}
272{-# INLINE_NORMAL enumerateFromToFractional #-}
382enumerateFromToFractional :: (Monad m, Fractional a, Ord a) =>
273enumerateFromToFractional :: (Monad m, Fractional a, Ord a) =>
383 Unfold m (a, a) a
274 Unfold m (a, a) a
384−enumerateFromToFractional = enumerateFromToNum
275+enumerateFromToFractional =
276+ takeWhileMWithInput (\(_, to) b -> return $ b <= to + 1 / 2)
277+ $ lmap (\(from, _) -> (from, 1)) enumerateFromStepNum
385
278
386−{-# INLINE_NORMAL enumerateFromThenToFractional #-}
279+{-# INLINE enumerateFromThenToFractional #-}
387enumerateFromThenToFractional :: (Monad m, Fractional a, Ord a) =>
280enumerateFromThenToFractional :: (Monad m, Fractional a, Ord a) =>
388 Unfold m (a, a, a) a
281 Unfold m (a, a, a) a
389−enumerateFromThenToFractional = enumerateFromThenToNum
282+enumerateFromThenToFractional =
283+ takeWhileMWithInput cond $ lmap toFromStep enumerateFromStepNum
284+
285+ where
286+
287+ toFromStep (from, next, _) = (from, next - from)
288+
289+ cond (from, next, to) b =
290+ let stride = next - from
291+ in return
292+ $ if next >= from
293+ then b <= to + stride / 2
294+ else b >= to + stride / 2
390
295
391-------------------------------------------------------------------------------
296-------------------------------------------------------------------------------
392-- Enumeration of Enum types not larger than Int
297-- Enumeration of Enum types not larger than Int
393-------------------------------------------------------------------------------
298-------------------------------------------------------------------------------
394
299
395−-- XXX should we check for bounds here? Otherwise it will cycle back to "to" if
396−-- to is smaller?
397−--
398-- | Enumerate from given starting Enum value 'from' and to Enum value 'to'
300-- | Enumerate from given starting Enum value 'from' and to Enum value 'to'
399-- with stride of 1 till to value.
301-- with stride of 1 till to value.
400--
302--
@@ -402,16 +304,8 @@ enumerateFromThenToFractional = enumerateFromThenToNum
402--
304--
403{-# INLINE enumerateFromToSmall #-}
305{-# INLINE enumerateFromToSmall #-}
404enumerateFromToSmall :: (Monad m, Enum a) => Unfold m (a, a) a
306enumerateFromToSmall :: (Monad m, Enum a) => Unfold m (a, a) a
405−enumerateFromToSmall = map toEnum $
307+enumerateFromToSmall =
406− Unfold step inject
308+ fmap toEnum (lmap (bimap fromEnum fromEnum) enumerateFromToIntegral)
407− where
408− inject (from, to) =
409− fromEnum from
410− `seq` fromEnum to
411− `seq` return (fromEnum from, 1, fromEnum to)
412− {-# INLINE_LATE step #-}
413− step (x, stride, to) = return $
414− if x <= to then Yield x $! (x + stride, stride, to) else Stop
415
309
416-- | Enumerate from given starting Enum value 'from' and then Enum value 'next'
310-- | Enumerate from given starting Enum value 'from' and then Enum value 'next'
417-- and to Enum value 'to' with stride of (fromEnum next - fromEnum from)
311-- and to Enum value 'to' with stride of (fromEnum next - fromEnum from)
@@ -421,31 +315,9 @@ enumerateFromToSmall = map toEnum $
421--
315--
422{-# INLINE enumerateFromThenToSmall #-}
316{-# INLINE enumerateFromThenToSmall #-}
423enumerateFromThenToSmall :: (Monad m, Enum a) => Unfold m (a, a, a) a
317enumerateFromThenToSmall :: (Monad m, Enum a) => Unfold m (a, a, a) a
424−enumerateFromThenToSmall = map toEnum $
318+enumerateFromThenToSmall =
425− Unfold step inject
319+ let toInts (x, y, z) = (fromEnum x, fromEnum y, fromEnum z)
426− where
320+ in fmap toEnum (lmap toInts enumerateFromThenToIntegral)
427− inject (from, next, to) =
428− fromEnum from
429− `seq` fromEnum next
430− `seq` fromEnum to
431− `seq` return
432− (fromEnum from, fromEnum next - fromEnum from, fromEnum to)
433− {-# INLINE_LATE step #-}
434− step (x, stride, to) = return $
435− if stride == 0
436− then
437− if x <= to then Yield x $! (x, stride, to) else Stop
438−
439− else
440− if stride > 0
441− then
442− if x <= to
443− then Yield x $! (x + stride, stride, to)
444− else Stop
445− else
446− if x >= 0 && x >= to
447− then Yield x $! (x + stride, stride, to)
448− else Stop
449
321
450-------------------------------------------------------------------------------
322-------------------------------------------------------------------------------
451-- Bounded Enumeration of Enum types not larger than Int
323-- Bounded Enumeration of Enum types not larger than Int
@@ -457,16 +329,8 @@ enumerateFromThenToSmall = map toEnum $
457-- /Internal/
329-- /Internal/
458--
330--
459{-# INLINE enumerateFromSmallBounded #-}
331{-# INLINE enumerateFromSmallBounded #-}
460−enumerateFromSmallBounded :: forall a m. (Monad m, Bounded a, Enum a) => Unfold m a a
332+enumerateFromSmallBounded :: (Monad m, Enum a, Bounded a) => Unfold m a a
461−enumerateFromSmallBounded = map toEnum $
333+enumerateFromSmallBounded = supplySecond maxBound enumerateFromToSmall
462− Unfold step inject
463− where
464− inject from =
465− fromEnum from
466− `seq` return (fromEnum from, 1, fromEnum (maxBound :: a))
467− {-# INLINE_LATE step #-}
468− step (x, stride, to) = return $
469− if x <= to then Yield x $! (x + stride, stride, to) else Stop
470
334
471-- | Enumerate from given starting Enum value 'from' and next Enum value 'next'
335-- | Enumerate from given starting Enum value 'from' and next Enum value 'next'
472-- with stride of (fromEnum next - fromEnum from) till maxBound.
336-- with stride of (fromEnum next - fromEnum from) till maxBound.
@@ -474,35 +338,18 @@ enumerateFromSmallBounded = map toEnum $
474-- /Internal/
338-- /Internal/
475--
339--
476{-# INLINE enumerateFromThenSmallBounded #-}
340{-# INLINE enumerateFromThenSmallBounded #-}
477−enumerateFromThenSmallBounded :: forall a m. (Monad m, Bounded a, Enum a) =>
341+enumerateFromThenSmallBounded :: forall m a. (Monad m, Enum a, Bounded a) =>
478 Unfold m (a, a) a
342 Unfold m (a, a) a
479−enumerateFromThenSmallBounded = map toEnum $
343+enumerateFromThenSmallBounded =
480− Unfold step inject
481− where
482− inject (from, next) =
344+ let adapt (from, next) =
483− fromEnum from
484− `seq` fromEnum next
485− `seq` return
486− ( fromEnum from
345+ let frm = fromEnum from
487− , fromEnum next - fromEnum from
488− , fromEnum (maxBound :: a)
346+ nxt = fromEnum next
489− )
347+ stride = nxt - frm
490− {-# INLINE_LATE step #-}
348+ to = if stride >= 0
491− step (x, stride, to) = return $
349+ then fromEnum (maxBound :: a)
492− if stride == 0
350+ else fromEnum (minBound :: a)
493− then
351+ in (frm, nxt, to)
494− if x <= to then Yield x $! (x, stride, to) else Stop
352+ in fmap toEnum (lmap adapt enumerateFromThenToIntegral)
495−
496− else
497− if stride > 0
498− then
499− if x <= to
500− then Yield x $! (x + stride, stride, to)
501− else Stop
502− else
503− if x >= 0
504− then Yield x $! (x + stride, stride, to)
505− else Stop
506
353
507-------------------------------------------------------------------------------
354-------------------------------------------------------------------------------
508-- Enumerable type class
355-- Enumerable type class