我无法弄清楚为什么这不起作用:
final' :: [a] -> a
final' lst = foldl(\accum x -> accum - accum + x) 0 lst
我总是得到错误没有使用'+'
引起的(Num a)实例答案 0 :(得分:6)
问题与功能本身无关,但是您自己附加签名:
final' :: [a] -> a
这里你基本上说你的final'
功能适用于任何 a
。所以我可以 - 如果我想 - 将String
加在一起,以及IO ()
个实例,或其他任何东西。但是现在Haskell会检查你的函数,并注意到你执行了一个加法(+) :: Num a => a -> a -> a
,并使用了类型为x
的右操作数a
。就像(+)
已经说明的签名一样,两个操作数都应该具有相同的类型,并且该类型应该是Num
的实例。
您可以通过使签名更具限制性来解决问题:
final' :: Num a => [a] -> a
final' lst = foldl(\accum x -> accum - accum + x) 0 lst
事实上,我们也可以概括部分签名,让它适用于任何Foldable
:
final' :: (Num a, Foldable f) => f a -> a
final' lst = foldl(\accum x -> accum - accum + x) 0 lst
然而,我们可以摆脱accum
,因为从自身中减去一个数字,通常会导致零(除了舍入问题等):
final' :: (Num a, Foldable f) => f a -> a
final' = foldl (const id) 0
现在我们摆脱了(+)
(和(-)
),但仍然需要使用Num
。原因是您使用0
作为初始累加器,如果是空列表,我们将返回0
和0 :: Num n => n
。