2017-09-24 114 views
0

我想寫一個方程來找到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和分子的錯誤。

對於前者,我給出的錯誤

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

該代碼在一些地方是錯誤的,因此類型推斷試圖分配錯誤的類型。嘗試爲_all_函數添加一個類型註釋,並且類型錯誤將變得更加清晰。現在,「分子」必須是一個列表列表,這是錯誤的,例如。 – chi

+0

如何定義'listSum'? –

回答

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