Como configurar a conversão implícita para permitir aritmética entre tipos numéricos?

Eu gostaria de implementar uma classeC para armazenar valores de vários tipos numéricos e booleanos. Além disso, eu gostaria de poder operar em instâncias dessa classe, entre tipos, convertendo sempre que necessárioInt --> Double eBoolean -> Int, ou seja, para poder adicionarBoolean + Boolean, Int + Boolean, Boolean + Int, Int + Double, Double + Double etc., retornando o menor tipo possível (Int ouDouble) quando possível.

Até agora eu vim com isso:

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
}

Isso funciona para alguns casos (1, 2, 3), mas não para (4, 5). O motivo é que há um aumento implícito do tipo de menor para maior, mas não o contrário. De certa forma, o método

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

de alguma forma, precisa ter um método de parceiro parecido com:

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

mas isso não é compilado por dois motivos: primeiro, o compilador não pode converterthis.n digitarT (apesar de especificarmos o limite de visualizaçõesA <% T) e, em segundo lugar, que mesmo que fosse capaz de converterthis.n, após o tipo apagar os dois+ métodos tornam-se ambíguos.

Desculpe isso é muito longo. Qualquer ajuda seria muito apreciada! Caso contrário, parece que eu tenho que escrever todas as operações entre todos os tipos explicitamente. E ficaria peludo se eu tivesse que adicionar tipos extras (Complex é o próximo no menu ...).

Talvez alguém tenha outra maneira de conseguir tudo isso? Parece que há algo simples que estou ignorando.

Desde já, obrigado!

questionAnswers(2)

yourAnswerToTheQuestion