From 4864e32ad1c683c7fc569d6aa5f2c605076abdbe Mon Sep 17 00:00:00 2001 From: sof Date: Thu, 21 Jan 1999 20:15:32 +0000 Subject: [PATCH] [project @ 1999-01-21 20:15:30 by sof] 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. --- ghc/lib/std/PrelBase.lhs | 95 ++++++++++++++++++++++++++---------------- ghc/lib/std/PrelBounded.lhs | 3 -- ghc/lib/std/PrelHandle.lhs | 2 + ghc/lib/std/PrelNum.lhs | 20 +++++---- ghc/lib/std/PrelNumExtra.lhs | 36 ++++++++++++---- 5 files changed, 103 insertions(+), 53 deletions(-) diff --git a/ghc/lib/std/PrelBase.lhs b/ghc/lib/std/PrelBase.lhs index 48dc8cf..1d6d69d 100644 --- a/ghc/lib/std/PrelBase.lhs +++ b/ghc/lib/std/PrelBase.lhs @@ -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 () () = [()] @@ -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} @@ -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#) @@ -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' @@ -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', ' ') @@ -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 #-} @@ -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 diff --git a/ghc/lib/std/PrelBounded.lhs b/ghc/lib/std/PrelBounded.lhs index 3d1d0fd..de8699e 100644 --- a/ghc/lib/std/PrelBounded.lhs +++ b/ghc/lib/std/PrelBounded.lhs @@ -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} diff --git a/ghc/lib/std/PrelHandle.lhs b/ghc/lib/std/PrelHandle.lhs index 139594d..caa8c50 100644 --- a/ghc/lib/std/PrelHandle.lhs +++ b/ghc/lib/std/PrelHandle.lhs @@ -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 diff --git a/ghc/lib/std/PrelNum.lhs b/ghc/lib/std/PrelNum.lhs index 4f09ebd..5a835ad 100644 --- a/ghc/lib/std/PrelNum.lhs +++ b/ghc/lib/std/PrelNum.lhs @@ -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 @@ -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 @@ -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 diff --git a/ghc/lib/std/PrelNumExtra.lhs b/ghc/lib/std/PrelNumExtra.lhs index 5ba5ebd..8322e26 100644 --- a/ghc/lib/std/PrelNumExtra.lhs +++ b/ghc/lib/std/PrelNumExtra.lhs @@ -384,6 +384,7 @@ instance Enum Float where toEnum = fromIntegral fromEnum = fromInteger . truncate -- may overflow enumFrom = numericEnumFrom + enumFromTo = numericEnumFromTo enumFromThen = numericEnumFromThen enumFromThenTo = numericEnumFromThenTo @@ -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, @@ -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 -- 1.7.10.4