hdizzle
hdizzle

Reputation: 107

No instance for (Num a) arising from a use of ‘+’ Haskell

I can't figure out why this won't work:

final' :: [a] -> a
final' lst = foldl(\accum x -> accum - accum + x) 0 lst

I always get the error No instance for (Num a) arising from a use of ‘+’

Upvotes: 3

Views: 3978

Answers (1)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 476729

The problem has nothing to do with the function itself, but with the signature you attach to it yourself:

final' :: [a] -> a

Here you basically say that your final' function will work for any a. So I could - if I wanted - add Strings together, as well as IO () instances, or anything else. But now Haskell inspects your function, and notices that you perform an addition (+) :: Num a => a -> a -> a, with as right operand x, which has type a. Like the signature for (+) already says, both operands should have the same type, and that type should be an instance of Num.

You can solve the problem by making the signature more restrictive:

final' :: Num a => [a] -> a
final' lst = foldl(\accum x -> accum - accum + x) 0 lst

In fact we can also generalize a part of the signature, and let it work for any Foldable:

final' :: (Num a, Foldable f) => f a -> a
final' lst = foldl(\accum x -> accum - accum + x) 0 lst

We can however get rid of the accum, since subtracting a number from itself, will usually result in zero (except for rounding issues, etc.):

final' :: (Num a, Foldable f) => f a -> a
final' = foldl (const id) 0

Now we got rid of (+) (and (-)), but still need to use Num. The reason is that you use 0 as initial accumulator, and in case of an empty list, we thus will return 0, and 0 :: Num n => n.

Upvotes: 6

Related Questions