没有因使用“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 扩展更轻松地查看 fromDigits
和 f
的类型如何匹配。通过添加
启用扩展
{-# 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)
这个函数工作正常:
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 扩展更轻松地查看 fromDigits
和 f
的类型如何匹配。通过添加
{-# 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)