在Haskell中将Num转换为Doublle



我正在尝试编写一个函数,用于计算包含类型Num.的列表的值的平均值

以下是我尝试过的:

mean :: Num a => [a] -> Double
mean [] = error "Trying to calculate mean of 0 values"
mean x = sumx / lengthx
where
sumx = fromIntegral (sum x)
lengthx = fromIntegral length x

GHCI拒绝fromIntegral函数,因为它需要Integral类型而不是Num.

有没有一种方法可以将Num(无论其具体类型如何(转换为Double?

Num a => a转换为Double的问题在于Num实际上可能根本不是一个数字。Num类的成员不需要是某种数字。您可以为任何东西实现Num的实例,甚至是单元。

一个明显的现实例子是Complex:它有一个Num的实例,但复数不能总是转换为实数。

如果希望函数使用整数,只需指定Integral作为约束即可。

好吧,我终于找到了这样做的方法:

mean :: Fractional a => [a] -> a
mean xs = sum xs / fromIntegral (length xs)

即使我将其应用于整数列表,这也有效。我不知道为什么,因为根据我阅读的文件,Fractional不适用于Integers。

显然,我对哈斯克尔的了解仍然很有限。

更通用的编写方法是使用Real:

mean :: (Real a, Fractional b) => [a] -> b
mean xs = realToFrac (sum xs) / fromIntegral (length xs)

但这并不完全令人满意,因为这对Complex或其他非Real数字的列表不起作用。

最新更新