3

我正在scala中试验上下文边界,但我没有找到一种方法来对这两个函数中的任何一个进行类型检查:

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
}

在 addExp1 的情况下,我可以理解编译器在函数定义点没有信息知道 Val 的参数是 Numeric,因此有一个 + 方法。它只是匹配 Any 作为 v1 的类型。

在 addExp2 的情况下,如何强制在模式中绑定?类型被“擦除”...T 注释被擦除消除...

我梦想拥有的是一个单点来设置界限,理想情况下是 Val 类的定义。

4

2 回答 2

3

避免丢失 Val 的参数化类型的一种方法是让 Expr 也采用类型参数。

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)

这编译没有警告。

现在我们需要的是一种Nothing为 Expr 的类型参数指定默认类型的方法:)。

于 2013-01-30T17:33:33.767 回答
3

问题在于,当您进行模式匹配时, 的两个实例Val可以具有不同的类型参数,例如Val[T1]Val[T2]

您可以按照@rjsvaljean 的建议修复它,并添加import Numeric.Implicits._以使用漂亮的运算符表示法。

于 2013-01-30T17:42:56.897 回答