質問

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?!

役に立ちましたか?

解決

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.

他のヒント

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.

If data is an instance of Num a, it is not a grantee , that this data is an instance of Eq a.

Integer (and Int, Double) has both instances: instance Num Integer and instance Eq Integer, and program is valid

Integral is defined as

class (Real a, Enum a)=> Integral a where ...
class (Num a, Ord a)=> Real a where ...
class Eq a => Ord a where ...

 ~= class (Num a, Eq a, Enum a)=> Integral a where ... --means
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top