2 {-# OPTIONS -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 -----------------------------------------------------------------------------
18 Bounded(..), Enum(..),
19 boundedEnumFrom, boundedEnumFromThen,
21 -- Instances for Bounded and Enum: (), Char, Int
25 import {-# SOURCE #-} GHC.Err ( error )
27 import Data.Tuple () -- for dependencies
28 default () -- Double isn't available yet
32 %*********************************************************
34 \subsection{Class declarations}
36 %*********************************************************
40 minBound, maxBound :: a
46 enumFrom :: a -> [a] -- [n..]
47 enumFromThen :: a -> a -> [a] -- [n,n'..]
48 enumFromTo :: a -> a -> [a] -- [n..m]
49 enumFromThenTo :: a -> a -> a -> [a] -- [n,n'..m]
51 succ = toEnum . (`plusInt` oneInt) . fromEnum
52 pred = toEnum . (`minusInt` oneInt) . fromEnum
53 enumFrom x = map toEnum [fromEnum x ..]
54 enumFromThen x y = map toEnum [fromEnum x, fromEnum y ..]
55 enumFromTo x y = map toEnum [fromEnum x .. fromEnum y]
56 enumFromThenTo x1 x2 y = map toEnum [fromEnum x1, fromEnum x2 .. fromEnum y]
58 -- Default methods for bounded enumerations
59 boundedEnumFrom :: (Enum a, Bounded a) => a -> [a]
60 boundedEnumFrom n = map toEnum [fromEnum n .. fromEnum (maxBound `asTypeOf` n)]
62 boundedEnumFromThen :: (Enum a, Bounded a) => a -> a -> [a]
63 boundedEnumFromThen n1 n2
64 | i_n2 >= i_n1 = map toEnum [i_n1, i_n2 .. fromEnum (maxBound `asTypeOf` n1)]
65 | otherwise = map toEnum [i_n1, i_n2 .. fromEnum (minBound `asTypeOf` n1)]
72 %*********************************************************
76 %*********************************************************
79 instance Bounded () where
83 instance Enum () where
84 succ _ = error "Prelude.Enum.().succ: bad argment"
85 pred _ = error "Prelude.Enum.().pred: bad argument"
87 toEnum x | x == zeroInt = ()
88 | otherwise = error "Prelude.Enum.().toEnum: bad argument"
92 enumFromThen () () = [()]
93 enumFromTo () () = [()]
94 enumFromThenTo () () () = [()]
98 instance (Bounded a, Bounded b) => Bounded (a,b) where
99 minBound = (minBound, minBound)
100 maxBound = (maxBound, maxBound)
102 instance (Bounded a, Bounded b, Bounded c) => Bounded (a,b,c) where
103 minBound = (minBound, minBound, minBound)
104 maxBound = (maxBound, maxBound, maxBound)
106 instance (Bounded a, Bounded b, Bounded c, Bounded d) => Bounded (a,b,c,d) where
107 minBound = (minBound, minBound, minBound, minBound)
108 maxBound = (maxBound, maxBound, maxBound, maxBound)
112 %*********************************************************
114 \subsection{Type @Bool@}
116 %*********************************************************
119 instance Bounded Bool where
123 instance Enum Bool where
125 succ True = error "Prelude.Enum.Bool.succ: bad argment"
128 pred False = error "Prelude.Enum.Bool.pred: bad argment"
130 toEnum n | n == zeroInt = False
132 | otherwise = error "Prelude.Enum.Bool.toEnum: bad argment"
134 fromEnum False = zeroInt
135 fromEnum True = oneInt
137 -- Use defaults for the rest
138 enumFrom = boundedEnumFrom
139 enumFromThen = boundedEnumFromThen
142 %*********************************************************
144 \subsection{Type @Ordering@}
146 %*********************************************************
149 instance Bounded Ordering where
153 instance Enum Ordering where
156 succ GT = error "Prelude.Enum.Ordering.succ: bad argment"
160 pred LT = error "Prelude.Enum.Ordering.pred: bad argment"
162 toEnum n | n == zeroInt = LT
165 toEnum _ = error "Prelude.Enum.Ordering.toEnum: bad argment"
167 fromEnum LT = zeroInt
171 -- Use defaults for the rest
172 enumFrom = boundedEnumFrom
173 enumFromThen = boundedEnumFromThen
176 %*********************************************************
178 \subsection{Type @Char@}
180 %*********************************************************
183 instance Bounded Char where
185 maxBound = '\x10FFFF'
187 instance Enum Char where
189 | not (ord# c# ==# 0x10FFFF#) = C# (chr# (ord# c# +# 1#))
190 | otherwise = error ("Prelude.Enum.Char.succ: bad argument")
192 | not (ord# c# ==# 0#) = C# (chr# (ord# c# -# 1#))
193 | otherwise = error ("Prelude.Enum.Char.pred: bad argument")
198 {-# INLINE enumFrom #-}
199 enumFrom (C# x) = eftChar (ord# x) 0x10FFFF#
200 -- Blarg: technically I guess enumFrom isn't strict!
202 {-# INLINE enumFromTo #-}
203 enumFromTo (C# x) (C# y) = eftChar (ord# x) (ord# y)
205 {-# INLINE enumFromThen #-}
206 enumFromThen (C# x1) (C# x2) = efdChar (ord# x1) (ord# x2)
208 {-# INLINE enumFromThenTo #-}
209 enumFromThenTo (C# x1) (C# x2) (C# y) = efdtChar (ord# x1) (ord# x2) (ord# y)
212 "eftChar" [~1] forall x y. eftChar x y = build (\c n -> eftCharFB c n x y)
213 "efdChar" [~1] forall x1 x2. efdChar x1 x2 = build (\ c n -> efdCharFB c n x1 x2)
214 "efdtChar" [~1] forall x1 x2 l. efdtChar x1 x2 l = build (\ c n -> efdtCharFB c n x1 x2 l)
215 "eftCharList" [1] eftCharFB (:) [] = eftChar
216 "efdCharList" [1] efdCharFB (:) [] = efdChar
217 "efdtCharList" [1] efdtCharFB (:) [] = efdtChar
221 -- We can do better than for Ints because we don't
222 -- have hassles about arithmetic overflow at maxBound
223 {-# INLINE [0] eftCharFB #-}
224 eftCharFB c n x y = go x
227 | otherwise = C# (chr# x) `c` go (x +# 1#)
229 eftChar x y | x ># y = []
230 | otherwise = C# (chr# x) : eftChar (x +# 1#) y
233 -- For enumFromThenTo we give up on inlining
234 {-# NOINLINE [0] efdCharFB #-}
236 | delta >=# 0# = go_up_char_fb c n x1 delta 0x10FFFF#
237 | otherwise = go_dn_char_fb c n x1 delta 0#
242 | delta >=# 0# = go_up_char_list x1 delta 0x10FFFF#
243 | otherwise = go_dn_char_list x1 delta 0#
247 {-# NOINLINE [0] efdtCharFB #-}
248 efdtCharFB c n x1 x2 lim
249 | delta >=# 0# = go_up_char_fb c n x1 delta lim
250 | otherwise = go_dn_char_fb c n x1 delta lim
255 | delta >=# 0# = go_up_char_list x1 delta lim
256 | otherwise = go_dn_char_list x1 delta lim
260 go_up_char_fb c n x delta lim
263 go_up x | x ># lim = n
264 | otherwise = C# (chr# x) `c` go_up (x +# delta)
266 go_dn_char_fb c n x delta lim
269 go_dn x | x <# lim = n
270 | otherwise = C# (chr# x) `c` go_dn (x +# delta)
272 go_up_char_list x delta lim
275 go_up x | x ># lim = []
276 | otherwise = C# (chr# x) : go_up (x +# delta)
278 go_dn_char_list x delta lim
281 go_dn x | x <# lim = []
282 | otherwise = C# (chr# x) : go_dn (x +# delta)
286 %*********************************************************
288 \subsection{Type @Int@}
290 %*********************************************************
292 Be careful about these instances.
293 (a) remember that you have to count down as well as up e.g. [13,12..0]
294 (b) be careful of Int overflow
295 (c) remember that Int is bounded, so [1..] terminates at maxInt
297 Also NB that the Num class isn't available in this module.
300 instance Bounded Int where
304 instance Enum Int where
306 | x == maxBound = error "Prelude.Enum.succ{Int}: tried to take `succ' of maxBound"
307 | otherwise = x `plusInt` oneInt
309 | x == minBound = error "Prelude.Enum.pred{Int}: tried to take `pred' of minBound"
310 | otherwise = x `minusInt` oneInt
315 {-# INLINE enumFrom #-}
316 enumFrom (I# x) = eftInt x maxInt#
317 where I# maxInt# = maxInt
318 -- Blarg: technically I guess enumFrom isn't strict!
320 {-# INLINE enumFromTo #-}
321 enumFromTo (I# x) (I# y) = eftInt x y
323 {-# INLINE enumFromThen #-}
324 enumFromThen (I# x1) (I# x2) = efdInt x1 x2
326 {-# INLINE enumFromThenTo #-}
327 enumFromThenTo (I# x1) (I# x2) (I# y) = efdtInt x1 x2 y
330 "eftInt" [~1] forall x y. eftInt x y = build (\ c n -> eftIntFB c n x y)
331 "efdInt" [~1] forall x1 x2. efdInt x1 x2 = build (\ c n -> efdIntFB c n x1 x2)
332 "efdtInt" [~1] forall x1 x2 l. efdtInt x1 x2 l = build (\ c n -> efdtIntFB c n x1 x2 l)
334 "eftIntList" [1] eftIntFB (:) [] = eftInt
335 "efdIntList" [1] efdIntFB (:) [] = efdInt
336 "efdtIntList" [1] efdtIntFB (:) [] = efdtInt
340 {-# INLINE [0] eftIntFB #-}
341 eftIntFB c n x y | x ># y = n
344 go x = I# x `c` if x ==# y then n else go (x +# 1#)
345 -- Watch out for y=maxBound; hence ==, not >
346 -- Be very careful not to have more than one "c"
347 -- so that when eftInfFB is inlined we can inline
348 -- whatver is bound to "c"
350 eftInt x y | x ># y = []
353 go x = I# x : if x ==# y then [] else go (x +# 1#)
356 -- For enumFromThenTo we give up on inlining; so we don't worry
357 -- about duplicating occurrences of "c"
358 {-# NOINLINE [0] efdtIntFB #-}
359 efdtIntFB c n x1 x2 y
360 | delta >=# 0# = if x1 ># y then n else go_up_int_fb c n x1 delta lim
361 | otherwise = if x1 <# y then n else go_dn_int_fb c n x1 delta lim
367 | delta >=# 0# = if x1 ># y then [] else go_up_int_list x1 delta lim
368 | otherwise = if x1 <# y then [] else go_dn_int_list x1 delta lim
373 {-# NOINLINE [0] efdIntFB #-}
375 | delta >=# 0# = case maxInt of I# y -> go_up_int_fb c n x1 delta (y -# delta)
376 | otherwise = case minInt of I# y -> go_dn_int_fb c n x1 delta (y -# delta)
381 | delta >=# 0# = case maxInt of I# y -> go_up_int_list x1 delta (y -# delta)
382 | otherwise = case minInt of I# y -> go_dn_int_list x1 delta (y -# delta)
386 -- In all of these, the (x +# delta) is guaranteed not to overflow
388 go_up_int_fb c n x delta lim
391 go_up x | x ># lim = I# x `c` n
392 | otherwise = I# x `c` go_up (x +# delta)
394 go_dn_int_fb c n x delta lim
397 go_dn x | x <# lim = I# x `c` n
398 | otherwise = I# x `c` go_dn (x +# delta)
400 go_up_int_list x delta lim
403 go_up x | x ># lim = [I# x]
404 | otherwise = I# x : go_up (x +# delta)
406 go_dn_int_list x delta lim
409 go_dn x | x <# lim = [I# x]
410 | otherwise = I# x : go_dn (x +# delta)