无法将类型`float'与`Int'匹配

时间:2013-11-27 19:47:41

标签: haskell

我正在编写一个计算标准偏差的函数。

代码:

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投了它。我不明白为什么它还在抱怨它。

2 个答案:

答案 0 :(得分: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

答案 1 :(得分:0)

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

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

您可能还希望从genericLength查看Data.List,该Num评估的值可以用作Float类型类的任何实例(包括{{1}})