我正在与初学者Haskell玩耍,我想编写一个平均函数。好像是世界上最简单的事情,对吧?
错误。
似乎Haskell的类型系统禁止平均值在通用数字类型上工作-我可以让它在整数列表或小数列表上工作,但不能同时在两者之间工作。
我想要:
average :: (Num a, Fractional b) => [a] -> b
average xs = ...
但是我只能得到:
averageInt :: (Integral a, Fractional b) => [a] -> b
averageInt xs = fromIntegral (sum xs) / fromIntegral (length xs)
要么
averageFrac :: (Fractional a) => [a] -> a
averageFrac xs = sum xs / fromIntegral (length xs)
第二个似乎可行。直到我尝试传递变量。
*Main> averageFrac [1,2,3]
2.0
*Main> let x = [1,2,3]
*Main> :t x
x :: [Integer]
*Main> averageFrac x
<interactive>:1:0:
No instance for (Fractional Integer)
arising from a use of `averageFrac ' at <interactive>:1:0-8
Possible fix: add an instance declaration for (Fractional Integer)
In the expression: average x
In the definition of `it': it = averageFrac x
显然,Haskell对它的类型确实很挑剔。那讲得通。但是当他们俩都可以成为[Num]时
我是否错过了RealFrac的明显应用程序?
有没有办法强制积分到分数输入时不会阻塞的分数?
有没有什么方法可以使用Either
和either
制作某种可以在任何数值数组上使用的多态平均函数?
Haskell的类型系统是否会彻底禁止该功能?
学习Haskell就像学习微积分。它真的很复杂,并且是基于大量理论,有时问题是如此令人难以置信,以至于我什至不知道如何正确地表达问题,因此任何见解都会被热烈接受。
(此外,脚注:这是基于作业问题。每个人都同意上面的averageFrac可以得到满分,但是我暗中怀疑是否有一种方法可以使它同时在整数和小数数组上工作)