Reputation: 15
I just started learning Haskell, and I intended to code a function that would return to last list 2.
lastButOne x = if ((==) (length x) 2)
then (head x)
else (tail x)
this is error:
‧ 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)
| ^^^^^^
I do not understand where my code is wrong and what the error meant.
Upvotes: 1
Views: 52
Reputation: 532063
lastButOne
has intended type [a] -> a
, but with tail x
you are trying to return a value of type [a]
. The error message results from the type checker's attempt to find a type which unifies with both a
and [a]
, in an attempt to make sense of a function that returns one or the other depending on which branch is taken.
What you want to do is recurse on the tail of the list:
lastButOne x = if length x == 2
then head x
else lastButOne (tail x)
This is more naturally written using pattern matching, though.
lastButOne [x,_] = x -- lists of length exactly 2
lastButOne (_:xs) = lastButOne xs -- All other non-empty lists
Note lastButOne
simply is not defined for empty or singleton lists, and will produce a run-time error if called on such. You can fix that by altering the return to Maybe a
:
lastButOne :: [a] -> Maybe a
lastButOne [x,_] = Just x
lastButOne (_:xs) = lastButOne xs
lastButOne _ = Nothing
Upvotes: 4