Haskell 列表反转错误
我正在为 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)
递归助手的其他情况下会发生错误。
编辑:感谢您的所有输入,我想我忘记提及问题的约束禁止使用 ++ 运算符。我会在以后提出问题时牢记这一点。
干杯, -紫谷
I'm writing a list reversal program for haskell.
I've got the idea for the list reversal and that has lead to the following code:
myreverse list1
| list1 == [] = list1
| otherwise = (myreverse(tail list1)):(head list1)
Unfortunately the above code results in the following error:
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: I get the same sort of error when I run it on a snippet that I wrote called mylast coded below:
mylast list
| list == [] = []
| otherwise = mylast_helper(head list1)(tail list1)
mylast_helper item list2
| list2 == [] = item
| otherwise = mylast_helper(head list2)(tail list2)
Error occurs at the otherwise case of the recursive helper.
EDIT: Thanks for all the input, I guess I forgot to mention that the constraints of the question forbid the use of the ++ operator. I'll keep that in mind for future questions I create.
Cheers,
-Zigu
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您使用的函数
带有错误类型的参数:
在您的函数中,列表 list1 必须具有类型 a。因此,第二个参数 head list1 必须具有类型 [a]。 GHC 警告您它无法构造您为其指定的类型。列表的头部在结构上小于列表的尾部,但是您告诉它列表的头部具有类型 [a],而列表的尾部具有类型 一个。
但是,如果您仔细观察您的类型,您会发现您可以使用 将 list1 的头部附加到 myreverse 的递归调用中。 em>(++):
这里
与 append 的类型一致:
(++) :: [a] -> [一]-> [a]
然而,还有更好的方法来实现反向。 Prelude 将 reverse 定义为左折叠(。reverse 的另一个版本可以使用右折叠来实现,并且与您的 myReverse 非常相似功能:
You are using the function
with ill-typed arguments:
In your function, the list list1 must have type a. Hence the second argument, head list1, must have type [a]. GHC is warning you that it cannot construct the type you have specified for it. The head of a list is structurally smaller than the tail of a list, but you are telling it that the head of a list has type [a], yet the tail of a list has type a.
If you stare closely at your types, however, you will notice that you can append the head of list1 to the recursive call to myreverse using (++):
Here,
which aligns with the type of append:
(++) :: [a] -> [a] -> [a]
There are much better ways to implement reverse, however. The Prelude defines reverse as a left fold (. Another version of reverse can be implemented using a right fold, and is very similar to your myReverse function:
首先,尝试为每个函数添加签名;这将帮助编译器知道您正在尝试做什么,并尽早为您提供更好的错误消息。签名看起来像这样,例如:
mylast :: [a] ->一个。然后,不要使用守卫 (
|
),而是使用模式匹配通过一系列方程定义函数:在 GHCi 中,您可以使用
:t
术语。这是我能给出的最好的一般建议......仔细查看类型并确保它们对于您如何使用它们有意义。First off, try adding a signature to each of your functions; this will help the compiler know what you're trying to do and give you better error messages earlier on. A signature would look like this, for example:
mylast :: [a] -> a
. Then, instead of using guards (|
), define your function through a series of equations, using pattern matching:In GHCi, you can look at the type of something using
:t
term. That's the best general advice I can give... look carefully at the types and make sure they make sense for how you're using them.cons (
:
) 的类型是a ->; [一]-> [a]
- 换句话说,您给它一个元素,然后给它一个列表,并将该元素放在列表的开头。在最后一行中,您将执行相反的操作 - 首先列出列表,然后列出元素。要修复此问题,请将:
更改为列表 concat 运算符++
:(要尝试翻译该错误,它会说“好的,
的第一个参数:
你给我的是一个列表,因此第二个参数需要是相同类型的元素列表,所以列表的列表......但是......你给了我一个参数是列表中元素的类型,所以我需要某种与该类型的列表列表相同的类型,但我做不到!”)The type of cons (
:
) isa -> [a] -> [a]
- in other words, you give it an element and then a list and it puts the element at the start of the list. In your last line, you're doing the reverse - list first and then an element. To fix it up, change the:
to the list concat operator++
:(To try and translate the error, it's saying "OK, the first argument to
:
you've given me is a list, therefore the second argument needs to be a list of elements of that same type, so a list of lists...BUT...you've given me an argument which is the type of an element of the list, so I need some type that is the same as a list of lists of that type, which I can't do. Bang!")最终我更多地研究这个问题并自己回答。
非常感谢您的反馈。它推动我沿着正确的方向前进。
对于更好的代码有什么评论吗?我认为它没有那么有效...
Ended up working on this question more and answering it myself.
Thanks a lot for the feedback. It pushed me along the right direction.
Any comments on better code though? I don't think its as efficient as it could be...