为什么Haskell无法在Num
类型上执行模式匹配,而我们没有将Eq
指定为类型类?
例如:
h :: Num a => a -> a
h 0 = -1
h x = x + 1
编译此功能时,ghci
会抱怨:
* 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
| ^
更改函数定义,如下所示编译并完美运行:
h :: (Num a, Eq a) => a -> a
h 0 = -1
h x = x + 1
*Main> h 0
-1
*Main>
答案 0 :(得分:4)
从Haskell 2010 Report开始,名为模式匹配的非正式语义的部分:
如果 v
==
,则将数字,字符或字符串文字模式 k 与值 v 匹配成功ķ
因此,当您使用文字(例如0
)作为模式时,其含义取决于==
(Eq
类的方法)。
例如,您的函数h
h 0 = -1
h x = x + 1
可以改写为
h x | x == 0 = -1
h x = x + 1
您(隐式)使用==
方法,因此您需要Eq
约束。
这里有两个关于Haskell与许多其他语言有何不同的重要观察结果:
x == y
和x
的类型具有{{1},否则无法询问是否y
实例。Eq
实例的类型。您可以定义自己的类型并将其设为Num
的实例,并且它也不一定必须具有Num
的实例。所以并非所有"数字"可以比较平等。因此,您的函数Eq
的上下文不足以成为" h
必须是数字。"更具体地说,上下文必须是" a
必须是具有相等性测试的数字"确保有办法检查a
是否等于x
以执行模式匹配。