media :: (Num a) => [a] -> a
media [] = 0
media lst = (head lst) + media (tail lst)
这是一个工作函数,它遍历一个数字列表,并使用以下元素对每个元素求和。
media2 :: (Num a) => [a] -> a
media2 str = (media str) / (length str)
第二个函数应该得到该总和并将其除以列表的长度,从而获得列表的算术平均值。但编译器会将此返回
src/Main.hs@6:29-6:39Could not deduce (a ~ Int)
from the context (Num a)
bound by the type signature for media2 :: Num a => [a] -> a
at /home/app/isolation-runner-work/projects/32614/src.207/Main.hs:6:1-39
`a' is a rigid type variable bound by
the type signature for media2 :: Num a => [a] -> a
at /home/app/isolation-runner-work/projects/32614/src.207/Main.hs:6:1
In the return type of a call of `length'
In the second argument of `(/)', namely `(length str)'
In the expression: (media str) / (length str)
我不明白我做错了什么,有人可以告诉我吗?
答案 0 :(得分:4)
length
函数始终返回Int
,因此您尝试将(Num a) => a
除以Int
。 fromIntegral
函数会将Int
转换为任何Num
类型:
media2 :: (Fractional a) => [a] -> a
media2 str = (media str) / (fromIntegral $ length str)
修改强>
关于一些富有洞察力的评论只是几句话:
media
功能只是Prelude的sum
。我假设您并不总是想要Integral
平均值,因此我已将media2
上的约束更改为Fractional
而不是Num
}。这是因为/
的类型为(/) :: (Fractional a) => a -> a -> a
。或者,您可以使用
media2 :: (Integral a) => [a] -> a
media2 str = (media str) `div` (fromIntegral $ length str)
但你总会得到一个整数平均值,这可能不是你想要的。
答案 1 :(得分:2)
您可以使用Data.List
中的genericLength
:
genericLength函数是length的重载版本。特别是,它不返回Int,而是返回任何Num实例的类型。然而,它的效率低于长度。
它的类型签名是
genericLength :: Num i => [a] -> i
用法:
import Data.List
media2 :: (Num a) => [a] -> a
media2 str = (media str) / (genericLength str)