我正在玩一些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] - >双重不正确?看来我给lst是一个类型a的通用列表,listMean返回一个Double。我做错了什么?
谢谢, 阿尔弗雷
答案 0 :(得分:20)
首先,listMean :: [a] -> Double
表示listMean
是一个将任意类型a
的列表添加到单个Double
值的函数。
但您依赖于能够将(+)
应用于列表(foldl1 (+)
)的元素,这要求类型a
是Num
的实例,这意味着你至少有:
listMean :: (Num a) => [a] -> b
您还将(/)
应用于a
操作产生的foldl1
类型的值。为此,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
专门设置此项,则必须将 a
的两个替换为Double
:
listMean :: [Double] -> Double
这是因为你没有任何操作符会将Fractional
的任何实例强制转换为Double
,因此(/)
的输入和输出都必须是Double
类型}。