2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1996
4 \section[PrelBounded]{Module @PrelBounded@}
6 Instances of Bounded for various datatypes.
9 {-# OPTIONS -fno-implicit-prelude #-}
12 Bounded(..), Enum(..),
13 enumFromBounded, enumFromThenBounded,
15 -- Instances for Bounded and Eum: (), Char, Int
19 import {-# SOURCE #-} PrelErr ( error )
21 import PrelTup () -- To make sure we look for the .hi file
25 %*********************************************************
27 \subsection{Class declarations}
29 %*********************************************************
33 minBound, maxBound :: a
39 enumFrom :: a -> [a] -- [n..]
40 enumFromThen :: a -> a -> [a] -- [n,n'..]
41 enumFromTo :: a -> a -> [a] -- [n..m]
42 enumFromThenTo :: a -> a -> a -> [a] -- [n,n'..m]
44 succ = toEnum . (`plusInt` oneInt) . fromEnum
45 pred = toEnum . (`minusInt` oneInt) . fromEnum
46 enumFromTo n m = map toEnum [fromEnum n .. fromEnum m]
47 enumFromThenTo n1 n2 m = map toEnum [fromEnum n1, fromEnum n2 .. fromEnum m]
49 -- Default methods for bounded enumerations
50 enumFromBounded :: (Enum a, Bounded a) => a -> [a]
51 enumFromBounded n = map toEnum [fromEnum n .. fromEnum (maxBound `asTypeOf` n)]
53 enumFromThenBounded :: (Enum a, Bounded a) => a -> a -> [a]
54 enumFromThenBounded n1 n2
55 | i_n2 >= i_n1 = map toEnum [i_n1, i_n2 .. fromEnum (maxBound `asTypeOf` n1)]
56 | otherwise = map toEnum [i_n1, i_n2 .. fromEnum (minBound `asTypeOf` n1)]
63 %*********************************************************
67 %*********************************************************
70 instance Bounded () where
74 instance Enum () where
75 succ x = error "Prelude.Enum.().succ: bad argment"
76 pred x = error "Prelude.Enum.().pred: bad argument"
78 toEnum x | x == zeroInt = ()
79 | otherwise = error "Prelude.Enum.().toEnum: bad argument"
83 enumFromThen () () = [()]
84 enumFromTo () () = [()]
85 enumFromThenTo () () () = [()]
89 instance (Bounded a, Bounded b) => Bounded (a,b) where
90 minBound = (minBound, minBound)
91 maxBound = (maxBound, maxBound)
93 instance (Bounded a, Bounded b, Bounded c) => Bounded (a,b,c) where
94 minBound = (minBound, minBound, minBound)
95 maxBound = (maxBound, maxBound, maxBound)
97 instance (Bounded a, Bounded b, Bounded c, Bounded d) => Bounded (a,b,c,d) where
98 minBound = (minBound, minBound, minBound, minBound)
99 maxBound = (maxBound, maxBound, maxBound, maxBound)
103 %*********************************************************
105 \subsection{Type @Bool@}
107 %*********************************************************
110 instance Bounded Bool where
114 instance Enum Bool where
116 succ True = error "Prelude.Enum.Bool.succ: bad argment"
119 pred False = error "Prelude.Enum.Bool.pred: bad argment"
121 toEnum n | n == zeroInt = False
123 | otherwise = error "Prelude.Enum.Bool.toEnum: bad argment"
125 fromEnum False = zeroInt
126 fromEnum True = oneInt
128 -- Use defaults for the rest
129 enumFrom = enumFromBounded
130 enumFromThen = enumFromThenBounded
133 %*********************************************************
135 \subsection{Type @Ordering@}
137 %*********************************************************
140 instance Bounded Ordering where
144 instance Enum Ordering where
147 succ GT = error "Prelude.Enum.Ordering.succ: bad argment"
151 pred LT = error "Prelude.Enum.Ordering.pred: bad argment"
153 toEnum n | n == zeroInt = LT
156 toEnum n = error "Prelude.Enum.Ordering.toEnum: bad argment"
158 fromEnum LT = zeroInt
162 -- Use defaults for the rest
163 enumFrom = enumFromBounded
164 enumFromThen = enumFromThenBounded
167 %*********************************************************
169 \subsection{Type @Char@}
171 %*********************************************************
174 instance Bounded Char where
178 instance Enum Char where
180 | not (ord# c# ==# 255#) = C# (chr# (ord# c# +# 1#))
181 | otherwise = error ("Prelude.Enum.Char.succ: bad argument")
183 | not (ord# c# ==# 0#) = C# (chr# (ord# c# -# 1#))
184 | otherwise = error ("Prelude.Enum.Char.pred: bad argument")
189 {-# INLINE enumFrom #-}
190 enumFrom (C# x) = build (\ c n -> eftCharFB c n (ord# x) 255#)
191 -- Blarg: technically I guess enumFrom isn't strict!
193 {-# INLINE enumFromTo #-}
194 enumFromTo (C# x) (C# y) = build (\ c n -> eftCharFB c n (ord# x) (ord# y))
196 {-# INLINE enumFromThen #-}
197 enumFromThen (C# x1) (C# x2) = build (\ c n -> efdCharFB c n (ord# x1) (ord# x2))
199 {-# INLINE enumFromThenTo #-}
200 enumFromThenTo (C# x1) (C# x2) (C# y) = build (\ c n -> efdtCharFB c n (ord# x1) (ord# x2) (ord# y))
202 -- We can do better than for Ints because we don't
203 -- have hassles about arithmetic overflow at maxBound
204 {-# INLINE eftCharFB #-}
205 eftCharFB c n x y = go x
208 | otherwise = C# (chr# x) `c` go (x +# 1#)
210 eftCharList x y | x ># y = []
211 | otherwise = C# (chr# x) : eftCharList (x +# 1#) y
214 -- For enumFromThenTo we give up on inlining
216 | delta >=# 0# = go_up_char_fb c n x1 delta 255#
217 | otherwise = go_dn_char_fb c n x1 delta 0#
222 | delta >=# 0# = go_up_char_list x1 delta 255#
223 | otherwise = go_dn_char_list x1 delta 0#
227 efdtCharFB c n x1 x2 lim
228 | delta >=# 0# = go_up_char_fb c n x1 delta lim
229 | otherwise = go_dn_char_fb c n x1 delta lim
233 efdtCharList x1 x2 lim
234 | delta >=# 0# = go_up_char_list x1 delta lim
235 | otherwise = go_dn_char_list x1 delta lim
239 go_up_char_fb c n x delta lim
242 go_up x | x ># lim = n
243 | otherwise = C# (chr# x) `c` go_up (x +# delta)
245 go_dn_char_fb c n x delta lim
248 go_dn x | x <# lim = n
249 | otherwise = C# (chr# x) `c` go_dn (x +# delta)
251 go_up_char_list x delta lim
254 go_up x | x ># lim = []
255 | otherwise = C# (chr# x) : go_up (x +# delta)
257 go_dn_char_list x delta lim
260 go_dn x | x <# lim = []
261 | otherwise = C# (chr# x) : go_dn (x +# delta)
265 "eftCharList" eftCharFB (:) [] = eftCharList
266 "efdCharList" efdCharFB (:) [] = efdCharList
267 "efdtCharList" efdtCharFB (:) [] = efdtCharList
272 %*********************************************************
274 \subsection{Type @Int@}
276 %*********************************************************
278 Be careful about these instances.
279 (a) remember that you have to count down as well as up e.g. [13,12..0]
280 (b) be careful of Int overflow
281 (c) remember that Int is bounded, so [1..] terminates at maxInt
283 Also NB that the Num class isn't available in this module.
286 instance Bounded Int where
290 instance Enum Int where
292 | x == maxBound = error "Prelude.Enum.succ{Int}: tried to take `succ' of maxBound"
293 | otherwise = x `plusInt` oneInt
295 | x == minBound = error "Prelude.Enum.pred{Int}: tried to take `pred' of minBound"
296 | otherwise = x `minusInt` oneInt
301 {-# INLINE enumFrom #-}
302 enumFrom (I# x) = build (\ c n -> eftIntFB c n x 2147483647#)
303 -- Blarg: technically I guess enumFrom isn't strict!
305 {-# INLINE enumFromTo #-}
306 enumFromTo (I# x) (I# y) = build (\ c n -> eftIntFB c n x y)
308 {-# INLINE enumFromThen #-}
309 enumFromThen (I# x1) (I# x2) = build (\ c n -> efdIntFB c n x1 x2)
311 {-# INLINE enumFromThenTo #-}
312 enumFromThenTo (I# x1) (I# x2) (I# y) = build (\ c n -> efdtIntFB c n x1 x2 y)
314 {-# INLINE eftIntFB #-}
315 eftIntFB c n x y | x ># y = n
318 go x = I# x `c` if x ==# y then n else go (x +# 1#)
319 -- Watch out for y=maxBound; hence ==, not >
320 -- Be very careful not to have more than one "c"
321 -- so that when eftInfFB is inlined we can inline
322 -- whatver is bound to "c"
324 eftIntList x y | x ># y = []
327 go x = I# x : if x ==# y then [] else go (x +# 1#)
330 -- For enumFromThenTo we give up on inlining; so we don't worry
331 -- about duplicating occurrences of "c"
332 efdtIntFB c n x1 x2 y
333 | delta >=# 0# = if x1 ># y then n else go_up_int_fb c n x1 delta lim
334 | otherwise = if x1 <# y then n else go_dn_int_fb c n x1 delta lim
340 | delta >=# 0# = if x1 ># y then [] else go_up_int_list x1 delta lim
341 | otherwise = if x1 <# y then [] else go_dn_int_list x1 delta lim
347 | delta >=# 0# = go_up_int_fb c n x1 delta ( 2147483647# -# delta)
348 | otherwise = go_dn_int_fb c n x1 delta ((-2147483648#) -# delta)
353 | delta >=# 0# = go_up_int_list x1 delta ( 2147483647# -# delta)
354 | otherwise = go_dn_int_list x1 delta ((-2147483648#) -# delta)
358 -- In all of these, the (x +# delta) is guaranteed not to overflow
360 go_up_int_fb c n x delta lim
363 go_up x | x ># lim = I# x `c` n
364 | otherwise = I# x `c` go_up (x +# delta)
366 go_dn_int_fb c n x delta lim
369 go_dn x | x <# lim = I# x `c` n
370 | otherwise = I# x `c` go_dn (x +# delta)
372 go_up_int_list x delta lim
375 go_up x | x ># lim = [I# x]
376 | otherwise = I# x : go_up (x +# delta)
378 go_dn_int_list x delta lim
381 go_dn x | x <# lim = [I# x]
382 | otherwise = I# x : go_dn (x +# delta)
386 "eftIntList" eftIntFB (:) [] = eftIntList
387 "efdIntList" efdIntFB (:) [] = efdIntList
388 "efdtIntList" efdtIntFB (:) [] = efdtIntList