【问题标题】:Fixing a match clause warning by getting rid of a type parameter通过摆脱类型参数来修复匹配子句警告
【发布时间】:2011-09-09 16:42:17
【问题描述】:

我想实现以下详尽匹配,但我不知道要删除类型参数,因此无法删除它被删除的警告:

sealed trait Q[+V]
case object QEmpty extends Q[Nothing]
sealed trait QNonEmpty[V] extends Q[V] {
  def foo: V
}
final class QLeaf[V](val foo: V) extends QNonEmpty[V]
final class QNode[V](val foo: V, var children: Array[Q[V]]) extends QNonEmpty[V]

def test[V](n: Q[V]): String = n match {
  case QEmpty          => "empty"
  case n: QNonEmpty[V] => n.foo.toString  // warning: type parameter V is erased
}

在我的具体情况下,case n 匹配的主体非常大,我不想添加更多匹配子句,以便我匹配 QLeaf 和 QNode(因为在我的具体情况下,有两个以上的子类,它们也是可变的,因此不应该是案例类)。解析的类型必须是QNonEmpty[V],不能是QNonEmpty[_]。

我可以为QNonEmpty 创建一个同时匹配QLeaf 和QNode 的提取器吗?

【问题讨论】:

  • 附注请不要清单;这是一个性能关键位,所以请不要像trait Q[ +V ] { def lift: Either[ QEmpty, QNonEmpty[ V ]]}这样的额外对象创建
  • 编写这种提取器的唯一方法是将 isInstanceOf 与具体类型一起使用。我想你知道怎么做吗?
  • @Kim Aehm,不,但我已经写了一些简单的提取器,所以肯定可以弄清楚。可惜不能做到类型安全

标签: scala pattern-matching type-erasure extractor


【解决方案1】:

您可以使用存在类型来匹配带有已擦除参数的类型:

type AnyNonEmpty = QNonEmpty[X] forSome { type X }

in match {
  case x: AnyNonEmpty => //...
}

提取器可能如下所示:

object QNonEmpty {
  def unapply(in: QNonEmpty[_]): Option[Any] = Some(in.foo)
}

def test[ V ]( n: Q[ V ]) : String = n match {
   case QEmpty => "empty"
   case QNonEmpty(foo) => foo.toString
}

我认为您不能编写类型安全的提取器,因为在您的示例代码中,该方法的类型参数也被删除了。 也许你应该考虑在你的 trait 中添加一个 fold 方法并像这样重写你的示例:

sealed trait Q[ +V ] {
  def fold[A](e: => A, f: V => A): A = e
}

case object QEmpty extends Q[ Nothing ]

sealed trait QNonEmpty[ V ] extends Q[ V ] {
  def foo: V
  override def fold[A](e: => A, f: V => A) = f(foo)
}

// ...

def test[V](n: Q[V]) = n.fold("empty", _.toString)

【讨论】:

  • 谢谢。我有点喜欢fold 方法。就我而言,我可以完全控制Q,所以添加它没问题。 (不过,我仍然想知道如果 Q 来自某个外部库,我会怎么做。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多