3

私は scala でコンテキスト境界を試していますが、これら 2 つの関数のいずれかを型チェックする方法が見つかりません。

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 であり、したがって + メソッドがあることを知るための情報が関数定義ポイントにないことがわかります。v1 のタイプとして Any に一致するだけです。

addExp2 の場合、パターンの境界を強制するにはどうすればよいですか? 型は「消去」されます... T 注釈は消去によって削除されます...

私が夢見ているのは、理想的には Val クラスの定義に境界を置くための単一のポイントです。

4

2 に答える 2

3

問題は、パターン マッチの場合、 の 2 つのインスタンスが、 となどのVal異なる型パラメーターを持つ可能性があることです。Val[T1]Val[T2]

@rjsvaljean の提案に従って修正しimport Numeric.Implicits._、nice 演算子表記を使用するように追加できます。

于 2013-01-30T17:42:56.897 に答える
3

Val のパラメーター化された型が失われないようにする 1 つの方法は、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)

これは警告なしでコンパイルされます。

ここで必要なのは、NothingExpr の型パラメーターのデフォルトの型を指定する方法だけです:)。

于 2013-01-30T17:33:33.767 に答える