2 {-# OPTIONS_GHC -fno-implicit-prelude #-}
3 -----------------------------------------------------------------------------
6 -- Copyright : (c) The University of Glasgow, 1992-2002
7 -- License : see libraries/base/LICENSE
9 -- Maintainer : cvs-ghc@haskell.org
10 -- Stability : internal
11 -- Portability : non-portable (GHC extensions)
13 -- The 'Enum' and 'Bounded' classes.
15 -----------------------------------------------------------------------------
19 Bounded(..), Enum(..),
20 boundedEnumFrom, boundedEnumFromThen,
22 -- Instances for Bounded and Enum: (), Char, Int
27 import Data.Tuple () -- for dependencies
28 default () -- Double isn't available yet
32 %*********************************************************
34 \subsection{Class declarations}
36 %*********************************************************
39 -- | The 'Bounded' class is used to name the upper and lower limits of a
40 -- type. 'Ord' is not a superclass of 'Bounded' since types that are not
41 -- totally ordered may also have upper and lower bounds.
43 -- The 'Bounded' class may be derived for any enumeration type;
44 -- 'minBound' is the first constructor listed in the @data@ declaration
45 -- and 'maxBound' is the last.
46 -- 'Bounded' may also be derived for single-constructor datatypes whose
47 -- constituent types are in 'Bounded'.
50 minBound, maxBound :: a
52 -- | Class 'Enum' defines operations on sequentially ordered types.
54 -- The @enumFrom@... methods are used in Haskell's translation of
55 -- arithmetic sequences.
57 -- Instances of 'Enum' may be derived for any enumeration type (types
58 -- whose constructors have no fields). The nullary constructors are
59 -- assumed to be numbered left-to-right by 'fromEnum' from @0@ through @n-1@.
60 -- See Chapter 10 of the /Haskell Report/ for more details.
62 -- For any type that is an instance of class 'Bounded' as well as 'Enum',
63 -- the following should hold:
65 -- * The calls @'succ' 'maxBound'@ and @'pred' 'minBound'@ should result in
68 -- * 'fromEnum' and 'toEnum' should give a runtime error if the
69 -- result value is not representable in the result type.
70 -- For example, @'toEnum' 7 :: 'Bool'@ is an error.
72 -- * 'enumFrom' and 'enumFromThen' should be defined with an implicit bound,
75 -- > enumFrom x = enumFromTo x maxBound
76 -- > enumFromThen x y = enumFromThenTo x y bound
78 -- > bound | fromEnum y >= fromEnum x = maxBound
79 -- > | otherwise = minBound
82 -- | the successor of a value. For numeric types, 'succ' adds 1.
84 -- | the predecessor of a value. For numeric types, 'pred' subtracts 1.
86 -- | Convert from an 'Int'.
88 -- | Convert to an 'Int'.
89 -- It is implementation-dependent what 'fromEnum' returns when
90 -- applied to a value that is too large to fit in an 'Int'.
93 -- | Used in Haskell's translation of @[n..]@.
95 -- | Used in Haskell's translation of @[n,n'..]@.
96 enumFromThen :: a -> a -> [a]
97 -- | Used in Haskell's translation of @[n..m]@.
98 enumFromTo :: a -> a -> [a]
99 -- | Used in Haskell's translation of @[n,n'..m]@.
100 enumFromThenTo :: a -> a -> a -> [a]
102 succ = toEnum . (`plusInt` oneInt) . fromEnum
103 pred = toEnum . (`minusInt` oneInt) . fromEnum
104 enumFrom x = map toEnum [fromEnum x ..]
105 enumFromThen x y = map toEnum [fromEnum x, fromEnum y ..]
106 enumFromTo x y = map toEnum [fromEnum x .. fromEnum y]
107 enumFromThenTo x1 x2 y = map toEnum [fromEnum x1, fromEnum x2 .. fromEnum y]
109 -- Default methods for bounded enumerations
110 boundedEnumFrom :: (Enum a, Bounded a) => a -> [a]
111 boundedEnumFrom n = map toEnum [fromEnum n .. fromEnum (maxBound `asTypeOf` n)]
113 boundedEnumFromThen :: (Enum a, Bounded a) => a -> a -> [a]
114 boundedEnumFromThen n1 n2
115 | i_n2 >= i_n1 = map toEnum [i_n1, i_n2 .. fromEnum (maxBound `asTypeOf` n1)]
116 | otherwise = map toEnum [i_n1, i_n2 .. fromEnum (minBound `asTypeOf` n1)]
123 %*********************************************************
127 %*********************************************************
130 instance Bounded () where
134 instance Enum () where
135 succ _ = error "Prelude.Enum.().succ: bad argument"
136 pred _ = error "Prelude.Enum.().pred: bad argument"
138 toEnum x | x == zeroInt = ()
139 | otherwise = error "Prelude.Enum.().toEnum: bad argument"
141 fromEnum () = zeroInt
143 enumFromThen () () = let many = ():many in many
144 enumFromTo () () = [()]
145 enumFromThenTo () () () = let many = ():many in many
149 -- Report requires instances up to 15
150 instance (Bounded a, Bounded b) => Bounded (a,b) where
151 minBound = (minBound, minBound)
152 maxBound = (maxBound, maxBound)
154 instance (Bounded a, Bounded b, Bounded c) => Bounded (a,b,c) where
155 minBound = (minBound, minBound, minBound)
156 maxBound = (maxBound, maxBound, maxBound)
158 instance (Bounded a, Bounded b, Bounded c, Bounded d) => Bounded (a,b,c,d) where
159 minBound = (minBound, minBound, minBound, minBound)
160 maxBound = (maxBound, maxBound, maxBound, maxBound)
162 instance (Bounded a, Bounded b, Bounded c, Bounded d, Bounded e) => Bounded (a,b,c,d,e) where
163 minBound = (minBound, minBound, minBound, minBound, minBound)
164 maxBound = (maxBound, maxBound, maxBound, maxBound, maxBound)
166 instance (Bounded a, Bounded b, Bounded c, Bounded d, Bounded e, Bounded f)
167 => Bounded (a,b,c,d,e,f) where
168 minBound = (minBound, minBound, minBound, minBound, minBound, minBound)
169 maxBound = (maxBound, maxBound, maxBound, maxBound, maxBound, maxBound)
171 instance (Bounded a, Bounded b, Bounded c, Bounded d, Bounded e, Bounded f, Bounded g)
172 => Bounded (a,b,c,d,e,f,g) where
173 minBound = (minBound, minBound, minBound, minBound, minBound, minBound, minBound)
174 maxBound = (maxBound, maxBound, maxBound, maxBound, maxBound, maxBound, maxBound)
176 instance (Bounded a, Bounded b, Bounded c, Bounded d, Bounded e, Bounded f, Bounded g,
178 => Bounded (a,b,c,d,e,f,g,h) where
179 minBound = (minBound, minBound, minBound, minBound, minBound, minBound, minBound, minBound)
180 maxBound = (maxBound, maxBound, maxBound, maxBound, maxBound, maxBound, maxBound, maxBound)
182 instance (Bounded a, Bounded b, Bounded c, Bounded d, Bounded e, Bounded f, Bounded g,
183 Bounded h, Bounded i)
184 => Bounded (a,b,c,d,e,f,g,h,i) where
185 minBound = (minBound, minBound, minBound, minBound, minBound, minBound, minBound, minBound,
187 maxBound = (maxBound, maxBound, maxBound, maxBound, maxBound, maxBound, maxBound, maxBound,
190 instance (Bounded a, Bounded b, Bounded c, Bounded d, Bounded e, Bounded f, Bounded g,
191 Bounded h, Bounded i, Bounded j)
192 => Bounded (a,b,c,d,e,f,g,h,i,j) where
193 minBound = (minBound, minBound, minBound, minBound, minBound, minBound, minBound, minBound,
195 maxBound = (maxBound, maxBound, maxBound, maxBound, maxBound, maxBound, maxBound, maxBound,
198 instance (Bounded a, Bounded b, Bounded c, Bounded d, Bounded e, Bounded f, Bounded g,
199 Bounded h, Bounded i, Bounded j, Bounded k)
200 => Bounded (a,b,c,d,e,f,g,h,i,j,k) where
201 minBound = (minBound, minBound, minBound, minBound, minBound, minBound, minBound, minBound,
202 minBound, minBound, minBound)
203 maxBound = (maxBound, maxBound, maxBound, maxBound, maxBound, maxBound, maxBound, maxBound,
204 maxBound, maxBound, maxBound)
206 instance (Bounded a, Bounded b, Bounded c, Bounded d, Bounded e, Bounded f, Bounded g,
207 Bounded h, Bounded i, Bounded j, Bounded k, Bounded l)
208 => Bounded (a,b,c,d,e,f,g,h,i,j,k,l) where
209 minBound = (minBound, minBound, minBound, minBound, minBound, minBound, minBound, minBound,
210 minBound, minBound, minBound, minBound)
211 maxBound = (maxBound, maxBound, maxBound, maxBound, maxBound, maxBound, maxBound, maxBound,
212 maxBound, maxBound, maxBound, maxBound)
214 instance (Bounded a, Bounded b, Bounded c, Bounded d, Bounded e, Bounded f, Bounded g,
215 Bounded h, Bounded i, Bounded j, Bounded k, Bounded l, Bounded m)
216 => Bounded (a,b,c,d,e,f,g,h,i,j,k,l,m) where
217 minBound = (minBound, minBound, minBound, minBound, minBound, minBound, minBound, minBound,
218 minBound, minBound, minBound, minBound, minBound)
219 maxBound = (maxBound, maxBound, maxBound, maxBound, maxBound, maxBound, maxBound, maxBound,
220 maxBound, maxBound, maxBound, maxBound, maxBound)
222 instance (Bounded a, Bounded b, Bounded c, Bounded d, Bounded e, Bounded f, Bounded g,
223 Bounded h, Bounded i, Bounded j, Bounded k, Bounded l, Bounded m, Bounded n)
224 => Bounded (a,b,c,d,e,f,g,h,i,j,k,l,m,n) where
225 minBound = (minBound, minBound, minBound, minBound, minBound, minBound, minBound, minBound,
226 minBound, minBound, minBound, minBound, minBound, minBound)
227 maxBound = (maxBound, maxBound, maxBound, maxBound, maxBound, maxBound, maxBound, maxBound,
228 maxBound, maxBound, maxBound, maxBound, maxBound, maxBound)
230 instance (Bounded a, Bounded b, Bounded c, Bounded d, Bounded e, Bounded f, Bounded g,
231 Bounded h, Bounded i, Bounded j, Bounded k, Bounded l, Bounded m, Bounded n, Bounded o)
232 => Bounded (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o) where
233 minBound = (minBound, minBound, minBound, minBound, minBound, minBound, minBound, minBound,
234 minBound, minBound, minBound, minBound, minBound, minBound, minBound)
235 maxBound = (maxBound, maxBound, maxBound, maxBound, maxBound, maxBound, maxBound, maxBound,
236 maxBound, maxBound, maxBound, maxBound, maxBound, maxBound, maxBound)
240 %*********************************************************
242 \subsection{Type @Bool@}
244 %*********************************************************
247 instance Bounded Bool where
251 instance Enum Bool where
253 succ True = error "Prelude.Enum.Bool.succ: bad argument"
256 pred False = error "Prelude.Enum.Bool.pred: bad argument"
258 toEnum n | n == zeroInt = False
260 | otherwise = error "Prelude.Enum.Bool.toEnum: bad argument"
262 fromEnum False = zeroInt
263 fromEnum True = oneInt
265 -- Use defaults for the rest
266 enumFrom = boundedEnumFrom
267 enumFromThen = boundedEnumFromThen
270 %*********************************************************
272 \subsection{Type @Ordering@}
274 %*********************************************************
277 instance Bounded Ordering where
281 instance Enum Ordering where
284 succ GT = error "Prelude.Enum.Ordering.succ: bad argument"
288 pred LT = error "Prelude.Enum.Ordering.pred: bad argument"
290 toEnum n | n == zeroInt = LT
293 toEnum _ = error "Prelude.Enum.Ordering.toEnum: bad argument"
295 fromEnum LT = zeroInt
299 -- Use defaults for the rest
300 enumFrom = boundedEnumFrom
301 enumFromThen = boundedEnumFromThen
304 %*********************************************************
306 \subsection{Type @Char@}
308 %*********************************************************
311 instance Bounded Char where
313 maxBound = '\x10FFFF'
315 instance Enum Char where
317 | not (ord# c# ==# 0x10FFFF#) = C# (chr# (ord# c# +# 1#))
318 | otherwise = error ("Prelude.Enum.Char.succ: bad argument")
320 | not (ord# c# ==# 0#) = C# (chr# (ord# c# -# 1#))
321 | otherwise = error ("Prelude.Enum.Char.pred: bad argument")
326 {-# INLINE enumFrom #-}
327 enumFrom (C# x) = eftChar (ord# x) 0x10FFFF#
328 -- Blarg: technically I guess enumFrom isn't strict!
330 {-# INLINE enumFromTo #-}
331 enumFromTo (C# x) (C# y) = eftChar (ord# x) (ord# y)
333 {-# INLINE enumFromThen #-}
334 enumFromThen (C# x1) (C# x2) = efdChar (ord# x1) (ord# x2)
336 {-# INLINE enumFromThenTo #-}
337 enumFromThenTo (C# x1) (C# x2) (C# y) = efdtChar (ord# x1) (ord# x2) (ord# y)
340 "eftChar" [~1] forall x y. eftChar x y = build (\c n -> eftCharFB c n x y)
341 "efdChar" [~1] forall x1 x2. efdChar x1 x2 = build (\ c n -> efdCharFB c n x1 x2)
342 "efdtChar" [~1] forall x1 x2 l. efdtChar x1 x2 l = build (\ c n -> efdtCharFB c n x1 x2 l)
343 "eftCharList" [1] eftCharFB (:) [] = eftChar
344 "efdCharList" [1] efdCharFB (:) [] = efdChar
345 "efdtCharList" [1] efdtCharFB (:) [] = efdtChar
349 -- We can do better than for Ints because we don't
350 -- have hassles about arithmetic overflow at maxBound
351 {-# INLINE [0] eftCharFB #-}
352 eftCharFB c n x y = go x
355 | otherwise = C# (chr# x) `c` go (x +# 1#)
357 eftChar x y | x ># y = []
358 | otherwise = C# (chr# x) : eftChar (x +# 1#) y
361 -- For enumFromThenTo we give up on inlining
362 {-# NOINLINE [0] efdCharFB #-}
364 | delta >=# 0# = go_up_char_fb c n x1 delta 0x10FFFF#
365 | otherwise = go_dn_char_fb c n x1 delta 0#
370 | delta >=# 0# = go_up_char_list x1 delta 0x10FFFF#
371 | otherwise = go_dn_char_list x1 delta 0#
375 {-# NOINLINE [0] efdtCharFB #-}
376 efdtCharFB c n x1 x2 lim
377 | delta >=# 0# = go_up_char_fb c n x1 delta lim
378 | otherwise = go_dn_char_fb c n x1 delta lim
383 | delta >=# 0# = go_up_char_list x1 delta lim
384 | otherwise = go_dn_char_list x1 delta lim
388 go_up_char_fb c n x delta lim
391 go_up x | x ># lim = n
392 | otherwise = C# (chr# x) `c` go_up (x +# delta)
394 go_dn_char_fb c n x delta lim
397 go_dn x | x <# lim = n
398 | otherwise = C# (chr# x) `c` go_dn (x +# delta)
400 go_up_char_list x delta lim
403 go_up x | x ># lim = []
404 | otherwise = C# (chr# x) : go_up (x +# delta)
406 go_dn_char_list x delta lim
409 go_dn x | x <# lim = []
410 | otherwise = C# (chr# x) : go_dn (x +# delta)
414 %*********************************************************
416 \subsection{Type @Int@}
418 %*********************************************************
420 Be careful about these instances.
421 (a) remember that you have to count down as well as up e.g. [13,12..0]
422 (b) be careful of Int overflow
423 (c) remember that Int is bounded, so [1..] terminates at maxInt
425 Also NB that the Num class isn't available in this module.
428 instance Bounded Int where
432 instance Enum Int where
434 | x == maxBound = error "Prelude.Enum.succ{Int}: tried to take `succ' of maxBound"
435 | otherwise = x `plusInt` oneInt
437 | x == minBound = error "Prelude.Enum.pred{Int}: tried to take `pred' of minBound"
438 | otherwise = x `minusInt` oneInt
443 {-# INLINE enumFrom #-}
444 enumFrom (I# x) = eftInt x maxInt#
445 where I# maxInt# = maxInt
446 -- Blarg: technically I guess enumFrom isn't strict!
448 {-# INLINE enumFromTo #-}
449 enumFromTo (I# x) (I# y) = eftInt x y
451 {-# INLINE enumFromThen #-}
452 enumFromThen (I# x1) (I# x2) = efdInt x1 x2
454 {-# INLINE enumFromThenTo #-}
455 enumFromThenTo (I# x1) (I# x2) (I# y) = efdtInt x1 x2 y
458 -----------------------------------------------------
459 -- eftInt and eftIntFB deal with [a..b], which is the
460 -- most common form, so we take a lot of care
461 -- In particular, we have rules for deforestation
464 "eftInt" [~1] forall x y. eftInt x y = build (\ c n -> eftIntFB c n x y)
465 "eftIntList" [1] eftIntFB (:) [] = eftInt
468 eftInt :: Int# -> Int# -> [Int]
470 eftInt x y | x ># y = []
473 go x = I# x : if x ==# y then [] else go (x +# 1#)
475 {-# INLINE [0] eftIntFB #-}
476 eftIntFB :: (Int -> r -> r) -> r -> Int# -> Int# -> r
477 eftIntFB c n x y | x ># y = n
480 go x = I# x `c` if x ==# y then n else go (x +# 1#)
481 -- Watch out for y=maxBound; hence ==, not >
482 -- Be very careful not to have more than one "c"
483 -- so that when eftInfFB is inlined we can inline
484 -- whatver is bound to "c"
487 -----------------------------------------------------
488 -- efdInt and efdtInt deal with [a,b..] and [a,b..c], which are much less common
489 -- so we are less elaborate. The code is more complicated anyway, because
490 -- of worries about Int overflow, so we don't both with rules and deforestation
492 efdInt :: Int# -> Int# -> [Int]
495 | x2 >=# x1 = case maxInt of I# y -> efdtIntUp x1 x2 y
496 | otherwise = case minInt of I# y -> efdtIntDn x1 x2 y
498 efdtInt :: Int# -> Int# -> Int# -> [Int]
501 | x2 >=# x1 = efdtIntUp x1 x2 y
502 | otherwise = efdtIntDn x1 x2 y
504 efdtIntUp :: Int# -> Int# -> Int# -> [Int]
505 efdtIntUp x1 x2 y -- Be careful about overflow!
506 | y <# x2 = if y <# x1 then [] else [I# x1]
508 = -- Common case: x1 < x2 <= y
512 -- NB: x1 <= y'; hence y' is representable
514 -- Invariant: x <= y; and x+delta won't overflow
515 go_up x | x ># y' = [I# x]
516 | otherwise = I# x : go_up (x +# delta)
520 efdtIntDn :: Int# -> Int# -> Int# -> [Int]
521 efdtIntDn x1 x2 y -- x2 < x1
522 | y ># x2 = if y ># x1 then [] else [I# x1]
524 = -- Common case: x1 > x2 >= y
528 -- NB: x1 <= y'; hence y' is representable
530 -- Invariant: x >= y; and x+delta won't overflow
531 go_dn x | x <# y' = [I# x]
532 | otherwise = I# x : go_dn (x +# delta)