计算Haskell中的标准偏差

时间:2017-09-24 22:17:09

标签: haskell

我试图写一个等式来找出Haskell中整数列表的标准偏差,并且在我的大脑被震了一个小时之后,我想我已经弄明白了如何写出这个等式。虽然它给了我错误,但我不确定我做错了什么。

listLength :: (Num a) => [a] -> a
listLength [] = 0
listLength (x:xs) = 1 + listLength xs

listMeanInt x = listSum x `div` listLength x

listStdDev x = sqrt(numerator x `div` denominator x)
denominator x = (listLength x) - 1
numerator (x:xs) = if (x /= []) then ((x - listMeanInt x)^2) + (numerator xs) else 0

函数listLength和listMeanInt用于我程序的其他部分,所以我确信它们不是问题所在。当我尝试加载模块时,我得到listStdDev和numerator的错误。

对于前者,我给出了错误

Non type-variable argument in the constraint: Integral [a]
When checking the inferred type
    listStdDev :: forall a. (Integral [a], Floating [a]) => [[a]] -> [a].

我不确定那是什么意思?也许即使我使用div,分母也应该是浮动的?我对此感到困惑,并希望在我点火之前做一些澄清。

至于后者,我被告知

Occurs check: cannot construct the infinite type: a ~ [a]
In the second argument of ‘(-)’, namely ‘listMeanInt x’,
In the first argument of ‘(^)’, namely ‘(x - listMeanInt x)’,
In the first argument of ‘(+)’, namely ‘((x - listMeanInt x) ^ 2)’.
Relevant bindings include xs :: [[a]], x :: [a], numerator :: [[a]] -> [a].

我完全不知道如何解释这一点;我对Haskell很新。我能帮助你理解我做错了吗?

1 个答案:

答案 0 :(得分:0)

我猜您可以按如下方式计算标准偏差;

stdev :: [Float] -> Float
stdev xs = sqrt . average . map ((^2) . (-) axs) $ xs
           where average = (/) <$> sum <*> realToFrac . length
                 axs     = average xs

最好将我们的列表定义为Float类型。这使我们免于一些转换。

average功能; (/) <$> sum <*> realToFrac . length实际上是一种Applicative方法,我们使用(/)函数的两个参数从公共参数中提取sumrealToFrac . length的结果;一个列表。所以它会像;

sum ([1,2,3] :: [Float]) / (realToFrac . length $ [1,2,3])

map的第一个参数((^2) . (-) axs)是一个逐个获取每个元素的函数,找到它与列表的平均值的差异并将其平方。那么......然后我们计算它们的平均值并取平方根。因此;

*Main> stdev [600, 470, 170, 430, 300]
147.32277