Since Ord is a Subclass of Eq I find it difficult to understand how making a newtype instance of that class will look like.
I have managed to do this:
newtype NT1 = NT1 Integer
instance Eq NT1 where
(NT1 x) == (NT1 y) = x == y
instance Ord NT1 where
(NT1 x) `compare` (NT1 y) = x `compare` y
If I for examle have a variable x = NT1 5 and variable y = NT1 5 and type x == y it will return True
I managed also to do this:
instance Show NT1 where
show (NT1 n) = show n
whill display x = NT1 5 as 5 instead of NT1 5
following this I should be able to do something like this:
instance Ord NT1 where
(>) (NT1 x)(NT1 y) = (NT1 x) > (NT1 y)
(<) (NT1 x)(NT1 y) = (NT1 x) < (NT1 y)
(<=) (NT1 x)(NT1 y) = (NT1 x) <= (NT1 y)
(>=) (NT1 x)(NT1 y) = (NT1 x) >= (NT1 y)
But this doesn't work. How do I do this with Ord class :
class (Eq a) => Ord a where
compare :: a -> a -> Ordering
(<), (<=), (>=), (>) :: a -> a -> Bool
max, min :: a -> a -> a
?
following this I should be able to do something like this:
instance Ord NT1 where (>) (NT1 x)(NT1 y) = (NT1 x) > (NT1 y) (<) (NT1 x)(NT1 y) = (NT1 x) < (NT1 y) (<=) (NT1 x)(NT1 y) = (NT1 x) <= (NT1 y) (>=) (NT1 x)(NT1 y) = (NT1 x) >= (NT1 y)
What you here do is basically defining a set of functions where each function calls itself, with the same parameters, so this will get stuck in an infinite loop.
Indeed, here for example you define:
instance Ord NT1 where (>) (NT1 x)(NT1 y) = (NT1 x) > (NT1 y)
so that means that you say NT1 x > NT1 y, given NT1 x > NT1 y, but of course that does not really do anything.
The nice thing is that you do not need to define all these functions: Haskell has constructed already a lot of other functions in the Ord typeclass in terms of others, so if we take a look at the documentation for Ord, we see:
Minimal complete definition
compare | (<=)
So implementing compare, or (<=) is sufficient. Haskell can, based on that implementation, also calculate the other comparisons, as well as min, max, etc. You can implement these, if for example there are more efficient ways to check if NT1 x < NT1 y than calling compare and checking if the result is LT.
Your implementation like:
newtype NT1 = NT1 Integer instance Eq NT1 where (NT1 x) == (NT1 y) = x == y instance Ord NT1 where (NT1 x) `compare` (NT1 y) = x `compare` y
is thus sufficient, for example:
Prelude> NT1 14 < NT1 25
True
thus compares the two objects correctly.
This is also a straightforward implementation, the fact that two NT1 objects are equal if the constructors are the same (well here there is only one constructor), and the arguments is a straightforward implementation.
Ord has also a "popular" implementation: an object is considered smaller than another object given that the constructor of the first object is defined before the constructor of the second object, or if the constructors are the same, that the arguments are smaller by comparing these "lexicographically".
Haskell has support for these kind of implementations, you can use a deriving clause in your type definition:
newtype NT1 = NT1 Integer deriving (Show, Eq, Ord)
Here we thus "automatically" implement the Eq, Ord and Show typeclass. For Show it is implemented by first showing the name of the constructor followed by the show of the arguments. It also adds brackets in some cases where it is ambiguous (although the rules are a bit more complex).
We can also, like @DanielWagner says implement these functions ourself, with:
instance Ord NT1 where
compare (NT1 x) (NT1 y) = compare x y
(>) (NT1 x)(NT1 y) = x > y
Here we thus do not call this with NT1 data constructors on the right side, since otherwise we would simply call this function again with the same parameters. With the above implementation, we call x > y, so (>) but on the arguments wrapped in the constructor.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With