Haskell,一个参数的多个类型

kab*_*oom 5 haskell types

这是Learn You A Haskell中的一个示例,有关高阶函数的章节:

compareWithHundred :: (Num a, Ord a) => a -> Ordering  
compareWithHundred x = compare 100 x  
Run Code Online (Sandbox Code Playgroud)

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

lef*_*out 10

这不是签名的唯一可能签名.它恰好是最普遍的一个.compareWithHundred :: Int -> Ordering实际上是一个可能的实例-多态a参数可以用任何数量的订购类型,这也果然被包括instatiated Int,而且Integer,Rational,Double...

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
Run Code Online (Sandbox Code Playgroud)

并非所有数字类型都允许您订购 - 比较它们 - 这是不可能的经典示例是复数(具有"多个方向",您可以在其中订购它们).

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)
Run Code Online (Sandbox Code Playgroud)

因此,您需要同时要求参数是一个数字(因此存在要与之比较的值100)并且参数在Ord类中.这种组合约束被写入(Num a, Ord a).


luq*_*qui 7

我有一些东西需要补充,以防你无法收集左撇子的全面答案.

=>类型签名左侧的所有内容都是约束.阅读这样的类型:

compareWithHundred :: (Num a, Ord a) => a -> Ordering
                      ^^^^^^^^^^^^^^    ^    ^^^^^^^^
                       constraints      |         |
                                 argument type    |
                                             result type
Run Code Online (Sandbox Code Playgroud)

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

Num a说,无论你更换a与必须是数字(因此它可以是Int,Integer,Double,...),并Ord a说,它必须是可比的.leftroundabout的答案详细说明了为什么你需要两者,我只是想确保你知道如何阅读签名.

因此,在某种意义上说compareWithHundred "foobar",类型检查器表示该表达式的类型是完全合法的Ordering,但是当它试图检查是否存在Num String实例时它将会失败.

我希望这有帮助.