-- 300 BC Euclid
gcd' (x, y) =
  if x == y then x
  else if x < y then gcd' (x, y - x)
  else gcd' (x - y, x)

lcm' (x, y) = head [ x * i | i <- [1..], j <- [1..x], x*i == y*j]

data Rational = Rational {numr :: Int, denr :: Int}

(%) :: Int -> Int -> Rational
x % y = let z = gcd x y in Rational (x `div` z) (y `div` z)

instance Eq Rational where
  (Rational a b) == (Rational c d) = a * d == b * c

instance Show Rational where
  show (Rational x 1) = show x
  show (Rational 0 _) = "0"
  show (Rational x y) = show x ++ "/" ++ show y

instance Num Rational where
  (Rational a b) * (Rational c d) = (a * c) % (b * d)
  (Rational a b) + (Rational c d) = (a*d + c*b) % (b*d)
  fromInteger x = fromIntegral x % 1

instance Fractional Rational where
  (Rational a b) / (Rational c d) = (a * d) % (b * c)

instance Ord Rational where
  (Rational a b) > (Rational c d) = a*d > b*c
  (Rational a b) < (Rational c d) = a*d < b*c

instance Enum Rational where
  succ (Rational a b) = if a < b then Rational (succ a) b else Rational 1 (succ b)
  fromEnum x = f x $ zip rats ints
  toEnum x = f x $ zip ints rats

ints = 1 : map succ ints
rats = (1 % 1) : map succ rats

f x = snd . head . dropWhile ((/= x) . fst)