Haskell 哈斯克尔';s型关联链令人费解

Haskell 哈斯克尔';s型关联链令人费解,haskell,types,Haskell,Types,我在玩一些Haskell代码。我定义了两个函数: count :: [a] -> Int count [] = 0 count (x:xs) = 1 + (count xs) -- 03. Write a function that computes the mean of a list, i.e., the sum of all -- elements in the list divided by its length. (You may need to use the -

我在玩一些Haskell代码。我定义了两个函数:

count :: [a] -> Int
count []     = 0
count (x:xs) = 1 + (count xs)

-- 03. Write a function that computes the mean of a list, i.e., the sum of all 
-- elements in the list divided by its length. (You may need to use the 
-- fromIntegralfunction to convert the length of the list from an integer 
-- into a floating-point number.)

-- I've guessed this type definition, but it's incorrect:
-- listMean :: [a] -> Double
-- The following is the same inferred by hgci
listMean :: (Fractional a) => [a] -> a
listMean lst = (foldl1 (+) lst)/(fromIntegral (count lst))
为什么[a]->Double不正确?似乎我给出了lst,它是某种类型a的泛型列表,listMean返回一个Double。我做错了什么

谢谢,
Alfredo

首先,
listMean::[a]->Double
表示
listMean
是一个函数,它将任何类型的
a
列表转换为一个
Double

但是您需要能够将
(+)
应用于列表的元素(
foldl1(+)
),这要求类型
a
Num
的实例,这意味着您至少有:

listMean :: (Num a) => [a] -> b
您还可以将
(/)
应用于
foldl1
操作产生的
a
类型的值。为此,
a
不仅必须是
Num
的实例,而且必须是
fractive
的实例。将此要求应用于类型
a
会给出类型签名:

listMean :: (Fractional a) => [a] -> b
现在,关于
b
?嗯,
(/)
的签名是
(/)::(分数a)=>a->a->a
。因此,
listMean
的结果也必须是
分数的一个实例。此外,它必须与列表中包含的
分数
的实例相同:因此,类型
b
实际上是类型
a
,而
listMean
最常用的签名是:

listMean :: (Fractional a) => [a] -> a
这正是编译器推断的结果。如果您想专门针对
Double
,则必须用
Double
替换出现的
a

listMean :: [Double] -> Double

这是因为这里没有将
分数
的任何实例强制为
双精度
,所以
(/)
的输入和输出必须是
双精度

完美!!非常感谢你!