Haskell划分数量

Eva*_*oll 4 haskell types division typeclass

我有一个问题,我想了解更多,以及如何避免.我有这个代码

len :: (Num r ) => [a] -> r
len [] = 0
len xs = 1 + len ( tail xs )

avg :: (Num t) => [t] -> Double
avg xs = ( sum xs ) / ( len xs )
Run Code Online (Sandbox Code Playgroud)

这会导致以下错误

len.hs:6:9:
    Couldn't match expected type `Double' against inferred type `t'
      `t' is a rigid type variable bound by
          the type signature for `avg' at len.hs:5:12
    In the expression: (sum xs) / (len xs)
    In the definition of `avg': avg xs = (sum xs) / (len xs)

现在,我知道这个错误(感谢irc.freenode.net #haskell)是除法功能的结果

(/) :: (Fractional a) => a -> a -> a
Run Code Online (Sandbox Code Playgroud)

但是,我不知道该怎么办.我的avg函数签名应该与除法运算符怪异(需要Fractional类型类)无关.所以,我认为克服这个问题的正确方法是通过强制转换为类型,Fractional但我不知道如何,或者即使这是正确的?有任何想法吗?

Jos*_*Lee 7

我的avg函数签名应该与除法运算符的怪癖无关

这是为什么?如果你想计算一堆整数的平均值,你必须在某个时刻进行除法,所以你必须将它们从整数转换为你选择的除法支持类型.仔细查看Num类(:i Num在ghci中)可以发现以下类型的一个问题avg:Num没有足够的方法 - 基本上足以添加,乘法和减去.我无法保证我提供的号码avg可以转换为a Double.

如果输入无类型函数来计算平均值,Haskell会以最通用的类​​型响应:

Prelude List> :type \x -> sum x / genericLength x
\x -> sum x / genericLength x :: (Fractional a) => [a] -> a
Run Code Online (Sandbox Code Playgroud)

所以这是正确的类型avg.

您可能会注意到这avg [1,2,3 :: Integer]会产生类型错误.你可以通过将参数传递给toRational或者fromIntegral首先使用RealIntegral实例Integer分别来解决这个问题.


关于表达式sum [1,2,3] / len [1,2,3]:正确的是,一个字面数字1类型具有类型Num a => a,它调用fromInteger它所证明的任何类型,但是表达式1/2具有更具体的类型Fractional a => a,如果你要求它的类型,你可以看到表达而不是打印出来.

可能有用的东西是:set -Wallghci,它会在为您选择默认类型时打开大量警告,从而提供最通用类型可能不再正确的线索.

  • 所有这些声明都在序曲中.在线参考:http://www.haskell.org/ghc/docs/6.10.2/html/libraries/base/Prelude.html (2认同)

Don*_*art 5

你过分约束平均类型.使用更通用的版本,avg ::(小数a)=> [a] - > a