【发布时间】: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) -
你应该尽量避免
head、tail。它们不是惯用的 Haskell,因为 1)如果您在空列表中使用它们,它们可能会使您的程序崩溃,并且 2)模式匹配也更易于使用和方便。
标签: haskell