Как сделать код, используя Value [T: Numeric], более «гибким», чем «распакованные» аналоги? - PullRequest
6 голосов
/ 03 октября 2011

Если у меня есть код, подобный 5 * 5.0, результат конвертируется в наиболее точный тип, Double.

Но, похоже, это не работает с кодом, подобным

case class Value[T : Numeric](value: T) {
    type This = Value[T]
    def +(m: This) = Value[T](implicitly[Numeric[T]].plus(value, m.value))
    ...
}

implicit def numToValue[T : Numeric](v: T) = Value[T](v)

Есть ли способ заставить такие вещи, как someIntValue + double работать, где someIntValue это Value[Int] и double это Double?

PS: извините за далеко не идеальный титул. Я благодарен за предложения по улучшению формулировки ...

1 Ответ

5 голосов
/ 03 октября 2011

Вы можете сделать это (с большим количеством занятой работы), создав неявные операторы:

abstract class Arith[A,B,C] {
  def +(a: A, b: B): C
  def -(a: A, b: B): C
  def *(a: A, b: B): C
  def /(a: A, b: B): C
}
implicit object ArithIntLong extends Arith[Int,Long,Long] {
  def +(a: Int, b: Long) = a+b
  def -(a: Int, b: Long) = a-b
  def *(a: Int, b: Long) = a*b
  def /(a: Int, b: Long) = a/b
}
...
def f[A,B,C](a: A, b: B)(implicit arith: Arith[A,B,C]) = arith.*(a,b)


scala> f(5,10L)
res46: Long = 50

но вам действительно нужно сделать больше, так как вам нужен числовой эквивалент только для A и B, и асимметричные операции должны быть определены в обоих направлениях. И не очень практично специализироваться, учитывая, что здесь задействованы три типа.

...