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
,但也包括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
并非所有的数字类型都允许您订购 - 虽然比较它们 - 这种不可能的经典示例是复杂数字(它们有“多个方向”,您可以订购它们)。
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
所以你只传递一个参数给函数,因为类型签名中只有一个参数a
。 a
是一个类型变量,只要该类型满足约束条件,就可以用任何类型替换。
Num a
表示,无论您替换a
数字必须是数字(因此它可以是Int
, Integer
, Double
,...), Ord a
表示它必须具有可比性。 leftroundabout的答案更详细地解释了为什么你需要这两个,我只是想确保你知道如何阅读签名。
因此,在某种意义上说,比较compareWithHundred "foobar"
,类型检查器说这个表达式的类型是Ordering
,但是当它试图检查是否有Num String
实例时,它会失败。
我希望这有帮助。
链接地址: http://www.djcxy.com/p/43131.html