简体   繁体   English

Haskell,一个参数的多个类型

[英]Haskell, multiple type classes for one argument

This is an example in Learn You A Haskell, chapter on higher order functions: 这是Learn You A Haskell中的一个示例,有关高阶函数的章节:

compareWithHundred :: (Num a, Ord a) => a -> Ordering  
compareWithHundred x = compare 100 x  

While the idea of the function is clear for me, I'm not sure why type signature is (Num a, Ord a). 虽然功能的想法对我来说很清楚,但我不确定为什么类型签名是(Num a,Ord a)。 We only pass integer that is to be compared to the function, of type Int. 我们只传递要与Int类型的函数进行比较的整数。 What Ord stands for here, and why is implicitly passed argument in type signature? Ord在这里代表什么,为什么在类型签名中隐式传递参数?

That's not the only possible signature for this signature. 这不是签名的唯一可能签名。 It happens to be the most general one. 它恰好是最普遍的一个。 compareWithHundred :: Int -> Ordering is actually a possible instantiation – the polymorphic a argument can be instatiated with any orderable number type, which does sure enough include Int , but also Integer , Rational , Double ... compareWithHundred :: Int -> Ordering实际上是一个可能的实例-多态a参数可以用任何数量的订购类型,它确实果然被包括instatiated Int ,也是IntegerRationalDouble ...

Prelude> let compareWithHundred :: (Num a, Ord a) => a -> Ordering; compareWithHundred x = compare 100 x
Prelude> compareWithHundred (99 :: Int)
GT
Prelude> compareWithHundred (100.3 :: Double)
LT

Not all number types permit you to order-compare them though – the classical example where this is not possible are complex numbers (which have “more than one direction” in which you could order them). 并非所有数字类型都允许您订购 - 比较它们 - 不可能的经典示例是复数(具有“多个方向”,您可以在其中订购它们)。

Prelude Data.Complex> compareWithHundred (100 :+ 30 :: Complex Double)

<interactive>:10:1:
    No instance for (Ord (Complex Double))
      arising from a use of ‘compareWithHundred’
    In the expression: compareWithHundred (100 :+ 30 :: Complex Double)
    In an equation for ‘it’:
        it = compareWithHundred (100 :+ 30 :: Complex Double)

Hence you need to require both that the argument is a number (so there exists a value 100 which to compare with) and that the argument is in the Ord class. 因此,您需要同时要求参数是一个数字(因此存在要与之比较的值100)并且参数在Ord类中。 This combined constrained is written (Num a, Ord a) . 写入组合约束(Num a, Ord a)

I have something to add, in case you couldn't gather something from leftaroundabout's thorough answer. 我有一些东西需要补充,以防你无法收集左撇子的全面答案。

Everything to the left of => in a type signature is a constraint . 在类型签名中=>左边的所有内容都是约束 Read the type like this: 阅读这样的类型:

compareWithHundred :: (Num a, Ord a) => a -> Ordering
                      ^^^^^^^^^^^^^^    ^    ^^^^^^^^
                       constraints      |         |
                                 argument type    |
                                             result type

So you only pass one argument to the function because there is only one argument in the type signature, a . 所以你只将一个参数传递给函数,因为类型签名中只有一个参数, a a is a type variable, and can be replaced with any type as long as that type satisfies the constraints . a是一个类型变量, 只要该类型满足约束条件 ,就可以用任何类型替换。

The Num a says that whatever you replace a with has to be numeric (so it can be Int , Integer , Double , ...), and the Ord a says that it has to be comparable. Num a表示无论你更换a必须是数字(所以它可以是IntIntegerDouble ,...),而Ord a说它必须是可比较的。 leftroundabout's answer goes into more detail about why you need both, I just wanted to make sure you knew how to read the signature. leftroundabout的答案详细说明了为什么你需要两者,我只是想确保你知道如何阅读签名。

So it's perfectly legal in one sense to say compareWithHundred "foobar" , the type checker says that that expression's type is Ordering , but then it will fail later when it tries to check that there is a Num String instance. 因此,在某种意义上说compareWithHundred "foobar"是完全合法的,类型检查器表示该表达式的类型是Ordering ,但是当它试图检查是否存在Num String实例时它将失败。

I hope this helps. 我希望这有帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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