这是Learn You A Haskell中的一个例子,关于高阶函数的章节:
compareWithHundred :: (Num a, Ord a) => a -> Ordering
compareWithHundred x = compare 100 x
虽然功能的概念对我来说很清楚,但我不确定为什么类型签名是(Num a,Ord a)。我们只传递要与Int类型的函数进行比较的整数。 Ord
代表什么,为什么在类型签名中隐式传递参数?
答案 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
因此,您只将一个参数传递给函数,因为类型签名中只有一个参数a
。 a
是一个类型变量,只要该类型满足约束,就可以替换为任何类型的。
Num a
表示您替换a
的所有内容必须为数字(因此可以是Int
,Integer
,Double
,... ),Ord a
表示它必须具有可比性。 leftroundabout的答案详细说明了为什么你需要两者,我只想确保你知道如何阅读签名。
因此,在某种意义上说compareWithHundred "foobar"
完全合法,类型检查器表示该表达式的类型为Ordering
,但是当它尝试时它会失败检查是否有Num String
个实例。
我希望这会有所帮助。