我刚刚开始学习Haskell,我打算编写一个返回到最后一个列表2的函数。
lastButOne x = if ((==) (length x) 2)
then (head x)
else (tail x)
这是错误:
‧ 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)
| ^^^^^^
我不明白我的代码在哪里以及错误的含义。
答案 0 :(得分:5)
lastButOne
的预期类型为[a] -> a
,但是您尝试使用tail x
返回类型为[a]
的值。该错误消息是由于类型检查器试图找到一个与a
和[a]
统一的类型而产生的,该尝试试图使一个函数根据使用哪个分支返回一个或另一个返回
您要执行的操作是列表末尾的递归:
lastButOne x = if length x == 2
then head x
else lastButOne (tail x)
不过,这自然是使用模式匹配编写的。
lastButOne [x,_] = x -- lists of length exactly 2
lastButOne (_:xs) = lastButOne xs -- All other non-empty lists
注意lastButOne
根本没有为空列表或单例列表定义,如果对此调用,则会产生运行时错误。您可以通过更改Maybe a
的返回值来解决此问题:
lastButOne :: [a] -> Maybe a
lastButOne [x,_] = Just x
lastButOne (_:xs) = lastButOne xs
lastButOne _ = Nothing