我的函数返回的最后一个列表有错误

ADW*_*ADW 2 haskell

我刚刚开始学习Haskell,我打算编写一个返回到最后一个列表2的函数。

lastButOne x = if ((==) (length x) 2)
               then (head x)
               else (tail x)
Run Code Online (Sandbox Code Playgroud)

这是错误的:

    ? Occurs check: cannot construct the infinite type: a ~ [a]
    ? In the expression: (tail x)
      In the expression:
        if ((==) (length x) 2) then (head x) else (tail x)
      In an equation for ‘lastButOne’:
          lastButOne x = if ((==) (length x) 2) then (head x) else (tail x)
    ? Relevant bindings include
        x :: [a] (bound at D:\\tool\8.6.3\test\lBoErr.hs:1:12)
        lastButOne :: [a] -> a (bound at D:\\tool\8.6.3\test\lBoErr.hs:1:1)

  |
3 |                            else (tail x)
  |                                  ^^^^^^
Run Code Online (Sandbox Code Playgroud)

我不明白我的代码在哪里以及错误的含义。

che*_*ner 5

lastButOne具有预期的类型[a] -> a,但与tail x您试图返回一个类型的值[a]。该错误消息是由于类型检查器试图找到一个与aand 统一的类型而产生的[a],该尝试试图使一个函数根据使用哪个分支返回一个或另一个返回。

您要做的是递归到列表的尾部:

lastButOne x = if length x == 2
               then head x
               else lastButOne (tail x)
Run Code Online (Sandbox Code Playgroud)

不过,这自然是使用模式匹配编写的。

lastButOne [x,_] = x  -- lists of length exactly 2
lastButOne (_:xs) = lastButOne xs -- All other non-empty lists
Run Code Online (Sandbox Code Playgroud)

注意lastButOne根本没有为空列表或单例列表定义,如果在此类上调用,则会产生运行时错误。您可以通过将return更改为来解决此问题Maybe a

lastButOne :: [a] -> Maybe a
lastButOne [x,_] = Just x
lastButOne (_:xs) = lastButOne xs
lastButOne _ = Nothing
Run Code Online (Sandbox Code Playgroud)