嘿,所以我在课堂上学习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
我猜测语法错误,但我不确定如何修复它。谢谢你的帮助。
答案 0 :(得分:5)
一些事情:
您的类型注释表明您的函数将接收单个列表参数并返回列表,而实现表明您应该接收两个参数,第一个参数是单个元素。
此外,由于您使用==
进行比较,因此您需要确保您的类型属于Eq
类型类。
您的类型注释应该如下所示:
removeElement :: Eq a => a -> [a] -> [a]
您还可以利用模式匹配来简化操作。如果您按照以下方式定义函数,则不需要使用head
和tail
:
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
有些事情是“显而易见的”:
x :: [a]
作为removeElement
的参数。t -> v
和t
,lambda表达式的类型为v
。但我们已经说过removeElement :: [a] -> [a]
,那么我们可以提出t
和v
的值[a] ~ t -> v
吗?也许。让我们继续推断类型。
t
是aList
的类型,我们可以将其从head aList == x
推断为[[a]]
。暂时跳过递归调用,我们还可以看到aList
是返回值,因此v
也是[[a]]
。因此,t -> v
确实是[[a]] -> [[a]]
。
我们可以将[[a]] -> [[a]]
类型的值与[a]
匹配吗?
不,这就是您收到确切错误消息的原因。
答案 2 :(得分:0)
您的类型签名应为
removeElement :: a -> [a] -> [a]
此外,看起来你的功能没有按你认为的那样做。