Haskell,一个参数的多个类型

时间:2016-11-25 23:34:55

标签: haskell types

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

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

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

2 个答案:

答案 0 :(得分:9)

这不是此签名唯一可能的签名。它碰巧是最通用的compareWithHundred :: Int -> Ordering实际上是一个可能的实例化 - 多态a参数可以使用任何可订购的数字类型进行实例化,其确实包含Int,还包括Integer,{{1 },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

因此,您需要同时要求参数为数字(因此存在要与之比较的值100)并且参数位于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) 类中。这个组合约束写为Ord

答案 1 :(得分:7)

我还有一些事情需要补充,以防你无法从左撇子那里得到一些全面的答案。

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

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个实例。

我希望这会有所帮助。