当我们有一个使用==
比较运算符比较两件事的函数时,我们在类型声明中添加类似Eq a => a...
的内容;但这并非总是如此。
例如,给定以下功能:
tail' xs = if length xs == 0
then []
else drop 1 xs
我们利用了==
比较运算符,因此我认为正确的类型声明应为:
tail':: (Eq a) => [a] -> [a]
但是,运行:t tail'
告诉我正确的类型十进制是:
tail':: [a] -> [a]
为什么会这样?为什么在类型声明中不需要Eq
?
答案 0 :(得分:6)
Eq a => t
说a
必须是类型Eq
的{{1}}的实例。作为t
实例的类型意味着为该类型定义了Eq
。但是在==
的定义中,您永远不会在tail'
上使用==
,即使是通过代理也是如此。 a
的实际用法是在==
中。 length xs == 0
(和length xs
)的类型为0
,并且Int
已经是Int
的实例,因此我们已经知道它具有{{1} }定义。由于您从未在Eq
上使用==
,因此不需要==
约束。
但是,如果您说的a
似乎是等效的(都测试列表是否为空),则您将受到Eq a
约束。这是因为xs == []
上的Eq a
需要一个==
约束,因为它在每个列表的条目上使用[a]
来比较列表。但是,由于您可以使用Eq a
(或者更好的是==
),所以这种增加的约束是虚假的,应该避免。
(顺便说一句,length xs == 0
甚至不需要null xs
,但这与所问的问题无关。)