Haskell fromIntegral-类型混淆 [英] Haskell fromIntegral -- type confusion
问题描述
我正在经历真实世界Haskell",并且正在做随之而来的练习.
I am just going through "Real World Haskell" and I am doing the excercises that come along with it.
我注意到我认为很奇怪的东西.
And i noticed something that i think is odd.
以该功能为例:
myAverage :: (Fractional a) => [a] -> Maybe a
myAverage [] = Nothing
myAverage xs = Just $ (mySum xs) / (fromIntegral $ myLength xs)
myAverage :: (Fractional a) => [a] -> Maybe a
myAverage [] = Nothing
myAverage xs = Just $ (mySum xs) / (fromIntegral $ myLength xs)
(/)
函数需要两个参数,它们是Fractional
的实例.
myLength
返回一个Int
,所以我按我所告诉的那样使用the fromIntegral
函数.
The (/)
function wants two arguments that are instances of Fractional
.
myLength
returns an Int
so i use the fromIntegral
function as i have been told.
但是fromIntegral
仅保证返回的值将是Num
的实例.
But fromIntegral
only garantees that the returned value will be an instance of Num
.
在这种情况下,为什么Num
也包含" Fractional
的实例. Fractional
是否更具体?
Why does Num
also "include" an instance of Fractional
in this case. Isn't Fractional
more specific?
为什么编译器不会抱怨我返回类型中只有一个Num
而不是适当的" Fractional
.
Why doesn't the compiler complain that i have just a Num
from the return type and not a "proper" Fractional
.
为什么我不能直接使用Int
,它也是Num
的实例,不是吗?
Why can't i use the Int
directly, it is also an instance of Num
, is it not?
在调用mySum
的情况下,我明白了.它需要一个Num
的列表,但是我要给它一个Fractional
的列表(它们也是Num
的列表,因为它们是从中派生的).返回类型具有相同的类型,这可以从类型注释中看出(请参见下文):Fractional
In the case of calling mySum
i get it. It takes a list of Num
s but i feed it with a list of Fractional
s (which are also Num
s, because they are derived from it). The return type has the same type, which is evident from the type annotation (see below): a single element of Fractional
但是在fromIntegral
的情况下,我无法推断自己(编译器显然可以:-)),返回的值也是Fractional
的实例.为什么?
显然,它所采用的类型不是Fractional
.
But in case of fromIntegral
i cannot infer myself (the compiler obviously can :-)) that the returned value is also an instance of Fractional
. Why?
The type it takes is clearly no Fractional
.
整个功能按预期工作.
仅作说明:
mySum :: (Num a) => [a] -> a
myLength :: [a] -> Int
mySum :: (Num a) => [a] -> a
myLength :: [a] -> Int
谢谢
拉撒路
推荐答案
fromIntegral
不会产生某些未知类型,我们仅知道它是Num
的实例.只要它是Num
的实例,fromIntegral
就会产生我们(通常是隐式)要求的任何类型.
fromIntegral
doesn't produce some unknown type of which we only know that it's an instance of Num
. fromIntegral
produces whichever type we (usually implicitly) ask it to, as long as its an instance of Num
.
就OO语言而言,您需要将其视为泛型/模板,而不是虚拟继承/子类型多态.这就是fromIntegral
的等效Java签名,看起来像<A extends Integral, B extends Num> B fromIntegral(A i)
,而不是Num fromIntegral(Integral i)
.
In terms of OO languages, you need to think of it as generics/templates, not virtual inheritance/subtype polymorphism. That is the equivalent Java signature for fromIntegral
would look like <A extends Integral, B extends Num> B fromIntegral(A i)
, not Num fromIntegral(Integral i)
.
所以如果我们想要一个Int
,我们得到一个Int
.如果我们想要一个Integer
,我们将得到一个Integer
.如果我们想要一个Double
,我们将得到一个Double
.但是,如果我们想要String
,那么我们就不走运了,因为String
不是Num
的实例.
so if we want an Int
, we get an Int
. If we want an Integer
, we get an Integer
. And if we want a Double
, we get a Double
. But if we want a String
, we're out of luck as String
is not an instance of Num
.
在这种情况下,我们需要一个a
,其中a
是给定列表的元素类型.因此,如果我们传递Double
的列表,则fromIntegral
给我们一个Double
,如果我们传递Rational
s的列表,则fromIntegral
给我们一个Rational
.
In this case we want an a
where a
is the element type of the given list. So if we pass in a list of Double
s, fromIntegral
gives us a Double
and if we pass in a list of Rational
s, fromIntegral
gives us a Rational
.
这篇关于Haskell fromIntegral-类型混淆的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!