我是Haskell的新手,请原谅我提出这个可能很明显的问题,但我对此感到惊讶:
len2 :: [a] -> Int
len2 xx = if xx == [] then 0 else 1 + (len2 (tail xx))
给了我:
No instance for (Eq a) arising from a use of ‘==’
Possible fix:
add (Eq a) to the context of
the type signature for len2 :: [a] -> Int
In the expression: xx == []
我很惊讶,因为我认为Haskell可以在不查看任何元素的情况下判断列表是否为[]
(在C ++中,我会看到列表的大小为0,并将其留在那里,例如) 。
答案 0 :(得分:9)
在这种情况下,(==)
的类型为Eq a => [a] -> [a] -> Bool
。希望你同意在看到任何参数之前Eq a
约束是有意义的:如果你想检查两个任意列表是否相等,你必须知道如何检查元素是否相等。您可能希望,一旦您将(==)
应用于具体参数[]
,则不需要Eq a
约束,但实际上这是一个非常微妙的注意事项。也许部分评估可以产生没有约束的函数。但是现存的实现并没有尝试进行这种分析;他们保留了保守类型Eq a => [a] -> Bool
,它已经排除了[a]
个参数,但没有Eq a
约束。
一些选项:
使用null :: [a] -> Bool
代替(==[])
。
len2 xx = if null xx then ... else ...
模式匹配,因此:
len2 [] = ...
len2 (x:xs) = ...
作为奖励,这样您就可以避免调用讨厌的tail
函数。
我会说选择(2)明显更具惯用性。