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
CodePudding user response:
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
(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