Haskell的类型关联链令人费解
问题描述:
我正在玩一些Haskell代码。我定义了两个函数: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。我究竟做错了什么?
感谢, 阿尔弗雷多
答
首先,listMean :: [a] -> Double
说listMean
是采取任何类型a
的列表,以一个单一的Double
值的函数。
但是你依靠的是能够申请(+)
到列表(foldl1 (+)
),这需要该类型a
是Num
一个实例,这意味着你必须至少的元素:
listMean :: (Num a) => [a] -> b
你也可以将(/)
应用于由foldl1
操作产生的a
类型的值。为此,a
不仅必须是Num
的实例,而且还应该是Fractional
的实例。运用这一要求的类型a
给出了类型签名:
listMean :: (Fractional a) => [a] -> b
现在,b
什么?那么,(/)
的签名是(/) :: (Fractional a) => a -> a -> a
。所以,listMean
的结果也必须是Fractional
的一个实例。此外,它必须是Fractional
为包含在列表中的同一个实例:类型b
因此,事实上,a
型和listMean
最一般的签名是:
listMean :: (Fractional a) => [a] -> a
这正是编译器推断。如果你想专注本作Double
,你将不得不与Double
更换两个出现a
:
listMean :: [Double] -> Double
这是因为你在那里有没有运营商,这将迫使的Fractional
任何实例为Double
,所以输入和输出到(/)
必须是Double
类型。
+1,非常好的解释。 – 2010-11-02 19:11:33
完美!非常感谢你! – 2010-11-02 19:19:28