Как настроить неявное преобразование, чтобы разрешить арифметику между числовыми типами?

Я хотел бы реализовать классC для хранения значений различных числовых типов, а также логических. Кроме того, я хотел бы иметь возможность работать с экземплярами этого класса, между типами, преобразовывая при необходимостиInt --> Double а такжеBoolean -> Intто есть, чтобы иметь возможность добавлятьBoolean + Boolean, Int + Boolean, Boolean + Int, Int + Double, Double + Double и т.д., возвращая наименьший возможный тип (Int или жеDouble) когда возможно.

До сих пор я придумал это:

abstract class SemiGroup[A] { def add(x:A, y:A):A }

class C[A] (val n:A) (implicit val s:SemiGroup[A]) {
  def +[T <% A](that:C[T]) = s.add(this.n, that.n)
}

object Test extends Application {
  implicit object IntSemiGroup extends SemiGroup[Int] { 
    def add(x: Int, y: Int):Int = x + y 
  }

  implicit object DoubleSemiGroup extends SemiGroup[Double] { 
    def add(x: Double, y: Double):Double = x + y 
  }

  implicit object BooleanSemiGroup extends SemiGroup[Boolean] { 
    def add(x: Boolean, y: Boolean):Boolean = true;
  }

  implicit def bool2int(b:Boolean):Int = if(b) 1 else 0

  val n = new C[Int](10)
  val d = new C[Double](10.5)
  val b = new C[Boolean](true)

  println(d + n)    // [1]
  println(n + n)    // [2]
  println(n + b)    // [3]
  // println(n + d)    [4] XXX - no implicit conversion of Double to Int exists
  // println(b + n)    [5] XXX - no implicit conversion of Int to Boolean exists
}

Это работает для некоторых случаев (1, 2, 3), но не для (4, 5). Причина в том, что существует неявное расширение типа от низшего к высшему, но не наоборот. В некотором смысле, метод

def +[T <% A](that:C[T]) = s.add(this.n, that.n)

каким-то образом нужно иметь метод партнера, который будет выглядеть примерно так:

def +[T, A <% T](that:C[T]):T = that.s.add(this.n, that.n)

но это не компилируется по двум причинам, во-первых, что компилятор не может конвертироватьthis.n печататьT (хотя мы указываем границы просмотраA <% T) и, во-вторых, даже если бы он был в состоянии преобразоватьthis.nпосле стирания двух+ методы становятся неоднозначными.

Извините, это так долго. Любая помощь приветствуется! В противном случае кажется, что я должен явно записать все операции между всеми типами. И было бы волосатым, если бы мне пришлось добавить дополнительные типы (Complex следующий в меню ...).

Может быть, у кого-то есть другой способ достичь всего этого? Кажется, что-то простое я пропускаю.

Заранее спасибо!

Ответы на вопрос(2)

Ваш ответ на вопрос