24
votes

This function:

hola :: (Integral a) => a -> String
hola 1 = "OK"
hola _ = "asdf"

works fine. But this one:

hola :: (Num a) => a -> String
hola 1 = "OK"
hola _ = "asdf"

can't be compiled: "Could not deduce (Eq a) arising from the literal `1'"

I really don't get it. I am reading a tutorial where it is said

"Integral is also a numeric typeclass. Num includes all numbers, including real numbers and integral numbers, Integral includes only integral (whole) numbers. In this typeclass are Int and Integer." http://learnyouahaskell.com/types-and-typeclasses

Why can't I use Num?

2

2 Answers

32
votes

It's a recent change proposed and accepted in September/October last year, in the latest version of the base package, Eq and Show are no longer superclasses of Num. Since that change, no new version of the language report has been published, so it's not yet in the report. And since it's recent, it has also not made it yet into many tutorials or books.

"Pattern matching" against a numeric literal is an implicit application of (==), so an Eq instance is required for it to work. That instance can now no longer be inferred from the Num constraint, so the (quite new :D) compiler rejects the code with only a Num constraint.

But Integral is a subclass of Real, which has Ord (and hence Eq) as a superclass, hence that works.

8
votes

As Daniel Fischer said, it used to work but it now doesn't work because Num and Eq were split so Num a does not imply Eq a anymore. To fix your code just make Eq a explicit:

hola :: (Num a, Eq a) => a -> String
hola 1 = "OK"
hola _ = "asdf"