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

(%) :: Int -> Int -> Ratl
x % y = Ratl (x `div` (gcd x y)) (y `div` (gcd x y))

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

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

instance Num Ratl where
    -- a/b * c/d = (a*c)/(b*d)
    (Ratl a b) * (Ratl c d) = (a*c) % (b*d)
    -- a/b + c/d = (a*d + c*b)/(b*d)
    (Ratl a b) + (Ratl c d) = ((a*d) + (c*b)) % (b*d)

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

data Sexpr = Symbol String | Number Int | Cons Sexpr Sexpr | Nil

foo = (Cons (Number 1) (Cons (Number 2) (Cons (Number 3) Nil)))
bar = (Cons (Cons (Symbol "foo") Nil) Nil)

instance Show Sexpr where
    show (Nil) = "()"
    show (Symbol x) = x
    show (Number x) = show x
    show (Cons x Nil) = "(" ++ (show x) ++ ")"
    show (Cons x y@(Cons _ _)) = "(" ++ (show x) ++ (showCdr y) ++ ")"
    show (Cons x y) = "(" ++ (show x) ++ " . " ++ (show y) ++ ")"

showCdr :: Sexpr -> [Char]
showCdr (Nil) = ""
showCdr (Cons x Nil) = " " ++ (show x)
showCdr (Cons x y@(Cons _ _)) = " " ++ (show x) ++ (showCdr y)
showCdr (Cons x y) = " " ++ (show x) ++ " . " ++ (show y)
showCdr x = " . " ++ (show x)