我试图写一个等式来找出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很新。我能帮助你理解我做错了吗?
答案 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
方法,我们使用(/)
函数的两个参数从公共参数中提取sum
和realToFrac . length
的结果;一个列表。所以它会像;
sum ([1,2,3] :: [Float]) / (realToFrac . length $ [1,2,3])
和map
的第一个参数((^2) . (-) axs)
是一个逐个获取每个元素的函数,找到它与列表的平均值的差异并将其平方。那么......然后我们计算它们的平均值并取平方根。因此;
*Main> stdev [600, 470, 170, 430, 300]
147.32277