Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Couldn't match expected type `a' with actual type `[a]'

Tags:

haskell

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?

like image 581
BobLoblaw Avatar asked Jun 03 '13 00:06

BobLoblaw


3 Answers

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

like image 171
Jeremy Roman Avatar answered Nov 16 '22 03:11

Jeremy Roman


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.

like image 28
user2407038 Avatar answered Nov 16 '22 01:11

user2407038


(_: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?

like image 35
gkamal Avatar answered Nov 16 '22 01:11

gkamal