Reputation: 11
I have just started writing my first few programs in Haskell and I'm struggling a lot - so please excuse errors galore. I found this practice problem online and it wants me to take in a list, an int, and return a bool. I should check if the int is to be found within the list or not and return true or false, respectively. This is what I have:
import Data.List
elem':: (Eq a) => a -> [a] -> Bool
elem' x [x]
| x == [x:xs] = True
| length [x] == 1 = False
| otherwise = elem' tail [x]
The compiler returns
Illegal type signature [...] Type signatures are only allowed in patterns with ScopedTypeVariables
which I cannot really make sense of yet. I've found some people saying that this error occurs when using tabs instead of spaces, yet I solely used spaces. I am grateful for any advice!
Upvotes: 0
Views: 976
Reputation: 120711
First you have a simple indentation problem. Your definition is parsed as
elem':: (Eq a) => a -> [a] -> Bool elem' x [x]
| x == [x:xs] = True
| length [x] == 1 = False
| otherwise = elem' tail [x]
I'm a bit surprised that this isn't reported as a parse error, but basically it is one.
What you need to do is, indent all function clauses to the same level as the signature (i.e. in this case, not indented at all).
elem':: (Eq a) => a -> [a] -> Bool
elem' x [x]
| x == [x:xs] = True
| length [x] == 1 = False
| otherwise = elem' tail [x]
This is still very wrong though. First, you're matching twice on x
. This is not possible in Haskell. OTOH there's no variable xs
in scope. If it were, it would have to have type [a]
, and then [x:xs]
would have type [[a]]
: a nested list. But then comparing it to x
, which is not even a simple list, doesn't make any sense. length [x]
is always 1, regardless of what x
is. Similarly, tail [x]
is always the empty list (but that's not even what's used here, you've actually wrote that the tail
function should be passed as an argument to elem'
).
Perhaps the confusion comes from the fact that [
]
can mean two different things: one the type level, it means you're talking about lists of elements of the enclosed type. I.e. [a]
is the type of lists whose elements have type a
.
By contrast, on the value level, [x]
is specifically the list that contains only a single element, namely x
.
You should make sure you understand how pattern matching works. Your clause would have been legal if you had two different variables in it. Then, matching [y]
would mean this clause only accepts lists with exactly one element, and y
will than be the value of the single element. In this case, the correct implementation would be
elem' x [y] = x==y
(Alternatively, you could have guards here yielding True
and False
, but that's just redundant work.)
Actually though there's no good reason to have a clause for exactly one element. All you need is a clause for zero elements
elem' x [] = ...
and a clause for at least one element:
elem' x (y:ys)
| ...
| ...
Upvotes: 3