Haskell:无法将预期类型与实际类型匹配

时间:2016-04-14 16:58:27

标签: haskell

嘿,所以我在课堂上学习Haskell,我遇到了从列表中删除所有实例的问题。这是我的目标,但我遇到了这个错误,我不确定我是否会这样做。

--delete element from list 
removeElement :: [a] -> [a]
removeElement x [] = []
removeElement x aList =
    if (head aList) == x
        then removeElement x (tail aList)
        else aList

我收到的错误是:

Couldn't match expected type `[[a]] -> [[a]]'
                with actual type `[a]'
    Relevant bindings include
      removeElement :: [a] -> [a] (bound at hwmk3.hs:8:1)
    The equation(s) for `removeElement' have two arguments,
    but its type `[a] -> [a]' has only one

我猜测语法错误,但我不确定如何修复它。谢谢你的帮助。

3 个答案:

答案 0 :(得分:5)

一些事情:

您的类型注释表明您的函数将接收单个列表参数并返回列表,而实现表明您应该接收两个参数,第一个参数是单个元素。

此外,由于您使用==进行比较,因此您需要确保您的类型属于Eq类型类。

您的类型注释应该如下所示:

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

您还可以利用模式匹配来简化操作。如果您按照以下方式定义函数,则不需要使用headtail

removeElement x aList@(y:ys) =
  if y == x
    then removeElement x ys
    else aList

但是,条件语句中存在逻辑错误。因为这听起来像家庭作业,我会留给你找到答案。提示,请尝试removeElement 3 [1, 2, 3]

答案 1 :(得分:1)

如果您省略了函数的显式类型声明,Haskell会推断类似a -> [a] -> [a]的内容。事实上,它仍然推断,这就是为什么它抱怨它不同意你声明的类型。

Haskell报告的问题是这个。看看你的第二个方程式,这个方程式去了

removeElement x = \aList -> if (head aList) == x then removeElement x (tail aList) else aList

有些事情是“显而易见的”:

  1. x :: [a]作为removeElement的参数。
  2. 对于某些类型t -> vt,lambda表达式的类型为v
  3. 但我们已经说过removeElement :: [a] -> [a],那么我们可以提出tv的值[a] ~ t -> v吗?也许。让我们继续推断类型。

    taList的类型,我们可以将其从head aList == x推断为[[a]]。暂时跳过递归调用,我们还可以看到aList是返回值,因此v也是[[a]]。因此,t -> v确实是[[a]] -> [[a]]

    我们可以将[[a]] -> [[a]]类型的值与[a]匹配吗?

    不,这就是您收到确切错误消息的原因。

答案 2 :(得分:0)

您的类型签名应为

removeElement :: a -> [a] -> [a]

此外,看起来你的功能没有按你认为的那样做。