简体   繁体   中英

Haskell, Even though my type is not specified I get this error: Couldn't match type `a' with `[a]', `a' is a rigid type variable bound by

So I realize this is a possible duplicate question, as there a number of those errors reported on Stack Overflow, but none of the solutions seem to apply to my problem.

So I have the following function:

elementAt' :: Integral b => [a] -> b -> a
elementAt' [x:_] 1 = x
elementAt' [x:xs] y = elementAt' xs yminus1
    where yminus1 = y - 1

In case you're wondering it's problem 3 from 99 Haskell Problems . The goal of the function is to take as input a list and an index, and return the value at that index (starting at 1). I don't want a solution to the problem, if I did I could just look at the ones provided. But I'm getting an error I don't understand. I'm using eclipseFP, the eclipse plugin for haskell and it's underlining the "[x:_]" and "[x:xs]" portions of the function with the following error:

Couldn't match type `a' with `[a]'
`a' is a rigid type variable bound by
the type signature for elementAt' :: Integral b => [a] -> b -> a

In all the threads that discuss this error that I've looked at the problem usually occurs when someone tries to give an incorrect output to something which expects a certain type. For example, returning the length of something (which is of type Int) to what should be a "Num a" variable type.

But in my case I'm not even providing a type for variable a. It should be able to be ANYTHING, right? So why am I getting this error? If I understood why I was getting the error I could fix it, but I just don't understand.

Could someone please explain to me why I'm receiving this error?

Your help is much appreciated, thank you. -Asaf

Edit: Every answer provided so far is correct, thank you all for the helpful information. I'm going to pick the one I believe to be most clear (I have to wait 5 minutes to do it though).

Entering your definition without type declaration shows that the inferred type is Integral b => [[a]] -> b -> a . That's correct, your current patterns match lists of lists.

A pattern like

f [pat] = ...

matches a singleton list whose sole element matches pat . You want to work with cons aka (:) instead of requring a certain length, and then you need parenthesis instead of brackets:

elementAt' (x:xs) n = ...

The error basically says "you treat a (the elements of the first argument) as if it was a list".

If you want to matching list to head and tail, you should use

elementAt' (x:_) 1 = x

So, finally

elementAt' :: Integral b => [a] -> b -> a
elementAt' (x:_) 1 = x
elementAt' (x:xs) y = elementAt' xs yminus1
    where yminus1 = y - 1

And

λ> elementAt' [1,2,3] 2
2

Is it what you need?

But in my case I'm not even providing a type for variable a. It should be able to be ANYTHING, right?

It has to be able to be anything. According to your type signature the user of your function has to be able to call your function with a being Int , with a being [Char] or with `a´ being whatever else the user wants to.

However the error message is telling you that you defined your function so that it's only possible to call it with a being a list of something. Ie you defined it, so that the first argument has to be a list of lists - it can't be a list of anything else. And that contradicts your type signature.

Use parentheses, not brackets: (x:xs)

module Aaa where

elementAt' (x:_) 1 = x
elementAt' (x:xs) y = elementAt' xs yminus1
    where yminus1 = y - 1

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM