Haskell 哈斯克尔';s型关联链令人费解
我在玩一些Haskell代码。我定义了两个函数: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 -
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
这是因为这里没有将分数的任何实例强制为双精度,所以(/)
的输入和输出必须是双精度完美!!非常感谢你!