Why can't you compare Ints to Nums or Ords?
compare, haskell, typeclass
Solution
`>` expects two `Ord` instances of the same type.
ghci> :t (>)
(>) :: Ord a => a -> a -> Bool
That type signature is not the same as `(Ord a, Ord b) => a -> b -> Bool`, which would be the signature of a function which can compare any two instances of `Ord`. (A non-trivial version of such a function does not exist.)
The reason `>` places such a draconian requirement on the poor programmer is that different types may have different ordering semantics. How would you compare an `Int` to a `[Bool]`?* Even though they are both instances of `Ord`, it doesn't make sense to compare them and the compiler won't allow it:
ghci> 3 > [True, True, False]
<interactive>:6:1:
No instance for (Num [Bool]) arising from the literal `3'
Possible fix: add an instance declaration for (Num [Bool])
In the first argument of `(>)', namely `3'
In the expression: 3 > [True, True, False]
In an equation for `it': it = 3 > [True, True, False]
Each instance of `Ord` defines its own version of `>`. That's why you can't compare an `Int` to a `Float`:
ghci> (3 :: Int) > (4 :: Float)
<interactive>:4:15:
Couldn't match expected type `Int' with actual type `Float'
In the second argument of `(>)', namely `(4 :: Float)'
In the expression: (3 :: Int) > (4 :: Float)
In an equation for `it': it = (3 :: Int) > (4 :: Float)
* To be pedantic, you could devise some way of representing an integer in binary as a list of booleans. Such a representation would be a good candidate for a `newtype` with its own instances of `Num` and `Ord`.
The reason `4 > 4.5` works is that the literal `4` is polymorphic. It can stand in for the '4' value of any numeric type:
ghci> :t 4
4 :: Num a => a
Similarly, `4.5` can take on any fractional type (`4.5 :: Fractional a => a`). The compiler is smart enough to realise that you are comparing a value of type "any number" to a value of type "any fractional number" and uses the most convenient concrete type available, which in this case is `Double`. (`Double` is declared as a `default` in the standard prelude.) So in the expression `4 > 4.5`, `4` and `4.5` will both be `Double`s.
You can force the comparison to use the `Ord` instance of a particular concrete type by supplying a type signature to one of the operands.
Problem
I have a function: ``` comp :: (Ord a) => a -> a -> Bool comp a b = if a > b then True else False ``` This works. But if I do this: ``` comp :: (Num a) => Int -> a -> Bool comp a b = if a > b then True else False ``` or this: ``` comp :: (Ord a) => Int -> a -> Bool comp a b = if a > b then True else False ``` I get an error message: Could not deduce (a ~ Int) Huh? Doesn't Num and Ord include Int? Aren't Num and Ord only supposed to include reals and not complex numbers? Why is it that in the interpreter I can compare any real to any int: ``` 4 > 4.5 False ``` But I'm not allowed to define a function that compares Ints to Nums or Ords?