1

次の徹底的な一致を実装したいのですが、型パラメーターを削除する方法がわからないため、型パラメーターが消去されるという警告が表示されます。

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
}

私の具体的なケースでは、一致の本体が非常に大きく、代わりにandcase nに対して一致するようにこれ以上 match 句を追加したくありません(私の具体的なケースでは 2 つ以上のサブクラスがあり、それらも変更可能であり、したがってケースクラスではありません)。解決された型は である必要がありますが、 ではありません。QLeafQNodeQNonEmpty[V]QNonEmpty[_]

と の両方にQNonEmpty一致するエクストラクタを作成できますか?QLeafQNode

4

1 に答える 1

3

存在型を使用して、パラメータが消去された型と一致させることができます。

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
}

ただし、コード例ではメソッドの型パラメーターも消去されるため、タイプセーフなエクストラクターを作成できるとは思いません。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)
于 2011-06-07T01:06:12.163 に答える