2013-11-27 67 views
2

我正在写一个计算标准差的函数。无法与'Int'类型'float'匹配

代码:

stdDev :: [float]->float 
stdDev [] = 0.0 
stdDev list = sqrt (foldl (\x-> fromIntegral(x^2/length list)) 0 list - foldl (\x->fromIntegral(x/length list)^2) 0 list) 

编译时,它显示:

Couldn't match type `float' with `Int' 

我已经用fromIntegral投放。我不明白为什么它仍在抱怨。

回答

3

首先,类型必须以大写字母开头。如果他们不这样做,他们会解释为类型变量

stdDev :: [Float] -> Float 
stdDev [] = 0.0 

接下来,你并不需要所有这些fromIntegral在里面,你是不是有Integral类型的工作。如果我们使用where子句计算长度,我们也可以得到更高效的函数。不幸的是你不太使用foldl正确的,它需要两个参数的函数,你只能通过它的1.功能也有你的标准偏差功能有点过了,它应该看起来像

stdDev xs = sqrt $ (sum $ map (^2) xs)/l - (sum xs/l)^2 
    where l = fromIntegral $ length xs 

作为最后的改进,可以使这项工作对于实现Floating任何类型,其中包括FloatDouble是用一种类

stdDev :: Floating a => [a] -> a 
stdDev [] = 0 
stdDev xs = sqrt $ (sum $ map (^2) xs)/l - (sum xs/l)^2 
    where l = fromIntegral $ length xs 

因此,我们可以测试一下:

> stdDev [1, 1, 1] 
0.0 
> stdDev [2, 4, 4, 4, 5, 5, 7, 9] 
2.0 

所以它看起来像它的工作


如果你真的想使用折叠,你必须通过它的功能有两个参数。在使用一般的模式是

foldl (\acc x -> <expr>) <initial value> <list> 

对于总和,它是作为

foldl (\acc x -> acc + x) 0 xs 

简单但性能方面的原因,你应该实际使用foldr在这里,它可以减少到只需

foldr (+) 0 xs 

在你的情况下,你需要一个简单的总和,然后一个平方和,所以你可以做

mySum xs = foldr (+) 0 xs 
sumSqrs xs = foldr (\acc x -> acc + x^2) 0 xs 

所以,你可以在stdDev作为

stdDev xs = sqrt $ foldr (\acc x -> acc + x^2) 0 xs/l - (foldr (+) 0 xs/l)^2 
    where l = fromIntegral $ length xs 
+0

正如我告诉@大卫。我我强迫自己使用foldl ..我想我有两个paras,第一个是函数,第二个是0,这是累积值? –

+0

你传递给'foldl'的函数必须有两个参数,但是现在它们都只有一个:'x'。 –

+0

@NobWong看看我的编辑 – bheklilr

0

float应该大写:Float。任何以小写字母开头的类型签名都是Haskell中的一个类型变量。

此外,传递给foldl的函数必须带有两个参数。在这种情况下,我认为你想在列表中使用map函数,然后将所有结果项与sum相加,而不是foldl(对于标准偏差的天真执行)。

您可能还需要寻找到genericLengthData.List,其评价为可以用作Num型类的任何实例的值(包括Float)。

+0

我学习更高阶的功能使用这些所以只是尽力实现它不和,虽然它是非常容易使用和 –

相关问题