on 2ea9fb0 help sign in
591 lines 22 kB history raw
1-- |
2-- Module : Streamly.Internal.Data.Stream.Enumeration
3-- Copyright : (c) 2018 Composewell Technologies
4--
5-- License : BSD3
6-- Maintainer : streamly@composewell.com
7-- Stability : experimental
8-- Portability : GHC
9--
10-- The functions defined in this module should be rarely needed for direct use,
11-- try to use the operations from the 'Enumerable' type class
12-- instances instead.
13--
14-- This module provides an 'Enumerable' type class to enumerate 'Enum' types
15-- into a stream. The operations in this type class correspond to similar
16-- perations in the 'Enum' type class, the only difference is that they produce
17-- a stream instead of a list. These operations cannot be defined generically
18-- based on the 'Enum' type class. We provide instances for commonly used
19-- types. If instances for other types are needed convenience functions defined
20-- in this module can be used to define them. Alternatively, these functions
21-- can be used directly.
23module Streamly.Internal.Data.Stream.IsStream.Enumeration
24 (
25 Enumerable (..)
27 -- ** Enumerating 'Bounded' 'Enum' Types
28 , enumerate
29 , enumerateTo
30 , enumerateFromBounded
32 -- ** Enumerating 'Enum' Types not larger than 'Int'
33 , enumerateFromToSmall
34 , enumerateFromThenToSmall
35 , enumerateFromThenSmallBounded
37 -- ** Enumerating 'Bounded' 'Integral' Types
38 , enumerateFromIntegral
39 , enumerateFromThenIntegral
41 -- ** Enumerating 'Integral' Types
42 , enumerateFromToIntegral
43 , enumerateFromThenToIntegral
45 -- ** Enumerating unbounded 'Integral' Types
46 , enumerateFromStepIntegral
48 -- ** Enumerating 'Fractional' Types
49 , enumerateFromFractional
50 , enumerateFromToFractional
51 , enumerateFromThenFractional
52 , enumerateFromThenToFractional
53 )
54where
56import Data.Fixed
57import Data.Int
58import Data.Ratio
59import Data.Word
60import Numeric.Natural
61import Data.Functor.Identity (Identity(..))
63import Streamly.Internal.Data.Stream.IsStream.Type (IsStream(..), fromStreamD)
65import qualified Streamly.Internal.Data.Stream.IsStream.Type as IsStream
66import qualified Streamly.Internal.Data.Stream.StreamD as D
67 ( enumerateFromNum
68 , enumerateFromThenNum
69 , enumerateFromThenToIntegral
70 , enumerateFromThenIntegral
71 , enumerateFromStepIntegral
72 , enumerateFromToIntegral
73 , enumerateFromIntegral
74 , enumerateFromToFractional
75 , enumerateFromThenToFractional
76 )
77import qualified Streamly.Internal.Data.Stream.Serial as Serial (map)
79-- $setup
80-- >>> import Streamly.Prelude as Stream
81-- >>> import Streamly.Internal.Data.Stream.IsStream.Enumeration as Stream
83-------------------------------------------------------------------------------
84-- Enumeration of Integral types
85-------------------------------------------------------------------------------
86--
87-- | @enumerateFromStepIntegral from step@ generates an infinite stream whose
88-- first element is @from@ and the successive elements are in increments of
89-- @step@.
90--
91-- CAUTION: This function is not safe for finite integral types. It does not
92-- check for overflow, underflow or bounds.
93--
94-- @
95-- >>> Stream.toList $ Stream.take 4 $ Stream.enumerateFromStepIntegral 0 2
96-- [0,2,4,6]
97--
98-- >>> Stream.toList $ Stream.take 3 $ Stream.enumerateFromStepIntegral 0 (-2)
99-- [0,-2,-4]
100--
101-- @
102--
103-- @since 0.6.0
104{-# INLINE enumerateFromStepIntegral #-}
105enumerateFromStepIntegral
106 :: (IsStream t, Monad m, Integral a)
107 => a -> a -> t m a
108enumerateFromStepIntegral from stride =
109 fromStreamD $ D.enumerateFromStepIntegral from stride
111-- | Enumerate an 'Integral' type. @enumerateFromIntegral from@ generates a
112-- stream whose first element is @from@ and the successive elements are in
113-- increments of @1@. The stream is bounded by the size of the 'Integral' type.
114--
115-- @
116-- >>> Stream.toList $ Stream.take 4 $ Stream.enumerateFromIntegral (0 :: Int)
117-- [0,1,2,3]
118--
119-- @
120--
121-- @since 0.6.0
122{-# INLINE enumerateFromIntegral #-}
123enumerateFromIntegral
124 :: (IsStream t, Monad m, Integral a, Bounded a)
125 => a -> t m a
126enumerateFromIntegral from = fromStreamD $ D.enumerateFromIntegral from
128-- | Enumerate an 'Integral' type in steps. @enumerateFromThenIntegral from
129-- then@ generates a stream whose first element is @from@, the second element
130-- is @then@ and the successive elements are in increments of @then - from@.
131-- The stream is bounded by the size of the 'Integral' type.
132--
133-- @
134-- >>> Stream.toList $ Stream.take 4 $ Stream.enumerateFromThenIntegral (0 :: Int) 2
135-- [0,2,4,6]
136--
137-- >>> Stream.toList $ Stream.take 4 $ Stream.enumerateFromThenIntegral (0 :: Int) (-2)
138-- [0,-2,-4,-6]
139--
140-- @
141--
142-- @since 0.6.0
143{-# INLINE enumerateFromThenIntegral #-}
144enumerateFromThenIntegral
145 :: (IsStream t, Monad m, Integral a, Bounded a)
146 => a -> a -> t m a
147enumerateFromThenIntegral from next =
148 fromStreamD $ D.enumerateFromThenIntegral from next
150-- | Enumerate an 'Integral' type up to a given limit.
151-- @enumerateFromToIntegral from to@ generates a finite stream whose first
152-- element is @from@ and successive elements are in increments of @1@ up to
153-- @to@.
154--
155-- @
156-- >>> Stream.toList $ Stream.enumerateFromToIntegral 0 4
157-- [0,1,2,3,4]
158--
159-- @
160--
161-- @since 0.6.0
162{-# INLINE enumerateFromToIntegral #-}
163enumerateFromToIntegral :: (IsStream t, Monad m, Integral a) => a -> a -> t m a
164enumerateFromToIntegral from to =
165 fromStreamD $ D.enumerateFromToIntegral from to
167-- | Enumerate an 'Integral' type in steps up to a given limit.
168-- @enumerateFromThenToIntegral from then to@ generates a finite stream whose
169-- first element is @from@, the second element is @then@ and the successive
170-- elements are in increments of @then - from@ up to @to@.
171--
172-- @
173-- >>> Stream.toList $ Stream.enumerateFromThenToIntegral 0 2 6
174-- [0,2,4,6]
175--
176-- >>> Stream.toList $ Stream.enumerateFromThenToIntegral 0 (-2) (-6)
177-- [0,-2,-4,-6]
178--
179-- @
180--
181-- @since 0.6.0
182{-# INLINE enumerateFromThenToIntegral #-}
183enumerateFromThenToIntegral
184 :: (IsStream t, Monad m, Integral a)
185 => a -> a -> a -> t m a
186enumerateFromThenToIntegral from next to =
187 fromStreamD $ D.enumerateFromThenToIntegral from next to
189-------------------------------------------------------------------------------
190-- Enumeration of Fractional types
191-------------------------------------------------------------------------------
192--
193-- Even though the underlying implementation of enumerateFromFractional and
194-- enumerateFromThenFractional works for any 'Num' we have restricted these to
195-- 'Fractional' because these do not perform any bounds check, in contrast to
196-- integral versions and are therefore not equivalent substitutes for those.
197--
198-- | Numerically stable enumeration from a 'Fractional' number in steps of size
199-- @1@. @enumerateFromFractional from@ generates a stream whose first element
200-- is @from@ and the successive elements are in increments of @1@. No overflow
201-- or underflow checks are performed.
202--
203-- This is the equivalent to 'enumFrom' for 'Fractional' types. For example:
204--
205-- @
206-- >>> Stream.toList $ Stream.take 4 $ Stream.enumerateFromFractional 1.1
207-- [1.1,2.1,3.1,4.1]
208--
209-- @
210--
211--
212-- @since 0.6.0
213{-# INLINE enumerateFromFractional #-}
214enumerateFromFractional :: (IsStream t, Monad m, Fractional a) => a -> t m a
215enumerateFromFractional from = fromStreamD $ D.enumerateFromNum from
217-- | Numerically stable enumeration from a 'Fractional' number in steps.
218-- @enumerateFromThenFractional from then@ generates a stream whose first
219-- element is @from@, the second element is @then@ and the successive elements
220-- are in increments of @then - from@. No overflow or underflow checks are
221-- performed.
222--
223-- This is the equivalent of 'enumFromThen' for 'Fractional' types. For
224-- example:
225--
226-- @
227-- >>> Stream.toList $ Stream.take 4 $ Stream.enumerateFromThenFractional 1.1 2.1
228-- [1.1,2.1,3.1,4.1]
229--
230-- >>> Stream.toList $ Stream.take 4 $ Stream.enumerateFromThenFractional 1.1 (-2.1)
231-- [1.1,-2.1,-5.300000000000001,-8.500000000000002]
232--
233-- @
234--
235-- @since 0.6.0
236{-# INLINE enumerateFromThenFractional #-}
237enumerateFromThenFractional
238 :: (IsStream t, Monad m, Fractional a)
239 => a -> a -> t m a
240enumerateFromThenFractional from next = fromStreamD $ D.enumerateFromThenNum from next
242-- | Numerically stable enumeration from a 'Fractional' number to a given
243-- limit. @enumerateFromToFractional from to@ generates a finite stream whose
244-- first element is @from@ and successive elements are in increments of @1@ up
245-- to @to@.
246--
247-- This is the equivalent of 'enumFromTo' for 'Fractional' types. For
248-- example:
249--
250-- @
251-- >>> Stream.toList $ Stream.enumerateFromToFractional 1.1 4
252-- [1.1,2.1,3.1,4.1]
253--
254-- >>> Stream.toList $ Stream.enumerateFromToFractional 1.1 4.6
255-- [1.1,2.1,3.1,4.1,5.1]
256--
257-- @
258--
259-- Notice that the last element is equal to the specified @to@ value after
260-- rounding to the nearest integer.
261--
262-- @since 0.6.0
263{-# INLINE enumerateFromToFractional #-}
264enumerateFromToFractional
265 :: (IsStream t, Monad m, Fractional a, Ord a)
266 => a -> a -> t m a
267enumerateFromToFractional from to =
268 fromStreamD $ D.enumerateFromToFractional from to
270-- | Numerically stable enumeration from a 'Fractional' number in steps up to a
271-- given limit. @enumerateFromThenToFractional from then to@ generates a
272-- finite stream whose first element is @from@, the second element is @then@
273-- and the successive elements are in increments of @then - from@ up to @to@.
274--
275-- This is the equivalent of 'enumFromThenTo' for 'Fractional' types. For
276-- example:
277--
278-- @
279-- >>> Stream.toList $ Stream.enumerateFromThenToFractional 0.1 2 6
280-- [0.1,2.0,3.9,5.799999999999999]
281--
282-- >>> Stream.toList $ Stream.enumerateFromThenToFractional 0.1 (-2) (-6)
283-- [0.1,-2.0,-4.1000000000000005,-6.200000000000001]
284--
285-- @
286--
287--
288-- @since 0.6.0
289{-# INLINE enumerateFromThenToFractional #-}
290enumerateFromThenToFractional
291 :: (IsStream t, Monad m, Fractional a, Ord a)
292 => a -> a -> a -> t m a
293enumerateFromThenToFractional from next to =
294 fromStreamD $ D.enumerateFromThenToFractional from next to
296-------------------------------------------------------------------------------
297-- Enumeration of Enum types not larger than Int
298-------------------------------------------------------------------------------
299--
300-- | 'enumerateFromTo' for 'Enum' types not larger than 'Int'.
301--
302-- @since 0.6.0
303{-# INLINE enumerateFromToSmall #-}
304enumerateFromToSmall :: (IsStream t, Monad m, Enum a) => a -> a -> t m a
305enumerateFromToSmall from to =
306 IsStream.fromSerial
307 $ Serial.map toEnum
308 $ enumerateFromToIntegral (fromEnum from) (fromEnum to)
310-- | 'enumerateFromThenTo' for 'Enum' types not larger than 'Int'.
311--
312-- @since 0.6.0
313{-# INLINE enumerateFromThenToSmall #-}
314enumerateFromThenToSmall :: (IsStream t, Monad m, Enum a)
315 => a -> a -> a -> t m a
316enumerateFromThenToSmall from next to =
317 IsStream.fromSerial
318 $ Serial.map toEnum
319 $ enumerateFromThenToIntegral
320 (fromEnum from) (fromEnum next) (fromEnum to)
322-- | 'enumerateFromThen' for 'Enum' types not larger than 'Int'.
323--
324-- Note: We convert the 'Enum' to 'Int' and enumerate the 'Int'. If a
325-- type is bounded but does not have a 'Bounded' instance then we can go on
326-- enumerating it beyond the legal values of the type, resulting in the failure
327-- of 'toEnum' when converting back to 'Enum'. Therefore we require a 'Bounded'
328-- instance for this function to be safely used.
329--
330-- @since 0.6.0
331{-# INLINE enumerateFromThenSmallBounded #-}
332enumerateFromThenSmallBounded :: (IsStream t, Monad m, Enumerable a, Bounded a)
333 => a -> a -> t m a
334enumerateFromThenSmallBounded from next =
335 if fromEnum next >= fromEnum from
336 then enumerateFromThenTo from next maxBound
337 else enumerateFromThenTo from next minBound
339-------------------------------------------------------------------------------
340-- Enumerable type class
341-------------------------------------------------------------------------------
342--
343-- NOTE: We would like to rewrite calls to fromList [1..] etc. to stream
344-- enumerations like this:
345--
346-- {-# RULES "fromList enumFrom" [1]
347-- forall (a :: Int). D.fromList (enumFrom a) = D.enumerateFromIntegral a #-}
348--
349-- But this does not work because enumFrom is a class method and GHC rewrites
350-- it quickly, so we do not get a chance to have our rule fired.
352-- | Types that can be enumerated as a stream. The operations in this type
353-- class are equivalent to those in the 'Enum' type class, except that these
354-- generate a stream instead of a list. Use the functions in
355-- "Streamly.Internal.Data.Stream.Enumeration" module to define new instances.
356--
357-- @since 0.6.0
358class Enum a => Enumerable a where
359 -- | @enumerateFrom from@ generates a stream starting with the element
360 -- @from@, enumerating up to 'maxBound' when the type is 'Bounded' or
361 -- generating an infinite stream when the type is not 'Bounded'.
362 --
363 -- @
364 -- >>> Stream.toList $ Stream.take 4 $ Stream.enumerateFrom (0 :: Int)
365 -- [0,1,2,3]
366 --
367 -- @
368 --
369 -- For 'Fractional' types, enumeration is numerically stable. However, no
370 -- overflow or underflow checks are performed.
371 --
372 -- @
373 -- >>> Stream.toList $ Stream.take 4 $ Stream.enumerateFrom 1.1
374 -- [1.1,2.1,3.1,4.1]
375 --
376 -- @
377 --
378 -- @since 0.6.0
379 enumerateFrom :: (IsStream t, Monad m) => a -> t m a
381 -- | Generate a finite stream starting with the element @from@, enumerating
382 -- the type up to the value @to@. If @to@ is smaller than @from@ then an
383 -- empty stream is returned.
384 --
385 -- @
386 -- >>> Stream.toList $ Stream.enumerateFromTo 0 4
387 -- [0,1,2,3,4]
388 --
389 -- @
390 --
391 -- For 'Fractional' types, the last element is equal to the specified @to@
392 -- value after rounding to the nearest integral value.
393 --
394 -- @
395 -- >>> Stream.toList $ Stream.enumerateFromTo 1.1 4
396 -- [1.1,2.1,3.1,4.1]
397 --
398 -- >>> Stream.toList $ Stream.enumerateFromTo 1.1 4.6
399 -- [1.1,2.1,3.1,4.1,5.1]
400 --
401 -- @
402 --
403 -- @since 0.6.0
404 enumerateFromTo :: (IsStream t, Monad m) => a -> a -> t m a
406 -- | @enumerateFromThen from then@ generates a stream whose first element
407 -- is @from@, the second element is @then@ and the successive elements are
408 -- in increments of @then - from@. Enumeration can occur downwards or
409 -- upwards depending on whether @then@ comes before or after @from@. For
410 -- 'Bounded' types the stream ends when 'maxBound' is reached, for
411 -- unbounded types it keeps enumerating infinitely.
412 --
413 -- @
414 -- >>> Stream.toList $ Stream.take 4 $ Stream.enumerateFromThen 0 2
415 -- [0,2,4,6]
416 --
417 -- >>> Stream.toList $ Stream.take 4 $ Stream.enumerateFromThen 0 (-2)
418 -- [0,-2,-4,-6]
419 --
420 -- @
421 --
422 -- @since 0.6.0
423 enumerateFromThen :: (IsStream t, Monad m) => a -> a -> t m a
425 -- | @enumerateFromThenTo from then to@ generates a finite stream whose
426 -- first element is @from@, the second element is @then@ and the successive
427 -- elements are in increments of @then - from@ up to @to@. Enumeration can
428 -- occur downwards or upwards depending on whether @then@ comes before or
429 -- after @from@.
430 --
431 -- @
432 -- >>> Stream.toList $ Stream.enumerateFromThenTo 0 2 6
433 -- [0,2,4,6]
434 --
435 -- >>> Stream.toList $ Stream.enumerateFromThenTo 0 (-2) (-6)
436 -- [0,-2,-4,-6]
437 --
438 -- @
439 --
440 -- @since 0.6.0
441 enumerateFromThenTo :: (IsStream t, Monad m) => a -> a -> a -> t m a
443-- MAYBE: Sometimes it is more convenient to know the count rather then the
444-- ending or starting element. For those cases we can define the folllowing
445-- APIs. All of these will work only for bounded types if we represent the
446-- count by Int.
447--
448-- enumerateN
449-- enumerateFromN
450-- enumerateToN
451-- enumerateFromStep
452-- enumerateFromStepN
454-------------------------------------------------------------------------------
455-- Convenient functions for bounded types
456-------------------------------------------------------------------------------
457--
458-- |
459-- > enumerate = enumerateFrom minBound
460--
461-- Enumerate a 'Bounded' type from its 'minBound' to 'maxBound'
462--
463-- @since 0.6.0
464{-# INLINE enumerate #-}
465enumerate :: (IsStream t, Monad m, Bounded a, Enumerable a) => t m a
466enumerate = enumerateFrom minBound
468-- |
469-- > enumerateTo = enumerateFromTo minBound
470--
471-- Enumerate a 'Bounded' type from its 'minBound' to specified value.
472--
473-- @since 0.6.0
474{-# INLINE enumerateTo #-}
475enumerateTo :: (IsStream t, Monad m, Bounded a, Enumerable a) => a -> t m a
476enumerateTo = enumerateFromTo minBound
478-- |
479-- > enumerateFromBounded = enumerateFromTo from maxBound
480--
481-- 'enumerateFrom' for 'Bounded' 'Enum' types.
482--
483-- @since 0.6.0
484{-# INLINE enumerateFromBounded #-}
485enumerateFromBounded :: (IsStream t, Monad m, Enumerable a, Bounded a)
486 => a -> t m a
487enumerateFromBounded from = enumerateFromTo from maxBound
489-------------------------------------------------------------------------------
490-- Enumerable Instances
491-------------------------------------------------------------------------------
492--
493-- For Enum types smaller than or equal to Int size.
494#define ENUMERABLE_BOUNDED_SMALL(SMALL_TYPE) \
495instance Enumerable SMALL_TYPE where { \
496 {-# INLINE enumerateFrom #-}; \
497 enumerateFrom = enumerateFromBounded; \
498 {-# INLINE enumerateFromThen #-}; \
499 enumerateFromThen = enumerateFromThenSmallBounded; \
500 {-# INLINE enumerateFromTo #-}; \
501 enumerateFromTo = enumerateFromToSmall; \
502 {-# INLINE enumerateFromThenTo #-}; \
503 enumerateFromThenTo = enumerateFromThenToSmall }
506ENUMERABLE_BOUNDED_SMALL(())
507ENUMERABLE_BOUNDED_SMALL(Bool)
508ENUMERABLE_BOUNDED_SMALL(Ordering)
509ENUMERABLE_BOUNDED_SMALL(Char)
511-- For bounded Integral Enum types, may be larger than Int.
512#define ENUMERABLE_BOUNDED_INTEGRAL(INTEGRAL_TYPE) \
513instance Enumerable INTEGRAL_TYPE where { \
514 {-# INLINE enumerateFrom #-}; \
515 enumerateFrom = enumerateFromIntegral; \
516 {-# INLINE enumerateFromThen #-}; \
517 enumerateFromThen = enumerateFromThenIntegral; \
518 {-# INLINE enumerateFromTo #-}; \
519 enumerateFromTo = enumerateFromToIntegral; \
520 {-# INLINE enumerateFromThenTo #-}; \
521 enumerateFromThenTo = enumerateFromThenToIntegral }
523ENUMERABLE_BOUNDED_INTEGRAL(Int)
524ENUMERABLE_BOUNDED_INTEGRAL(Int8)
525ENUMERABLE_BOUNDED_INTEGRAL(Int16)
526ENUMERABLE_BOUNDED_INTEGRAL(Int32)
527ENUMERABLE_BOUNDED_INTEGRAL(Int64)
528ENUMERABLE_BOUNDED_INTEGRAL(Word)
529ENUMERABLE_BOUNDED_INTEGRAL(Word8)
530ENUMERABLE_BOUNDED_INTEGRAL(Word16)
531ENUMERABLE_BOUNDED_INTEGRAL(Word32)
532ENUMERABLE_BOUNDED_INTEGRAL(Word64)
534-- For unbounded Integral Enum types.
535#define ENUMERABLE_UNBOUNDED_INTEGRAL(INTEGRAL_TYPE) \
536instance Enumerable INTEGRAL_TYPE where { \
537 {-# INLINE enumerateFrom #-}; \
538 enumerateFrom from = enumerateFromStepIntegral from 1; \
539 {-# INLINE enumerateFromThen #-}; \
540 enumerateFromThen from next = \
541 enumerateFromStepIntegral from (next - from); \
542 {-# INLINE enumerateFromTo #-}; \
543 enumerateFromTo = enumerateFromToIntegral; \
544 {-# INLINE enumerateFromThenTo #-}; \
545 enumerateFromThenTo = enumerateFromThenToIntegral }
547ENUMERABLE_UNBOUNDED_INTEGRAL(Integer)
548ENUMERABLE_UNBOUNDED_INTEGRAL(Natural)
550#define ENUMERABLE_FRACTIONAL(FRACTIONAL_TYPE,CONSTRAINT) \
551instance (CONSTRAINT) => Enumerable FRACTIONAL_TYPE where { \
552 {-# INLINE enumerateFrom #-}; \
553 enumerateFrom = enumerateFromFractional; \
554 {-# INLINE enumerateFromThen #-}; \
555 enumerateFromThen = enumerateFromThenFractional; \
556 {-# INLINE enumerateFromTo #-}; \
557 enumerateFromTo = enumerateFromToFractional; \
558 {-# INLINE enumerateFromThenTo #-}; \
559 enumerateFromThenTo = enumerateFromThenToFractional }
561ENUMERABLE_FRACTIONAL(Float,)
562ENUMERABLE_FRACTIONAL(Double,)
563ENUMERABLE_FRACTIONAL((Fixed a),HasResolution a)
564ENUMERABLE_FRACTIONAL((Ratio a),Integral a)
566instance Enumerable a => Enumerable (Identity a) where
567 {-# INLINE enumerateFrom #-}
568 enumerateFrom (Identity from) =
569 IsStream.fromSerial $ Serial.map Identity $ enumerateFrom from
570 {-# INLINE enumerateFromThen #-}
571 enumerateFromThen (Identity from) (Identity next) =
572 IsStream.fromSerial $ Serial.map Identity $ enumerateFromThen from next
573 {-# INLINE enumerateFromTo #-}
574 enumerateFromTo (Identity from) (Identity to) =
575 IsStream.fromSerial $ Serial.map Identity $ enumerateFromTo from to
576 {-# INLINE enumerateFromThenTo #-}
577 enumerateFromThenTo (Identity from) (Identity next) (Identity to) =
578 IsStream.fromSerial
579 $ Serial.map Identity
580 $ enumerateFromThenTo from next to
582-- TODO
583{-
584instance Enumerable a => Enumerable (Last a)
585instance Enumerable a => Enumerable (First a)
586instance Enumerable a => Enumerable (Max a)
587instance Enumerable a => Enumerable (Min a)
588instance Enumerable a => Enumerable (Const a b)
589instance Enumerable (f a) => Enumerable (Alt f a)
590instance Enumerable (f a) => Enumerable (Ap f a)
591-}