简体   繁体   English

(数字a)vs整数类型推断

[英](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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM