如何解决这个Haskell类型错误?预期类型和实际类型不匹配



我正试图使用foldr和助手函数将一个列表中的所有最大整数提取到另一个列表。我对foldr的理解与错误信息相冲突。这是我的代码:

largest :: [Int] -> [Int]
largest [] = []
largest xs = foldr largestHelper [] xs
largestHelper :: [Int] -> Int -> [Int]
largestHelper [] prev = [prev]
largestHelper (lrg : lrgs) prev | lrg < prev  = [prev]
| lrg == prev = prev : (lrg : lrgs)  
| otherwise   = (lrg : lrgs)

在我看来,要计算的第一个函数似乎是largestHelper,其中包含整数列表的最后一个元素和[]。接下来是largestHelper,使用列表的倒数第二个元素和上一次迭代,因为它是迄今为止最大的元素,所以它只是最后一个元素。因此,largest xs最终计算出一个列表,该列表包含一个或多个从给定列表中找到的最大值的整数。

以下是错误:

largest.hs:3:20: error:
* Couldn't match type `[Int]' with `Int'
Expected type: [Int] -> [Int] -> [Int]
Actual type: [Int] -> Int -> [Int]
* In the first argument of `foldr', namely `largestHelper'
In the expression: foldr largestHelper [] xs
In an equation for `largest':
largest xs = foldr largestHelper [] xs
|
3 | largest xs = foldr largestHelper [] xs
|                    ^^^^^^^^^^^^^
largest.hs:3:37: error:
* Couldn't match type `Int' with `[Int]'
Expected type: [[Int]]
Actual type: [Int]
* In the third argument of `foldr', namely `xs'
In the expression: foldr largestHelper [] xs
In an equation for `largest':
largest xs = foldr largestHelper [] xs
|
3 | largest xs = foldr largestHelper [] xs
|

第一个似乎是说largestHelper实际上正在接收两个整数列表,而不是它正在构建的一个。但是,foldr不是一个接一个地给出了给largest的列表中的元素吗?因此,largestHelper的第二个参数确实是一个整数,而不是一个整数列表?第二个似乎说largest的论点实际上是[[Int]]而不是[Int]。我不明白。

如果能澄清这种混淆,我将不胜感激。我还不知道这是否有效,因为它不会编译,作为函数式编程和Haskell的初学者,我也很感激考虑到代码的逻辑和风格的评论。

您的两个类型错误遵循模式Couldn't match type `foo' with `bar'Couldn't match type `bar' with `foo'。问题是largestHelper的参数顺序错误。foldr调用它的函数时,元素第一,累加器第二,但largestHelper希望累加器第一,元素第二。切换它们的顺序,您的类型错误将得到修复。

让我们分解第一条错误消息:

largest.hs:3:20: error:
[...]
|
3 | largest xs = foldr largestHelper [] xs
|                    ^^^^^^^^^^^^^

编译器在文件largest.hs的第3行第20列发现问题。它还打印了相关行。

* In the first argument of `foldr', namely `largestHelper'
In the expression: foldr largestHelper [] xs
In an equation for `largest':
largest xs = foldr largestHelper [] xs

再次给出位置,但这次是根据参数、表达式和方程式给出的。我们了解到largestHelper存在问题。

* Couldn't match type `[Int]' with `Int'
Expected type: [Int] -> [Int] -> [Int]
Actual type: [Int] -> Int -> [Int]

编译器预期largestHelper的类型为[Int] -> [Int] -> [Int],但发现它的实际类型是[Int] -> Int -> [Int]。由于[Int]Int不同,编译器报告了一个错误。

因此,在查看了错误消息后,我们得出了两个新问题:

  • 为什么编译器期望largestHelpler的类型为[Int] -> [Int] -> [Int]?这是关于统一的问题,在"如何手动推断表达式的类型"中有一些很好的答案
  • 如何解决问题?这已经由joseph sible解释了,恢复了monica的回答

请注意,编译器能够识别问题,因为您的编程语言使用类型。也就是说,类型赋予它发现代码有问题的能力。因此,当编译器在现实中遇到最奇怪、最复杂的技术术语时,它可能会认为自己是你的得力助手。这取决于你来解决问题。

相关内容

最新更新