Haskell列表反转错误

时间:2010-10-05 06:04:14

标签: list haskell recursion

我正在为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

4 个答案:

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

对更好的代码有何评论?我不认为它有效率......