无法从上下文中推导出(Eq a)(...)

时间:2011-04-27 15:51:59

标签: haskell types typeclass

我是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))

3 个答案:

答案 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)

编译器告诉您,如果aEq的实例,则仅从类型签名中就无法解决问题。

deleteDuplicates :: Eq a => [a] -> [a]

您需要告诉编译器aEq类型类的实例,方法是在签名中提及它。

答案 2 :(得分:1)

表达式

x == (head xs)

要求在==的成员上定义xs,这意味着a必须是类型类Eq的实例。将函数的类型签名更改为

deleteDuplicates :: Eq a => [a] -> [a]