为什么这个Haskell函数被推断为这种类型?

时间:2017-07-06 17:58:49

标签: haskell

我是一名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的解决方案更好,但作为一种练习,我认为我提出的解决方案只使用了本书目前介绍的概念。

1 个答案:

答案 0 :(得分:2)

问题出在以下几行:

        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."