Why can't Haskell perform pattern matching on Num
types, without us specifying Eq
as a type class?
For instance:
h :: Num a => a -> a
h 0 = -1
h x = x + 1
When compiling this function, ghci
complains:
* Could not deduce (Eq a) arising from the literal `0'
from the context: Num a
bound by the type signature for:
h :: forall a. Num a => a -> a
at functions.hs:9:1-20
Possible fix:
add (Eq a) to the context of
the type signature for:
h :: forall a. Num a => a -> a
* In the pattern: 0
In an equation for `h': h 0 = - 1
|
10 | h 0 = -1
| ^
Changing the function definition as following compiles and runs perfectly:
h :: (Num a, Eq a) => a -> a
h 0 = -1
h x = x + 1
*Main> h 0
-1
*Main>
From the Haskell 2010 Report, the section entitled Informal Semantics of Pattern Matching:
Matching a numeric, character, or string literal pattern k against a value v succeeds if v
==
k
So when you use a literal (such as 0
) as a pattern, its meaning depends upon ==
(a method of the Eq
class).
For example, your function h
h 0 = -1
h x = x + 1
can be rewritten as
h x | x == 0 = -1
h x = x + 1
You are (implicitly) using the ==
method, therefore you need an Eq
constraint.
There are two important observations here about how Haskell differs from a lot of other languages:
x == y
unless the type of x
and y
has an Eq
instance.Num
. You can define your own type and make it an instance of Num
, and it doesn't necessarily have to also have an instance of Eq
. So not all "numbers" can be compared for equality.So it is insufficient for the context of your function h
to be "a
has to be a number." The context must be, more specifically, "a
has to be a number with an equality test" to ensure that there is a way to check whether x
is equal to 0
in order to perform the pattern match.
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