Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't a Num be compared to 0?

This function is incorrect and won't compile:

checkIsZero :: (Num a) => a -> String
checkIsZero a = if a == 0
                  then "Zero"
                  else "Not zero"

This doesn't work because of the comparison between a Num and 0 in the expression a == 0. Changing Num to Integral makes this a valid function.

What is this wicked sorcery that doesn't let me compare my numbers to 0?!

like image 535
Cory Klein Avatar asked Sep 04 '13 21:09

Cory Klein


People also ask

Why we can not compare complex numbers?

It's indeed not possible to order complex numbers since they have no ordering defined. You can compare whether two complex numbers are equal or not, but not if one is larger than the other.

Can a complex number be greater than zero?

No, imaginary numbers are not greater than 0 or less than zero. They (or, more properly, the complex numbers that they're a subset of) are unordered, so the concepts of “greater than” and “less than” don't apply to them.

Is zero a number or not?

Zero can be classified as a whole number, natural number, real number, and non-negative integer. It cannot, however, be classified as a counting number, odd number, positive natural number, negative whole number, or complex number (though it can be part of a complex number equation.)

What are the rules for comparing integers?

How to compare and order integers? Integers on the left side of 0 on the number line get smaller as we move from right to left, whereas integers on the right side of 0 get greater as we move from left to right. Therefore, to compare two integers, we can use greater than (>) or less than (<) symbols.


2 Answers

Num requires instances to implement +, *, abs, signum, and fromInteger. Note that == isn't on the list! It's instances of the Eq typeclass that must implement ==.

So, the Num constraint is not sufficient - you need an Eq constraint too. The following will compile.

checkIsZero :: (Eq a, Num a) => a -> String
checkIsZero a | a == 0    = "Zero"
              | otherwise = "Not zero"

Integral works because something which is an instance of Integral must itself be an instance of Ord, which in turn must be an instance of Eq.

You can check all this stuff by using hoogle and digging into the source.

like image 182
jtobin Avatar answered Oct 23 '22 22:10

jtobin


The reason for not requiring an Eq instance to define a Num instance is that it would rule out useful instances like

instance Num b => Num (a -> b) where
    f + g    = \x -> f x + g x
    f - g    = \x -> f x - g x
    f * x    = \x -> f x * g x
    abs f    = \x -> abs (f x)
    signum f = \x -> signum (f x)
    fromInteger = const . fromInteger

because you can't write an Eq instance for a function.

like image 29
Chris Taylor Avatar answered Oct 23 '22 21:10

Chris Taylor