使用上下文绑定类型参数时,有没有办法使用更短的语法?目前我有类似的东西
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))
}
它使更复杂的公式变得不可读。
答案 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”类被称为“丰富我的库”模式。
答案 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]]
。