Skip to content

Commit

Permalink
[project @ 1999-01-21 20:15:30 by sof]
Browse files Browse the repository at this point in the history
Enum instances updated to comply with the behaviour that
Haskell 98 specifies. Notable changes,

  * [a..b] is not the empty list when a>b any longer.
  * [x..] and [x,y..] for Enum Int are now bounded lists.

The first change is might be worth bearing in mind when converting
1.4 code to Haskell 98; functions may have made use of the
old behaviour.
  • Loading branch information
sof committed Jan 21, 1999
1 parent 718754a commit 4864e32
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 53 deletions.
95 changes: 60 additions & 35 deletions ghc/lib/std/PrelBase.lhs
Original file line number Diff line number Diff line change
Expand Up @@ -325,10 +325,10 @@ instance Ord () where
compare () () = EQ
instance Enum () where
succ x = x
pred x = x
succ x = error "Prelude.Enum.succ{()}: not possible"
pred x = error "Prelude.Enum.pred{()}: not possible"
toEnum 0 = ()
toEnum _ = error "Prelude.Enum.().toEnum: argument not 0"
toEnum _ = error "Prelude.Enum.toEnum{()}: argument not 0"
fromEnum () = 0
enumFrom () = [()]
enumFromThen () () = [()]
Expand All @@ -347,7 +347,7 @@ instance Show () where
%*********************************************************
\begin{code}
data Ordering = LT | EQ | GT deriving (Eq, Ord, Enum, Bounded, Show {- Read -})
data Ordering = LT | EQ | GT deriving (Eq, Ord, Enum, Bounded, Show {- in PrelRead: Read -})
\end{code}
Expand All @@ -365,17 +365,19 @@ data Char = C# Char# deriving (Eq, Ord)
instance Enum Char where
succ c@(C# c#)
| not (ord# c# ==# 255#) = C# (chr# (ord# c# +# 1#))
| otherwise = error ("Prelude.Enum{Char}.succ: out of range " ++ show c)
| otherwise = error ("Prelude.Enum.succ{Char}: tried to take `succ' of maxBound")
pred c@(C# c#)
| not (ord# c# ==# 0#) = C# (chr# (ord# c# -# 1#))
| otherwise = error ("Prelude.Enum{Char}.succ: out of range " ++ show c)
| otherwise = error ("Prelude.Enum.pred{Char}: tried to to take `pred' of minBound")
toEnum (I# i) | i >=# 0# && i <=# 255# = C# (chr# i)
| otherwise = error ("Prelude.Enum.Char.toEnum:out of range: " ++ show (I# i))
fromEnum (C# c) = I# (ord# c)
| otherwise = error ("Prelude.Enum.toEnum{Char}: out of range: " ++ show (I# i))
fromEnum (C# c) = I# (ord# c)
enumFrom (C# c) = efttCh (ord# c) 1# (># 255#)
enumFromTo (C# c1) (C# c2) = efttCh (ord# c1) 1# (># (ord# c2))
enumFrom (C# c) = efttCh (ord# c) 1# (># 255#)
enumFromTo (C# c1) (C# c2)
| c1 `leChar#` c2 = efttCh (ord# c1) 1# (># (ord# c2))
| otherwise = efttCh (ord# c1) (negateInt# 1#) (<# (ord# c2))
enumFromThen (C# c1) (C# c2)
| c1 `leChar#` c2 = efttCh (ord# c1) (ord# c2 -# ord# c1) (># 255#)
Expand Down Expand Up @@ -432,6 +434,9 @@ isUpper c = c >= 'A' && c <= 'Z' ||
isLower c = c >= 'a' && c <= 'z' ||
c >= '\xDF' && c <= '\xF6' ||
c >= '\xF8' && c <= '\xFF'
isAsciiLower c = c >= 'a' && c <= 'z'
isAsciiUpper c = c >= 'A' && c <= 'Z'
isAlpha c = isLower c || isUpper c
isDigit c = c >= '0' && c <= '9'
isOctDigit c = c >= '0' && c <= '7'
Expand All @@ -442,15 +447,23 @@ isAlphaNum c = isAlpha c || isDigit c
-- Case-changing operations
toUpper, toLower :: Char -> Char
toUpper c
toUpper c@(C# c#)
| isAsciiLower c = C# (chr# (ord# c# -# 32#))
| isAscii c = c
-- fall-through to the slower stuff.
| isLower c && c /= '\xDF' && c /= '\xFF'
= toEnum (fromEnum c - fromEnum 'a' + fromEnum 'A')
| otherwise
= c
= toEnum (fromEnum c - fromEnum 'a' + fromEnum 'A')
| otherwise
= c
toLower c | isUpper c = toEnum (fromEnum c - fromEnum 'A'
toLower c@(C# c#)
| isAsciiUpper c = C# (chr# (ord# c# +# 32#))
| isAscii c = c
| isUpper c = toEnum (fromEnum c - fromEnum 'A'
+ fromEnum 'a')
| otherwise = c
| otherwise = c
asciiTab :: [String]
asciiTab = -- Using an array drags in the array module. listArray ('\NUL', ' ')
Expand Down Expand Up @@ -489,20 +502,35 @@ compareInt :: Int -> Int -> Ordering
| x ==# y = EQ
| otherwise = GT
instance Bounded Int where
minBound = -2147483648 -- GHC <= 2.09 had this at -2147483647
maxBound = 2147483647
instance Enum Int where
succ x = x+1
pred x = x-1
succ x
| x == maxBound = error "Prelude.Enum.succ{Int}: tried to take `succ' of maxBound"
| otherwise = x+1
pred x
| x == minBound = error "Prelude.Enum.pred{Int}: tried to take `pred' of minBound"
| otherwise = x-1
toEnum x = x
fromEnum x = x
#ifndef USE_FOLDR_BUILD
enumFrom (I# c) = eftInt c 1#
enumFromTo (I# c1) (I# c2) = efttInt c1 1# (># c2)
enumFromThen (I# c1) (I# c2) = eftInt c1 (c2 -# c1)
enumFrom (I# c) = efttInt True c 1# (\ _ -> False)
enumFromTo (I# c1) (I# c2)
| c1 <# c2 = efttInt True c1 1# (># c2)
| otherwise = efttInt False c1 (negateInt# 1#) (<# c2)
enumFromThen (I# c1) (I# c2)
| c1 <# c2 = efttInt True c1 (c2 -# c1) (\ _ -> False)
| otherwise = efttInt False c1 (c2 -# c1) (\ _ -> False)
enumFromThenTo (I# c1) (I# c2) (I# c3)
| c1 <=# c2 = efttInt c1 (c2 -# c1) (># c3)
| otherwise = efttInt c1 (c2 -# c1) (<# c3)
| c1 <=# c2 = efttInt True c1 (c2 -# c1) (># c3)
| otherwise = efttInt False c1 (c2 -# c1) (<# c3)
#else
{-# INLINE enumFrom #-}
Expand All @@ -513,19 +541,16 @@ instance Enum Int where
let g x = if x <= y then x `c` g (x `plusInt` 1) else n in g x)
#endif
efttInt :: Int# -> Int# -> (Int# -> Bool) -> [Int]
efttInt init step done
= go init
where
go now | done now = []
| otherwise = I# now : go (now +# step)
eftInt :: Int# -> Int# -> [Int]
eftInt init step
= go init
efttInt :: Bool -> Int# -> Int# -> (Int# -> Bool) -> [Int]
efttInt increasing init step done = go init
where
go now = I# now : go (now +# step)
go now
| done now = []
| increasing && now ># nxt = [I# now] -- overflowed
| not increasing && now <# nxt = [I# now] -- underflowed
| otherwise = I# now : go nxt
where
nxt = now +# step
instance Num Int where
(+) x y = plusInt x y
Expand Down
3 changes: 0 additions & 3 deletions ghc/lib/std/PrelBounded.lhs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,4 @@ instance Bounded Char where
minBound = '\0'
maxBound = '\255'
instance Bounded Int where
minBound = -2147483648 -- GHC <= 2.09 had this at -2147483647
maxBound = 2147483647
\end{code}
2 changes: 2 additions & 0 deletions ghc/lib/std/PrelHandle.lhs
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,8 @@ openFileEx f m = do
#ifndef __CONCURRENT_HASKELL__
file_flags = file_flags'
#else
-- See comment next to 'stderr' for why we leave
-- non-blocking off for now.
file_flags = file_flags' {-+ 128 Don't block on I/O-}
#endif
Expand Down
20 changes: 12 additions & 8 deletions ghc/lib/std/PrelNum.lhs
Original file line number Diff line number Diff line change
Expand Up @@ -138,10 +138,10 @@ instance Integral Int where
-- Following chks for zero divisor are non-standard (WDP)
a `quot` b = if b /= 0
then a `quotInt` b
else error "Prelude.Integral{Int}.quot: divide by 0\n"
else error "Prelude.Integral.quot{Int}: divide by 0"
a `rem` b = if b /= 0
then a `remInt` b
else error "Prelude.Integral{Int}.rem: divide by 0\n"
else error "Prelude.Integral.rem{Int}: divide by 0"
x `div` y = if x > 0 && y < 0 then quotInt (x-y-1) y
else if x < 0 && y > 0 then quotInt (x-y+1) y
Expand Down Expand Up @@ -254,10 +254,10 @@ instance Integral Integer where
-- you get slightly better code if you let the compiler
-- see them right here:
n `quot` d = if d /= 0 then q else
error "Prelude.Integral{Integer}.quot: divide by 0\n"
error "Prelude.Integral.quot{Integer}: divide by 0"
where (q,_) = quotRem n d
n `rem` d = if d /= 0 then r else
error "Prelude.Integral{Integer}.rem: divide by 0\n"
error "Prelude.Integral.rem{Integer}: divide by 0"
where (_,r) = quotRem n d
n `div` d = q where (q,_) = divMod n d
n `mod` d = r where (_,r) = divMod n d
Expand All @@ -272,11 +272,15 @@ instance Enum Integer where
toEnum n = toInteger n
fromEnum n = toInt n
enumFrom n = n : enumFrom (n + 1)
enumFromThen m n = en' m (n - m)
enumFromThen e1 e2 = en' e1 (e2 - e1)
where en' a b = a : en' (a + b) b
enumFromTo n m = takeWhile (<= m) (enumFrom n)
enumFromThenTo n m p = takeWhile (if m >= n then (<= p) else (>= p))
(enumFromThen n m)
enumFromTo n m
| n <= m = takeWhile (<= m) (enumFrom n)
| otherwise = takeWhile (>= m) (enumFromThen n (n-1))
enumFromThenTo n m p = takeWhile pred (enumFromThen n m)
where
pred | m >= n = (<= p)
| otherwise = (>= p)
instance Show Integer where
showsPrec x = showSignedInteger x
Expand Down
36 changes: 29 additions & 7 deletions ghc/lib/std/PrelNumExtra.lhs
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,7 @@ instance Enum Float where
toEnum = fromIntegral
fromEnum = fromInteger . truncate -- may overflow
enumFrom = numericEnumFrom
enumFromTo = numericEnumFromTo
enumFromThen = numericEnumFromThen
enumFromThenTo = numericEnumFromThenTo
Expand All @@ -396,13 +397,22 @@ instance Enum Double where
enumFromThen = numericEnumFromThen
enumFromThenTo = numericEnumFromThenTo
numericEnumFrom :: (Real a) => a -> [a]
numericEnumFromThen :: (Real a) => a -> a -> [a]
numericEnumFromThenTo :: (Real a) => a -> a -> a -> [a]
numericEnumFrom :: (Fractional a) => a -> [a]
numericEnumFrom = iterate (+1)
numericEnumFromThen :: (Fractional a) => a -> a -> [a]
numericEnumFromThen n m = iterate (+(m-n)) n
numericEnumFromThenTo n m p = takeWhile (if m >= n then (<= p) else (>= p))
(numericEnumFromThen n m)
numericEnumFromTo :: (Ord a, Fractional a) => a -> a -> [a]
numericEnumFromTo n m = takeWhile (<= m + 1/2) (numericEnumFrom n)
numericEnumFromThenTo :: (Ord a, Fractional a) => a -> a -> a -> [a]
numericEnumFromThenTo e1 e2 e3 = takeWhile pred (numericEnumFromThen e1 e2)
where
mid = (e2 - e1) / 2
pred | e2 > e1 = (<= e3 + mid)
| otherwise = (>= e3 + mid)
\end{code}

@approxRational@, applied to two real fractional numbers x and epsilon,
Expand Down Expand Up @@ -472,11 +482,23 @@ instance (Integral a) => RealFrac (Ratio a) where
instance (Integral a) => Enum (Ratio a) where
succ x = x + 1
pred x = x - 1
enumFrom = iterate ((+)1)
enumFromThen n m = iterate ((+)(m-n)) n
toEnum n = fromIntegral n :% 1
fromEnum = fromInteger . truncate
enumFrom = bounded_iterator True (1)
enumFromThen n m = bounded_iterator (diff >= 0) diff n
where diff = m - n
bounded_iterator :: (Ord a, Num a) => Bool -> a -> a -> [a]
bounded_iterator inc step v
| inc && v > new_v = [v] -- oflow
| not inc && v < new_v = [v] -- uflow
| otherwise = v : bounded_iterator inc step new_v
where
new_v = v + step
ratio_prec :: Int
ratio_prec = 7
Expand Down

0 comments on commit 4864e32

Please sign in to comment.