[英]Haskell's type associative chain is puzzling
I'm playing with some Haskell code. 我正在玩一些Haskell代码。 I've defined two functions:
我已经定义了两个函数:
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))
Why [a] -> Double is not correct? 为什么[a] - > Double不正确? It seems that I give lst that is a generic list of some type a and listMean returns a Double.
看来我给lst是一个类型a的通用列表,listMean返回一个Double。 What am I doing wrong?
我究竟做错了什么?
Thanks, Alfredo 谢谢,阿尔弗雷多
First of all, listMean :: [a] -> Double
says that listMean
is a function taking a list of any type a
to a single Double
value. 首先,
listMean :: [a] -> Double
表示listMean
是一个函数, listMean
任何类型a
的列表转换为单个Double
值。
But you rely on being able to apply (+)
to the elements of the list ( foldl1 (+)
), which requires that the type a
be an instance of Num
, which means you have at least: 但是你依赖于能够将
(+)
应用于列表的元素( foldl1 (+)
),这要求类型a
是Num
的实例,这意味着你至少有:
listMean :: (Num a) => [a] -> b
You also apply (/)
to the value of type a
that results from the foldl1
operation. 您还可以将
(/)
应用于由foldl1
操作产生的类型a
的值。 To do so, a
must not only be an instance of Num
, but of Fractional
. 要做到这一点,
a
不仅必须的一个实例Num
,但Fractional
。 Applying this requirement to the type a
gives the type signature: 将此要求应用于类型
a
会给出类型签名:
listMean :: (Fractional a) => [a] -> b
Now, what of b
? 现在,
b
什么? Well, the signature for (/)
is (/) :: (Fractional a) => a -> a -> a
. 那么,
(/)
的签名是(/) :: (Fractional a) => a -> a -> a
。 So, the result of listMean
must also be an instance of Fractional
. 因此,
listMean
的结果也必须是Fractional
一个实例。 Further, it must be the same instance of Fractional
as that contained in the list: type b
is thus, in fact, type a
, and listMean
's most general signature is: 此外,它必须与列表中包含的
Fractional
实例相同:因此,类型b
实际上是类型a
,而listMean
的最常见签名是:
listMean :: (Fractional a) => [a] -> a
This is exactly what the compiler inferred. 这正是编译器所推断的。 If you want to specialize this for
Double
, you would have to replace both occurrences of a
with Double
: 如果你想为
Double
专门化这个,你必须用Double
替换两个出现的a
:
listMean :: [Double] -> Double
This is because you have no operator in there that will coerce any instance of Fractional
into a Double
, so both input and output to (/)
must be of type Double
. 这是因为你没有操作符将
Fractional
任何实例强制转换为Double
,因此(/)
输入和输出必须是Double
类型。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.