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

How to solve this Haskell type error? Expected and actual types do not match

提问人:jvkloc 提问时间:7/5/2021 更新时间:7/6/2021 访问量:204

问:

我正在尝试使用 foldr 和 helper 函数将所有最大的整数从一个列表提取到另一个列表。我对折叠器的理解与错误消息相冲突。这是我的代码:

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[]largestHelperlargest 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
  |

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

我将非常希望澄清这种混淆。我还不知道这是否可行,因为它不会编译,并且作为函数式编程和 Haskell 的初学者,考虑到代码的逻辑和风格,我也希望发表评论。

Haskell 类型错误 折叠

评论


答:

6赞 Joseph Sible-Reinstate Monica 7/5/2021 #1

您的两个类型错误遵循模式和 。问题是你对 的参数顺序错误。 调用其函数时,首先使用元素,然后使用累加器,但希望先使用累加器,然后使用元素。切换它们的顺序,您的类型错误将得到修复。Couldn't match type `foo' with `bar'Couldn't match type `bar' with `foo'largestHelperfoldrlargestHelper

2赞 Micha Wiedenmann 7/6/2021 #2

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

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

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

* 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

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

请注意,编译器之所以能够识别问题,是因为您的编程语言使用类型。也就是说,类型赋予了它发现代码有问题的能力。因此,编译器可能认为自己是你的好伙伴,而实际上它面对的是你最奇怪和最复杂的技术术语。由您来解决问题。