[英](Num a) vs Integer type inference
Consider the following Haskell function: 考虑以下Haskell函数:
sign a
| a < 0 = (-1)
| a > 0 = 1
| otherwise = 0
When I load this into ghci I expected :t sign
to be: 当我将其加载到ghci中时,我期望:t sign
为:
sign :: (Num a, Ord a) => a -> Integer
Instead it inferred it as: 相反,它推断为:
*Main> :t sign
sign :: (Num a1, Num a, Ord a1) => a1 -> a
Similarly, if I ask for the type of the integer 5
, I expected Integer
, but instead I got 同样,如果我要求整数5
的类型,我希望使用Integer
,但是我得到了
*Main> :t 5
5 :: Num a => a
There's something I am not understanding about Haskell's types. 关于Haskell的类型,我有些不了解。 The thing is, if all I know about the return type of sign
is that it is an instance of the Num
typeclass, then I should not be able to pass its return value into this function: 问题是,如果我所知道的关于sign
的返回类型的全部是它是Num
类型类的实例,那么我应该不能将其返回值传递给此函数:
double :: Integer -> Integer
double x = x * 2
That is, my double
function requires an Integer
, not just any instance of Num
. 也就是说,我的double
函数需要一个Integer
,而不仅仅是Num
任何实例。
Yet, the following works just fine: 但是,以下工作正常:
*Main> double (sign 5.5)
2
What is it that I am mis-understanding about Haskell's type system? 我对Haskell的类型系统有误解是什么?
The thing is, if all I know about the return type of 'sign' is that it is an instance of the
Num
typeclass, then I should not be able to pass its return value into this function: 问题是,如果我对'sign'的返回类型的全部了解是它是Num
类型类的实例,那么我应该不能将其返回值传递给此函数:
Right, if that were all that you knew, you couldn't pass it to double
. 是的,如果您只知道这些,就无法将其double
。
But the type 但是类型
sign :: (Num a1, Num a, Ord a1) => a1 -> a
means that the result type of sign
is whichever Num
type the caller demands . 装置,其的结果类型sign
是取其 Num
键入呼叫者的需求 。 Type variables in type signatures are (implicitly) universally quantified, not existentially , like for eg Java interfaces. 类型签名中的类型变量是(隐式) 通用量化的,而不是像Java接口那样存在的 。
sign
can produce a return value of arbitrary type, subject to the restriction it be an instance of Num
, and the type it returns is determined by the calling context. sign
可以产生任意类型的返回值,但要受限制,它可以是Num
的实例,并且返回的类型由调用上下文确定。
If the caller wants an Integer
, it gets one. 如果呼叫者想要一个Integer
,它将得到一个。 If it wants a Double
, no problem either. 如果要使用Double
,也没有问题。
I forgot to mention initially: 我最初忘记提及:
Similarly, if I ask for the type of the integer 5, I expected "Integer", but instead I got 同样,如果我要求整数5的类型,我希望输入“ Integer”,但是我得到了
*Main> :t 5
5 :: Num a => a
Numeric literals are polymorphic, an integer literal stands for fromInteger value
, and a fractional literal for fromRational value
. 数值文字是多态的,整数文字代表fromInteger value
,而分数文字则代表fromRational value
。
I just wanted to clarify @DanielFischer's answer a little. 我只是想澄清一下@DanielFischer的答案。 A type signature like f :: Num b => a -> b
means that f
is capable of returning any instance of the typeclass Num
. 像f :: Num b => a -> b
这样的类型签名意味着f
能够返回类型类Num
任何实例。 When f
is called, Haskell uses the context (the type signature of the caller) to determine the concrete type of b
. 调用f
,Haskell使用上下文(调用方的类型签名)确定b
的具体类型。
Moreover, Haskell's numeric literals are an example of this type of polymorphism. 此外,Haskell的数字文字就是这种多态性的一个例子。 That's why :t 5
gave you Num a => a
. 这就是为什么:t 5
给您Num a => a
。 The symbol 5
is capable of acting as any type of number, not just an integer. 符号5
可以充当任何类型的数字,而不仅仅是整数。 The context it appears in determines which it will be. 它出现的上下文决定了它将是哪个。
In Haskell, if a function returns type x
is its result, that means that the caller can choose what x
should be, not the function . 在Haskell中,如果函数返回类型x
是其结果,则意味着调用者可以选择x
应该是什么,而不是function 。 Rather, the function must be able to return any possible type . 相反, 该函数必须能够返回任何可能的type 。
Your sign
can return any type of data - including Integer
. 您的sign
可以返回任何类型的数据,包括Integer
。 The double
function wants an Integer
, so that's just fine - sign
can return that. double
函数需要一个Integer
,所以就可以了sign
可以返回它。
Another part of the puzzle you may not be aware of: In Java, 2
has type int
and 2.0
has type double
. 您可能没有意识到的难题的另一部分:在Java中, 2
具有int
类型,而2.0
具有double
类型。 But in Haskell, 2
has type Num x => x
- in other words, any possible number type . 但是在Haskell中, 2
类型为Num x => x
换句话说, 任何可能的数字类型 。 (Also 2.0
has type Fractional x => x
, which is a similar deal.) (另外2.0
具有类型Fractional x => x
,这是类似的处理。)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.