我正在尝试学习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可以得到满分,但我有一种隐隐约约的感觉,有一种方法可以使它同时适用于Integral和Fractional数组)