tags:

views:

149

answers:

2

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

+8  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 a. Integer and Double fall into this category.

Correspondingly, 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.

luqui
Can I make `[a]` a member of `Num`, is it possible, if yes, can you provide a simple example? If no, why not?
Evan Carroll
Yes you could. For instance if you wanted to provide polynomials, but it'd be a bad idea in general.instance Num a => Num [a] where fromIntegral a = [a] (a:as) + (b:bs) = (a + b):(as + bs) [] + bs = bs as + [] = as ...
Edward Kmett
Technically, you can make anything an instance of any typeclass (provided kinds match) by doing something like `instance Num [a] where fromInteger x = undefined; x + y = undefined` etc. It obviously wouldn't be useful though.
John
+2  A: 

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
Shimuuar