```{-# LANGUAGE DeriveDataTypeable, CPP #-}
import Prelude hiding(Ratio, Rational, (%))
#else
import Prelude hiding(Rational)
#endif
import qualified Data.Ratio
import Data.Typeable
import Data.Bits
-- import Test.QuickCheck hiding (choose)
-- import GHC.Integer.GMP.Internals

-- So, the integral type is totally ignored!
data Ratio a = !Integer :% !Integer deriving Typeable

type Rational = Ratio Integer

(%) :: Integral a => a -> a -> Ratio a
x % y = toInteger x :% toInteger y
numerator, denominator :: Integral a => Ratio a -> a
numerator   (n:%d) = let (n':%_ ) = reduce n d in fromInteger \$ n' * signum d
denominator (n:%d) = let (_ :%d') = reduce n d in fromInteger \$ abs d'

notANumber = 0:%0

reduce _ 0 = notANumber
reduce x y = (x `quot` d) :% (y `quot` d)
where d = gcd x y

choose :: Ratio a -> Ratio a
-- choose = id

choose v@(n:%d) = if (abs n .|. abs d) > 0x3FFFFFFFFFFFFFFF then
reduce n d else v

instance Ord (Ratio a)  where
x:%y <= x':%y' =  case compare 0 \$ y * y' of
EQ -> False
LT -> x * y' <= x' * y
GT -> x * y' >= x' * y
x:%y <  x':%y' =  case compare 0 \$ y * y' of
EQ -> False
LT -> x * y' <  x' * y
GT -> x * y' >  x' * y
compare (x:%y) (x':%y') = case compare 0 \$ y * y' of
EQ -> EQ -- This conflicts the definition of (==) and (<=).
-- compare is used for the random-testing filters, while (==) is used by the predicate filter.
-- (But actually, compare is also used for the sortBy....)
LT -> compare (x * y')  (x' * y)
GT -> compare (x' * y)  (x * y')

instance Eq (Ratio a)  where
x:%y == x':%y' = (y * y') /= 0 && x*y' == x'*y
x:%y /= x':%y' = (y * y') /= 0 && x*y' /= x'*y

instance Integral a => Num (Ratio a)  where
(x:%y) + (x':%y') = choose \$ (x*y' + x'*y) :% (y*y')
(x:%y) - (x':%y') = choose \$ (x*y' - x'*y) :% (y*y')
(x:%y) * (x':%y') = choose \$ (x * x')      :% (y*y')
negate     (x:%y) = (-x):%y
abs        (x:%y) = abs x :% abs y
signum     (x:%0) = notANumber
signum     (x:%y) = signum (x * y) :% 1
fromInteger x     =  fromInteger x :% 1

instance Integral a => Fractional (Ratio a)  where
x:%y / x':%y' = if y' == 0 then notANumber else choose \$ (x*y') :% (y*x')
recip (x:%y) | y == 0    = notANumber
| otherwise = y:%x
fromRational r = Data.Ratio.numerator r :% Data.Ratio.denominator r

instance Integral a => RealFrac (Ratio a)  where
properFraction (x:%y) = (fromInteger q, r :% y)
where (q,r) = quotRem x y

instance (Show a, Integral a) => Show (Ratio a)  where
showsPrec p r
=  showParen (p > 7) \$
showsPrec 8 (numerator r) .
showString " % " .
showsPrec 8 (denominator r)
instance Integral a => Real (Ratio a) where
toRational (x:%y) = x Data.Ratio.% y

instance Integral a => Enum (Ratio a)  where
succ x              =  x + 1
pred x              =  x - 1

toEnum n            =  fromIntegral n :% 1
{-
enumFrom            =  numericEnumFrom
enumFromThen        =  numericEnumFromThen
enumFromTo          =  numericEnumFromTo
enumFromThenTo      =  numericEnumFromThenTo
-}

{- properties held.
prop_LE a b c d = c/=0 && d/=0 ==> let r1 = a%c <= b%d
r2 = a Data.Ratio.% c <= b Data.Ratio.% d
in r1 == r2
prop_LT a b c d = c/=0 && d/=0 ==> let r1 = a%c < b%d
r2 = a Data.Ratio.% c < b Data.Ratio.% d
in r1 == r2
prop_EQ a b c d = c/=0 && d/=0 ==> let r1 = a%c == b%d
r2 = a Data.Ratio.% c == b Data.Ratio.% d
in r1 == r2

prop_plus a b c d = c/=0 && d/=0 ==> let r1 = a%c + b%d
r2 = a Data.Ratio.% c + b Data.Ratio.% d
in toRational r1 == r2
prop_minus a b c d = c/=0 && d/=0 ==> let r1 = a%c - b%d
r2 = a Data.Ratio.% c - b Data.Ratio.% d
in r1 == fromRational r2
prop_times a b c d = c/=0 && d/=0 ==> let r1 = a%c * b%d
r2 = (a Data.Ratio.% c) * (b Data.Ratio.% d)
in numerator r1 == Data.Ratio.numerator r2 && denominator r1 == Data.Ratio.denominator r2
prop_negate a b = b/=0 ==> let r1 = negate \$ a%b
r2 = negate \$ a Data.Ratio.% b
in numerator r1 == Data.Ratio.numerator r2 && denominator r1 == Data.Ratio.denominator r2
prop_abs a b = b/=0 ==> let r1 = abs \$ a%b
r2 = abs \$ a Data.Ratio.% b
in numerator r1 == Data.Ratio.numerator r2 && denominator r1 == Data.Ratio.denominator r2
prop_signum a b = b/=0 ==> let r1 = signum \$ a%b
r2 = signum \$ a Data.Ratio.% b
in numerator r1 == Data.Ratio.numerator r2 && denominator r1 == Data.Ratio.denominator r2
prop_fromInteger a b = let r1 = fromInteger a
r2 = fromInteger a
in numerator r1 == Data.Ratio.numerator r2 && denominator r1 == Data.Ratio.denominator r2

prop_div a b c d = b/=0 && c/=0 && d/=0 ==> let r1 = a%c / b%d
r2 = (a Data.Ratio.% c) / (b Data.Ratio.% d)
in numerator r1 == Data.Ratio.numerator r2 && denominator r1 == Data.Ratio.denominator r2
prop_recip a b = a/=0 && b/=0 ==> let r1 = recip \$ a%b
r2 = recip \$ a Data.Ratio.% b
in numerator r1 == Data.Ratio.numerator r2 && denominator r1 == Data.Ratio.denominator r2
prop_properFraction a b = b/=0 ==> let (i1,r1) = properFraction \$ a%b
(i2,r2) = properFraction \$ a Data.Ratio.% b
in i1 == i2 && numerator r1 == Data.Ratio.numerator r2 && denominator r1 == Data.Ratio.denominator r2
prop_showsPrec p a b = b/=0 ==> let  r1 = showsPrec p \$ a%b
r2 = showsPrec p \$ a Data.Ratio.% b
in r1 [] == r2 []
-}
```