I was able to execute the following code flawlessly
myLast :: [a] -> a
myLast [] = error "Can't call myLast on an empty list!"
myLast (x:_) = x
but I'm getting this error Couldn't match expected type `a' with actual type `[a]'. `a' is a rigid type variable bound by the type signature for myLast :: [a] -> a
for the following code:
myLast :: [a] -> a
myLast [] = error "Can't call myLast on an empty list!"
myLast (_:x) = x
I'm a beginner in Haskell and the error message is too greek and latin for me. From what I can understand, the compiler is not able infer the type in the second case. Can someone point me to what is actually happening here?
You're declaring the input to be a list of type [a]
, and the rest to be of type a
.
A list of type [a]
in Haskell consists of a head of type a
and a tail, a list of type [a]
. The cons constructor :
takes the head and tail as its arguments.
When you deconstruct a list as (x:y)
, x
is the head and y
is the tail. So in your second code fragment, you're binding the tail of the list, which has the list type [a]
, when your type signature requires that you return a value of type a
(the head being one example).
Having an understanding of what :
really is will help decrypt the error message. :
can be thought of as a function which takes an element and a list, and returns a list that whose first element is the first argument and the rest of it is the second argument, or:
(:) :: a -> [a] -> [a]
Getting to your function, you wrote myLast :: [a] -> a
; however, the type of myLast (_:x) = x
is myLast :: [a] -> [a]
since the second argument of :
(which you named x
) is itself a list.
Additionally, in general when you don't understand something in Haskell, you should take a look at it's type first using :t
in GHCI.
(_:x)
matches _ with the head and x with the tail of the list. The type of tail of a list is [a]. You are trying to return [a]' where as the function declaration specifies return type as a.
myLast (_:x) = x
If you want to match last element take a look at this answer - Can you use pattern matching to bind the last element of a list?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With