Haskell,一个参数的多个类型类

这是Learn You Haskell的一个例子,关于高阶函数的章节:

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

虽然函数的思想对我来说很清楚,但我不确定为什么类型签名是(数字a,数字a)。 我们只传递要与Int类型的函数进行比较的整数。 Ord在这里代表什么,为什么在类型签名中隐含地传递了参数?


这不是签名的唯一可能签名。 它恰好是最普遍的一个。 compareWithHundred :: Int -> Ordering实际上是一个可能的实例 - 多态a参数可以用任何可定义的数字类型进行安装,这确实包括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

并非所有的数字类型都允许您订购 - 虽然比较它们 - 这种不可能的经典示例是复杂数字(它们有“多个方向”,您可以订购它们)。

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)

因此,您需要同时要求参数是一个数字(所以存在一个值为100的值),并且该参数在Ord类中。 这个组合约束被写入(Num a, Ord a)


我还有一些东西要补充,以防你无法从左边的答案中收集一些东西。

类型签名中=>左边的所有内容都是约束条件。 阅读这样的类型:

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

所以你只传递一个参数给函数,因为类型签名中只有一个参数aa是一个类型变量,只要该类型满足约束条件,就可以用任何类型替换。

Num a表示,无论您替换a数字必须是数字(因此它可以是IntIntegerDouble ,...), Ord a表示它必须具有可比性。 leftroundabout的答案更详细地解释了为什么你需要这两个,我只是想确保你知道如何阅读签名。

因此,在某种意义上说,比较compareWithHundred "foobar" ,类型检查器说这个表达式的类型是Ordering ,但是当它试图检查是否有Num String实例时,它会失败。

我希望这有帮助。

链接地址: http://www.djcxy.com/p/43131.html

上一篇: Haskell, multiple type classes for one argument

下一篇: Why does this function fail to typecheck?