我正在编写以下代码来说明问题:
def max[T <% Ordered[T]](a: T, b: T) = {
val c = a.compare(b)
if (c > 0) a else b
}
def min[T <% Ordering[T]](a: T, b: T) = {
val ord = implicitly[Ordering[T]]
val c = ord.compare(a, b)
if (c > 0) b else a
}
println(s"max is ${max(10, 20)}")
implicit val intOrdering = new Ordering[Int] {
override def compare(x: Int, y: Int): Int = x - y
}
println(s"min is ${min(10, 20)}")
max
方法效果很好,而min
方法却没有,抱怨No implicit Ordering defined for T
即使我定义了intOrdering
,它仍会抱怨。
我会问为什么Ordered
有效,但Ordering
不在此处,即使我已为Ordering[Int]
答案 0 :(得分:4)
Ordered
和Ordering
在语义上不同。 Ordered[T]
是支持与其他Ordered[T]
进行比较的对象,而Ordering[T]
是一个对象,它是能够比较普通T
s的函数集合。 / p>
这种差异反映在您需要使用的两种类型的边界中。视图绑定[T <% Ordered[T]]
意味着在范围内某处需要隐式函数T => Ordered[T]
。此函数是隐式转换intWrapper(Int): RichInt
。这些RichInt
直接通过比较方法支持它们之间的比较。
但是,def min[T <% Ordering[T]]...
无效。这需要T => Ordering[T]
,或者从类型的值到该类型的排序的函数。对于某些类型,这可能存在,但对于大多数类型,如Int
,它不会。
另一种绑定是上下文绑定T: Ordering
,这是您必须在min
中使用的内容。此表单的上下文绑定请求隐式Ordering[T]
,即def min[T: Ordering](a: T, b: T)
将两个T
作为参数,还有一个隐式Ordering[T]
定义它们的排序方式。
在数学语言中:视图绑定的格式为Left <% Right
,适用于类型Left
的某些类型Right
和*
,导致创建类型为Left => Right
的隐式参数。 上下文绑定的格式为Left: Right
,适用于Left
某种k
类型Right
k -> *
种类Right[Left]
,导致创建类型为Object.objects.all()
的隐式参数。
答案 1 :(得分:2)
view bound
方法中使用的max
实际上只是一个捷径:
def max[T](a: T, b: T)(implicit ord: T => Ordered[T]) = {
val c = a.compare(b)
if (c > 0) a else b
}
对于Ordering
方法, Ordered
需要隐式值(与min
的隐含函数相对),因此view bound
不适用:
def min[T](a: T, b: T)(implicit ord: Ordering[T]) = {
val c = ord.compare(a, b)
if (c > 0) b else a
}
以context bound
的形式表达上述内容会产生以下结果:
def min[T: Ordering](a: T, b: T) = {
val ord = implicitly[Ordering[T]]
val c = ord.compare(a, b)
if (c > 0) b else a
}