Apparently, my type signature was off. I've since found out why. Now, I'm interested in knowing more about the GHCI inferred signature on my typo. I was trying to get this code to work:
elemNum :: (Eq a, Num b) => a -> [a] -> b
elemNum e l = f e l
where f _  =  -- this was my typo, supposed to read 0
f e (x:xs)
| x == e = 1 + f e xs
| otherwise = f e xs
It obviously doesn't work for the reason noted above; but, if I remove my signature it compiles (not sure why, please explain), and I get this signature:
elemNum :: (Num [a], Eq t) => t -> [t] -> [a]
I've never seen the typeclass
Num [a] before.. What does that mean, and how does it compare to
(Num a) => [a].
Num a means that the type
a can be treated as a number; eg. you can add two
as together to get a new
a or you can negate an
a and get an
Double fall into this category.
Num [a] means that the type
[a] can be treated as a number. I.e. you can add together two lists of
a to get a new list of
a. This is very unlikely to be meaningful because no lists are numbers (by default). It means that you are treating a list like it is a number, causing GHC to conclude that you must want your list to act like a number, and thus adding an appropriate constraint.
Such a constraint might arise from a function like:
foo (x:xs) = xs + 1
xs is pattern matched as the tail of a list, and thus is itself a list, and then you are adding to it, treating the list as a number.
Num [a] constraint means that list is instance of Num type class.
foo :: Num a => [a]
is list of values which are instances of Num type class
bar :: Num [a] => [a]
is list of values which is instance of Num type class by itself. This means that you can use all functions from Num and construct lists from numeric literals so following code is valid although requires FlexibleContexts
bar :: Num [a] => [a] bar = 42
P.S. You don't need helper function here. elemNum e l = f e l ⇒ elemNum = f. So you can write your function as
elemNum _  = 0 elemNum e (x:xs) | x == e = 1 + f e xs | otherwise = f e xs