【问题标题】:Why is this Haskell function inferred to this type?为什么将此 Haskell 函数推断为这种类型?
【发布时间】:2017-07-06 17:58:48
【问题描述】:

我是一名 Haskell 初学者,正在完成 Real World Haskell 第 2 章中的一个练习,您在其中编写了一个返回列表倒数第二个元素的函数。

我编写了以下函数来尝试解决这个问题:

-- file: \Learn Haskell\lastButOne.hs
lastButOne xs = if length xs == 2
                then head xs
                else lastButOne tail xs

我不明白的是编译器抛出的这个错误:

lastButOne.hs:2:1: error:
    • Couldn't match type ‘[a] -> [a]’ with ‘[t]’
      Expected type: ([a] -> [a]) -> [t] -> t
        Actual type: [t] -> t
    • Relevant bindings include
        lastButOne :: ([a] -> [a]) -> [t] -> t (bound at lastButOne.hs:2:1)

据我了解,ghci 认为我的函数应该具有与它不同的类型,但我不明白为什么会发生这种情况,或者我该如何解决它。

编辑:感谢您的回答!我已将代码更新为:

-- file: \Learn Haskell\lastButOne.hs
lastButOne xs = if length xs == 2
                then head xs
                else if length xs < 2
                     then error "This list does not have a second-to-last element."
                     else lastButOne (tail xs)

这消除了 tail xs 被解释为两个参数而不是单个表达式的错误。我还添加了一些代码来确保列表不会太短。 Willem Van Onsem 的解决方案更好,但作为练习,我想我会想出一个仅使用本书迄今为止介绍的概念的解决方案。

【问题讨论】:

  • lastButOne tail xs(lastButOne tail) xs,而不是 lastButOne (tail xs)
  • 你应该尽量避免headtail。它们不是惯用的 Haskell,因为 1)如果您在空列表中使用它们,它们可能会使您的程序崩溃,并且 2)模式匹配也更易于使用和方便。

标签: haskell


【解决方案1】:

问题出在这行:

        else lastButOne tail xs

应该是:

        else lastButOne (tail xs)

否则 ghci 你给 lastButOne 两个参数:tailxs

但是,您可以使代码更优雅:

lastButOne [x,_] = x
lastButOne xs = lastButOne $ tail xs

此外,您必须找到一种方法来用一个元素和空列表解析列表。现在该函数将开始循环。一个想法可能是在这些列表上出错,例如:

lastButOne [x,_] = x
lastButOne (_:xs) = lastButOne xs
lastButOne [] = error "The list has no last but one element."

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多