上下文边界的语法更短?

时间:2014-11-08 18:56:47

标签: scala

使用上下文绑定类型参数时,有没有办法使用更短的语法?目前我有类似的东西

case class Vector2D[a : Numeric](x: a, y: a) {
  val numA = implicitly[Numeric[a]]

  def length2 = numA.plus(numA.times(x, x), numA.times(y, y))
}

它使更复杂的公式变得不可读。

2 个答案:

答案 0 :(得分:2)

尝试此REPL会话:

scala>  case class Vector2D[T : Numeric](x: T, y: T) {
  val numeric = implicitly[Numeric[T]]
  import numeric._
  def length2 = (x*x)+(y*y)
}

defined class Vector2D

scala> Vector2D(3,4).length2
res0: Int = 25

这是因为Numeric包含一个名为mkNumericOps的隐式转换,您可以如上所示导入该转换。如果它没有开箱即用,那么你自己滚动它的方式就像:

scala> implicit class NumericOps[T](val x: T) extends AnyVal { def +(y: T)(implicit n: Numeric[T]): T = n.plus(x, y)
     | def *(y: T)(implicit n: Numeric[T]): T = n.times(x, y)
     | }
defined class NumericOps

scala> case class Vector2D[a : Numeric](x: a, y: a) { def length2 = (x*x)+(y*y) }
defined class Vector2D

scala> Vector2D(3,4).length2
res0: Int = 25

如果你使NumericOps不是一个值类(不扩展AnyVal),那么隐式Numeric可以继承构造函数而不是每个方法,这可能更好,或者不重要。

无论如何,由于Numeric已经有mkNumericOps

,因此无需自行编写

这些“ops”类被称为“丰富我的库”模式。

Numeric.Opshere 并且在Numeric here上隐式导入以自动创建它是mkNumericOps

答案 1 :(得分:2)

只是

import Numeric.Implicits._

然后对于可以找到隐式数字的每种类型

(根据@Havoc P的建议,只导入一个Numeric实例的NumericOps转换,可以更好地控制哪些类型的操作可用,但大多数情况下,Numeric.Implicits应该没问题)

在更一般的问题上,使用上下文边界类型参数时会有更短的语法:通常,没有。根据类型规定,提供一些糖使其易于使用,正如Numeric在这里所做的那样。

例如,或多或少习惯在伴侣对象中使用apply方法,这使得实例比隐式方法更容易

object Ordering {
   def apply[T](implicit ord: Ordering[T]): Ordering[T] = implicitly[Ordering[T]]
}

这样你就可以得到隐含的Ordering[Int],而不是implicitly[Ordering[Int]]