I've implemented a normalisation function normaliseRat :: Rat -> Rat for rational numbers so that all of Rat 2 4, Rat (-1) (-2) and Rat 1 2 are transformed into the same internal representation. Furthermore, implemented a function createRat :: Integer -> Integer -> Rat that, given two Integers, returns a normalised Rat. Note: I used the Prelude that contains a function gcd to compute the greatest common divisor of two integers.
gcd' :: Integer -> Integer -> Integer
gcd' a b = if b == 0 then a else gcd' b (a `mod` b)
data Rat = Rat Integer Integer
normaliseRat :: Rat -> Rat
normaliseRat (Rat num den) =
let commonDivisor = gcd' (abs num) (abs den)
num' = num `div` commonDivisor
den' = den `div` commonDivisor
in Rat (if den < 0 then (-num') else num') (abs den')
createRat :: Integer -> Integer -> Rat
createRat num den = normaliseRat (Rat num den)
-- Adding the Show instance for Rat
instance Show Rat where
show (Rat num den) = show num ++ "/" ++ show den
This program is giving the expected result. Like:
ghci>createRat 2 4
ghci> rat1
1/2
Now I want to make Rat an instance of Eq and Ord. Of course, Rat 2 4 == Rat 1 2 should evaluate to True.
We know that two fractions a/b and c/d are equal if a×d = c×b (given the denominators are not zero), so we can implement the
Eq
instance as:I leave the instance of
Ord
as an exercise. This will be more complicated, since the denominators can be negative as well.