functionhaskellequalityhaskell-platform

Why cant i have a "equal" rational function


i am very new to the haskell and have a question about Eq.

data Rat = Rat Integer Integer

normaliseRat :: Rat -> Rat
normaliseRat (Rat x y)      
    |x < 0 && y < 0 = Rat (-x) (-y) 
    |otherwise = Rat (x `div`(gcd x y)) (y `div` (gcd x y))

So i have a func normaliseRat. And what i need is an instance of Eq and Ord. Of course, Rat 2 4 == Rat 1 2 should be valid.

Thanks for help


Solution

  • Haskell doesn't support function overloading. But (==) isn't a function; it's declared as a typeclass method, so any type-specific implementations of the method must be defined within an instance declaration, like so:

    instance Eq Rat where
        (Rat x y) == (Rat n m) = x * m == y * n
    

    (x/y == n/m is equivalent, after cross multiplying, to x * m == y * n; multiplication is more efficient and has none of accuracy issues that division would introduce.)

    The same applies to Ord, except you have your choice of implementing (<=) or compare. (Given either of those, default definitions for the other comparison methods will work.)

    instance Ord Rat where
        -- I leave fixing this to accommodate negative numbers
        -- correctly as an exercise.
        (Rat x y) <= (Rat n m) = (x * m) <= (y * n)
    

    As a typeclass method, (==) is really an entire family of functions, indexed by the type it's being used with. The purpose of the instance declaration is not to redefine the method, but to add a new function to that family.

    If you enable the TypeApplications extension, you can view (==) as a mapping from a type to a function.

    > :t (==)
    (==) :: Eq a => a -> a -> Bool
    > :t (==) @Int
    (==) @Int :: Int -> Int -> Bool
    

    Without a type application, Haskell's type checker automatically figures out which function to use:

    > (==) 'c' 'd'
    False
    > (==) 3 5
    False
    

    but you can be explicit:

    > (==) @Char 'c 'd'
    False
    > (==) @Char 3 5
    
    <interactive>:9:12: error:
        • No instance for (Num Char) arising from the literal ‘3’
        • In the second argument of ‘(==)’, namely ‘3’
          In the expression: (==) @Char 3 5
          In an equation for ‘it’: it = (==) @Char 3 5