import Complex
Section: 10.4 Default Numeric Types
第 10.4 节 默认数值类型
Ambiguous contexts arise frequently in numeric expressions. When an expression which produces a value with a general type, such as 1 (same as fromInteger 1; the type is (Num a) => a), with another expression which consumes the type, such as show or toInteger, ambiguity arises. This ambiguity can be resolved using expression type signatures, but this gets tedious fast! Assigning a type to the top level of an ambiguous expression does not help: the ambiguity does not propagate to the top level.
数值表达式中经常出现有歧义的上下文。当一个产生一般类型值的表达式,
如 1(等价于 fromInteger 1;类型是 (Num a) => a),与另一个
"消费"类型的表达式(如 show 或 toInteger)结合时,就会产生歧义。
这种歧义可以用表达式类型签名来解决,但很快就烦死人了!给歧义表达式的
顶层指定类型也无济于事:歧义不会传播到顶层。
e1 :: String -- This type does not influence the type of the argument to show
e1 = show 1 -- Does this mean to show an Int or a Float or ...
e2 :: String
e2 = show (1 :: Float)
e3 :: String
e3 = show (1 :: Complex Float)
The reason the first example works is that ambiguous numeric types are resolved using defaults. The defaults in effect here are Int and Double. Since Int fits in the expression for e1, Int is used. When Int is not valid (due to other context constraints), Double will be tried.
第一个例子之所以能工作,是因为有歧义的数值类型用默认规则解决了。
这里生效的默认类型是 Int 和 Double。由于 Int 在 e1 的表达式中"合适",
所以选用 Int。当 Int 不合法时(由于其他上下文约束),就会尝试 Double。
This function defaults the type of the 2's to be Int
这个函数会把两个 2 的类型默认为 Int:
rms :: (Floating a) => a -> a -> a
rms x y = sqrt ((x^2 + y^2) * 0.5)
One of the reasons for adding type signatures throughout these examples is to avoid unexpected defaulting. Many of the top level signatures are required to avoid ambiguity.
在这些示例中处处添加类型签名的原因之一,就是为了避免出人意料的
默认化。许多顶层签名是为了消除歧义所必需的。
Notice that defaulting applies only to numeric classes. The
注意,默认化只适用于数值类。这个
-- show (read "xyz") -- Try this if you want!
example uses only class Show so no defaulting occurs.
例子只用到类 Show,因此不会发生默认化。
Ambiguity also arises with polymorphic types. As discussed previously, expressions like [] have a similar problem.
多态类型也会有歧义。如前所述,像 [] 这样的表达式有类似的问题。
e4 = [] -- Won't print since [] has type [a] and `a' is not known.
Note the difference: even though the lists have no components, the type of component makes a difference in printing.
注意这里的区别:尽管列表没有任何元素,元素的类型对打印仍然有影响。
e5 = ([] :: [Int])
e6 = ([] :: [Char])