Reputation: 4417
I am a Haskell newbie, please forgive me for asking this which might be obvious, but I am surprised by this:
len2 :: [a] -> Int
len2 xx = if xx == [] then 0 else 1 + (len2 (tail xx))
gives me:
No instance for (Eq a) arising from a use of ‘==’
Possible fix:
add (Eq a) to the context of
the type signature for len2 :: [a] -> Int
In the expression: xx == []
I am surprised because I thought Haskell could tell whether a list was []
or not without looking at any element (in C++, I would see that the list has size 0 and leave it at that, for example).
Upvotes: 2
Views: 70
Reputation: 153182
The type of (==)
in this case is Eq a => [a] -> [a] -> Bool
. Hopefully you agree that before you see any arguments the Eq a
constraint makes sense: if you want to check two arbitrary lists are equal, you have to know how to check if elements are equal. You might wish that once you applied (==)
to the concrete argument []
that the Eq a
constraint wasn't needed, but this is actually quite a subtle thing to notice. Perhaps partial evaluation would be able to produce a function that didn't have the constraint. But extant implementations do not try to do this analysis; they keep the conservative type Eq a => [a] -> Bool
which has discharged an [a]
argument but not the Eq a
constraint.
Some options:
Use null :: [a] -> Bool
instead of (==[])
.
len2 xx = if null xx then ... else ...
Pattern match, thus:
len2 [] = ...
len2 (x:xs) = ...
As a bonus, this way you can avoid calling the nasty tail
function.
I would say choice (2) is significantly more idiomatic.
Upvotes: 9