【问题标题】:Context bounds and pattern matching in scalascala中的上下文边界和模式匹配
【发布时间】:2013-02-01 15:40:35
【问题描述】:

我正在 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 类的定义处。

【问题讨论】:

  • 您是只收到警告还是在addExp2 中收到错误?我必须做Val(implicitly[Numeric[T]].plus(v1, v2)) 而不是Val(v1+v2) 才能让它编译没有错误。

标签: scala


【解决方案1】:

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

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

【讨论】:

  • 感谢您的解释!
【解决方案2】:

避免丢失 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)

编译时没有警告。

现在我们所需要的只是为 Expr 的类型参数指定默认类型 Nothing :)。

【讨论】:

  • 您发布的版本实际上仍然存在警告:warning: abstract type pattern T is unchecked since it is eliminated by erasure。用 Scala 2.10 测试。您需要将 Val(v1: T) 更改为 Val(v1)
  • 确实如此。我的错。在非最终版本中复制。
  • 谢谢。我的实际问题比较复杂,毕竟你的回答提高了我对这些概念的理解,我不会使用 Numeric。
猜你喜欢
  • 2017-02-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-22
  • 2012-10-14
  • 2012-10-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多