skills
skills

Reputation: 327

No instance for (Num a) arising from a use of `sum' - Instance Num

this function works fine:

fromDigits :: [Int] -> Int
fromDigits n = sum (zipWith (\x y -> x*y) (n) (f n 0))
            where
                f :: [Int] -> Int -> [Int]
                f n x = if (x==length n) then []
                                         else (10^x):f n (x+1)

But if i want to change the type signature from the function, it does not work:

fromDigits :: (Num a) => [a] -> a
fromDigits n = sum (zipWith (\x y -> x*y) (n) (f n 0))
            where
                f :: (Num a) => [a] -> a -> [a]
                f n x = if (x==length n) then []
                                         else (10^x):f n (x+1)

Shouldn't this work too?

Upvotes: 1

Views: 2801

Answers (2)

dfeuer
dfeuer

Reputation: 48591

Almost, but not quite. The basic problem is that length has type [a]->Int. This will work:

fromDigits :: Num a => [a] -> a
fromDigits n = sum (zipWith (\x y -> x*y) (n) (f n 0))
  where
    f :: Num b => [b] -> Int -> [b]
    f n x = if (x==length n) then []
                             else (10^x):f n (x+1)

As Oleg Grenrus points out, one should always be careful to check if Int might overflow. It is in fact possible for this to happen if Int is 30, 31, or 32 bits, although it is relatively unlikely. However, if that is a concern, there is a way around it, using another function:

lengthIsExactly :: Integral n => n -> [a] -> Bool
lengthIsExactly = -- I'll let you figure this one out.
                  -- Remember: you can't use `length` here,
                  -- and `genericLength` is horribly inefficient,
                  -- and there's a completely different way.

You can make it easier to see how the types of fromDigits and f match up using a GHC extension. Enable the extension by adding

{-# LANGUAGE ScopedTypeVariables #-}

to the very top of your source file. Then you can write

fromDigits :: forall a . Num a => [a] -> a
fromDigits n = sum (zipWith (\x y -> x*y) (n) (f n 0))
  where
    f :: [a] -> Int -> [a]
    f n x = if (x==length n) then []
                             else (10^x):f n (x+1)

This way, it's clear that the list arguments all have the same type.

Upvotes: 2

jamshidh
jamshidh

Reputation: 12070

The problem is that you are using other functions that require even more of type a than just Num a

(^) requires "Integral a"

This works

fromDigits' :: (Num a, Integral a)=>[a] -> a
fromDigits' n = sum (zipWith (\x y -> x*y) (n) (f n 0))
        where
            f :: (Num a, Integral a)=>[a] -> a -> [a]
            f n x = if (x==fromIntegral (length n)) then []
                                     else (10^x):f n (x+1)

Upvotes: 2

Related Questions