没有因使用“sum”而产生的(Num a)实例 - Instance Num

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

这个函数工作正常:

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)

但是如果我想从函数中更改类型签名,它不起作用:

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)

这不应该也行吗?

差不多,但不完全是。基本问题是 length 的类型是 [a]->Int。这将起作用:

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)

正如 Oleg Grenrus 指出的那样,应该始终小心检查 Int 是否会溢出。事实上,如果 Int 是 30、31 或 32 位,则有可能发生这种情况,尽管这种情况相对不太可能发生。但是,如果这是一个问题,有一种方法可以解决它,使用另一个函数:

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.

您可以使用 GHC 扩展更轻松地查看 fromDigitsf 的类型如何匹配。通过添加

启用扩展
{-# LANGUAGE ScopedTypeVariables #-}

到源文件的最顶部。然后你可以写

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)

这样一来,列表参数的类型就很清楚了。

问题是您正在使用其他需要更多类型 a 的函数,而不仅仅是 Num a

(^) requires "Integral a"

这个有效

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)