上下文边界的较短语法



在使用上下文绑定类型参数时,是否有使用较短语法的方法?现在我有一个类似的东西

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))
}

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

尝试此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

这些"操作"类被称为"丰富我的库"模式。

Numeric.Ops在这里而被导入以自动创建它的隐式是Numeric上的mkNumericOps

import Numeric.Implicits._

则对于可以找到隐式数值的每种类型,

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

关于更普遍的问题,当使用上下文边界类型参数时,是否有一个较短的语法:一般来说,没有。这取决于typeclass提供一些糖以使其易于使用,就像Numeric在这里所做的那样。

例如,在伴随对象中或多或少有一个application方法,这使得获取实例比隐式更容易

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

这样您就可以只使用例如Ordering[Int]而不是implicitly[Ordering[Int]]来获得隐式。

最新更新