Context boundaries and pattern matching in scala
I am experimenting with context bounds in scala and I can't find a way to do one of these two typecheck functions:
abstract class Expr
case class Val[T: Numeric](v: T) extends Expr
case object Other extends Expr
val e1 = Val(1)
val e2 = Val(2)
def addExp1(e1: Expr, e2: Expr): Expr = (e1, e2) match {
case (Val(v1), Val(v2)) => Val(v1+v2)
case _ => Other
}
def addExp2[T: Numeric](e1: Expr, e2: Expr): Expr = (e1, e2) match {
case (Val(v1: T), Val(v2: T)) => Val(v1+v2)
case _ => Other
}
In the case of addExp1, I can understand that the compiler has no information at the point of the function definition to know that the Val arguments are numeric and therefore have a + method. It just matches Any as type v1.
In the case of addExp2, how can I force the binding in the template? Type "erased" ... T annotation removed by erasure ...
What I would have dreamed of having is a single point to put a border, ideally in the definition of the Val class.
source to share
One way to avoid losing the parameterized type Val is to have Expr also a type parameter.
abstract class Expr[T]
case class Val[T: Numeric](v: T) extends Expr[T]
case object Other extends Expr[Nothing]
val e1 = Val(1)
val e2 = Val(2)
def addExp2[T: Numeric](e1: Expr[T], e2: Expr[T]): Expr[_ <: T] = (e1, e2) match {
case (Val(v1), Val(v2)) => Val(implicitly[Numeric[T]].plus(v1, v2))
case _ => Other
}
addExp2[Int](e1, e2)
This compiles with no warnings.
Now we need to specify the default type Nothing
for the type parameter Expr :).
source to share