我是Haskell的新手。我写了这段代码:
deleteDuplicates :: [a] -> [a]
deleteDuplicates [] = []
deleteDuplicates (x:xs)
| x == (head xs) = x : (deleteDuplicates (tail xs))
| otherwise = x : (head xs) : (deleteDuplicates (tail xs))
这个错误意味着什么,为什么会发生?我是不是意外地比较了两种不同的类型?
set2.hs:10:3:
Could not deduce (Eq a) from the context ()
arising from a use of `==' at set2.hs:10:3-16
Possible fix:
add (Eq a) to the context of
the type signature for `deleteDuplicates'
In the expression: x == (head xs)
In a stmt of a pattern guard for
the definition of `deleteDuplicates':
x == (head xs)
In the definition of `deleteDuplicates':
deleteDuplicates (x : xs)
| x == (head xs) = x : (deleteDuplicates (tail xs))
| otherwise = x : (head xs) : (deleteDuplicates (tail xs))
答案 0 :(得分:18)
您的类型签名错误:
deleteDuplicates :: [a] -> [a]
这表示你的函数可以在任何类型的列表a
上工作,但事实并非如此!您稍后致电:
x == (head xs)
所以你必须能够比较你的类型是否相等。签名必须是:
deleteDuplicates :: Eq a => [a] -> [a]
在这种情况下,最好删除显式类型签名,在GHCi中加载函数并发现解释器认为应该具有的类型(通过:t deleteDuplicates
)。
更多错误
此外,您使用head
有一个坏主意。 head
是部分功能,在xs == []
时会失败。我建议你扩展模式匹配:
deleteDuplicates (x1:x2:xs)
| x1 == x2 = ...
| otherwise = x1 : deleteDuplicates (x2:xs)
另请注意otherwise
案例的修复程序。你跳过了x2,但是如果x2匹配列表中的下一个元素呢?像[1,2,2,3]
这样的东西会发现1 /= 2
,然后递归就会得到列表[2,3]
- 哎呀!
答案 1 :(得分:2)
编译器告诉您,如果a
是Eq
的实例,则仅从类型签名中就无法解决问题。
deleteDuplicates :: Eq a => [a] -> [a]
您需要告诉编译器a
是Eq类型类的实例,方法是在签名中提及它。
答案 2 :(得分:1)
表达式
x == (head xs)
要求在==
的成员上定义xs
,这意味着a
必须是类型类Eq
的实例。将函数的类型签名更改为
deleteDuplicates :: Eq a => [a] -> [a]