Scala Ordering,Ordered和View Bound

时间:2017-06-28 03:40:54

标签: scala

我正在编写以下代码来说明问题:

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]

提供隐式定义

2 个答案:

答案 0 :(得分:4)

OrderedOrdering在语义上不同。 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
}