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