我正在为haskell写一个列表反转程序。
我已经有了列表反转的想法,这导致了以下代码:
myreverse list1
| list1 == [] = list1
| otherwise = (myreverse(tail list1)):(head list1)
不幸的是,上面的代码会导致以下错误:
Occurs check: cannot construct the infinite type: a = [[a]]
Expected type: [[a]]
Inferred type: a
In the second argument of '(:)', namely '(head list1)'
In the expression: (myreverse(tail list1)):(head list1)
PS:当我在我编写的名为mylast编码的片段上运行时,我遇到了同样的错误:
mylast list
| list == [] = []
| otherwise = mylast_helper(head list1)(tail list1)
mylast_helper item list2
| list2 == [] = item
| otherwise = mylast_helper(head list2)(tail list2)
在递归助手的情况下会出现错误。
编辑:感谢所有的输入,我想我忘了提到问题的限制条件禁止使用++运算符。对于我创建的未来问题,我会牢记这一点。干杯, -Zigu
答案 0 :(得分:4)
您正在使用该功能
(:) :: a -> [a] -> [a]
带有错误的参数:
myReverse (tail list1) :: [a]
head list1 :: a
在您的函数中,列表 list1 必须具有 a 类型。因此,第二个参数 head list1 必须具有 [a] 类型。 GHC警告您它无法构造您为其指定的类型。列表的头部在结构上小于列表的尾部,但是您告诉它列表的头部具有类型 [a] ,但列表的尾部具有类型一个
但是,如果你仔细盯着你的类型,你会注意到你可以将 list1 的头追加到 myreverse 的递归调用中>使用(++):
myReverse xs = case (null xs) of
True -> xs
False -> myReverse (tail xs) ++ [head xs]
在这里,
[head xs] :: [a]
myReverse (tail xs) :: [a]
与追加的类型对齐:
(++) :: [a] -> [a] -> [a]
然而,有更好的方法来实现 reverse 。 Prelude将 reverse 定义为左侧折叠(。 reverse 的另一个版本可以使用右侧折叠实现,与 myReverse 非常相似功能:
reverse xs = foldr (\x xs -> xs ++ [x]) [] xs
答案 1 :(得分:3)
缺点(:
)的类型是a -> [a] -> [a]
- 换句话说,你给它一个元素,然后是一个列表,它将元素放在列表的开头。在你的最后一行中,你首先进行反向列表,然后是一个元素。要解决此问题,请将:
更改为列表concat运算符++
:
myreverse list1
| list1 == [] = list1
| otherwise = (myreverse (tail list1)) ++ [head list1]
(为了尝试翻译错误,它说“好了,你给我的:
的第一个参数是一个列表,因此第二个参数需要是同一类型的元素列表,所以列表列表......但是......你给了我一个参数,它是列表元素的类型,所以我需要一些与该类型列表相同的类型,我是不能做。砰!“)
答案 2 :(得分:3)
首先,尝试为每个功能添加签名;这将有助于编译器知道您正在尝试做什么,并在之前为您提供更好的错误消息。签名看起来像这样,例如:mylast :: [a] -> a
。然后,使用模式匹配,而不是使用保护(|
),通过一系列方程定义您的函数:
mylast :: [a] -> a
mylast (x:[]) = x
mylast (_:t) = mylast t
在GHCi中,您可以使用:t
term 查看某些内容的类型。这是我能给出的最好的一般建议......仔细看看这些类型并确保它们对你如何使用它们有意义。
答案 3 :(得分:1)
更多地继续处理这个问题并自己回答。 非常感谢您的反馈。它把我推向了正确的方向。
myreverse list1
| list1 == [] = list1
| otherwise = myreverse_h(list1)([])
myreverse_h list1 list2
| list1 == [] = list2
| otherwise = myreverse_h(tail list1)((head list1):list2)
对更好的代码有何评论?我不认为它有效率......