Scala:如何模式匹配参数化类型的联合

时间:2016-01-21 04:04:35

标签: scala

我使用Rex Kerr's variant Miles Sabin's idea来在Scala中实现未装箱的联合类型。我有以下课程:

class Foo[T] {
  trait Contr[-A] {}
  type Union[A,B] = {type Check[Z] = Contr[Contr[Z]] <:< Contr[Contr[A] with Contr[B]]}

  def foo[U: Union[T,Foo[T]]#Check](x:U) = x match {
    case _: Foo[T]       => println("x is a Foo[T]")
    case _: T @unchecked => println("x is a T")
  }
}

这允许以下内容:

val aux = new Foo[Int]
aux.foo(aux)   // prints "x is a Foo[T]"
aux.foo(42)    // prints "x is a T"
aux.foo("bar") // does not compile

然而:

val bar = new Foo[Foo[Int]]
bar.foo(bar) // OK: prints "x is a Foo[T]"
bar.foo(aux) // Not OK: prints "x is a Foo[T]"

有没有办法解决这个问题,也可能会消除@unchecked

修改 我认为这个特定示例的Union类型可以简化为:

type Union[Z] = Contr[Contr[Z]] <:< Contr[Contr[T] with Contr[Foo[T]]]

然后foo函数可以是:

def foo[U: Union](x:U) = ...

这使代码更简单。但问题仍然存在。

1 个答案:

答案 0 :(得分:0)

我提出了以下内容,它似乎有效,并且更接近我的实际用例:

import scala.reflect.runtime.universe._

case class Foo[T](z:T)(implicit tt:TypeTag[T], ft:TypeTag[Foo[T]]) {

  trait Contr[-A]
  type Union[Z] = Contr[Contr[Z]] <:< Contr[Contr[T] with Contr[Foo[T]]]

  def foo[U: Union](x:U)(implicit tu:TypeTag[U]):T = tu.tpe match {
    case t if t =:= tt.tpe => x.asInstanceOf[T]
    case t if t =:= ft.tpe => x.asInstanceOf[Foo[T]].z
  }

}

现在,以下效果很好:

val aux    = new Foo[Int](42)
val bar    = new Foo[Int](7)
val foobar = new Foo[Foo[Int]](bar)

println(aux.foo(aux))       // 42
println(aux.foo(1))         // 1
println(foobar.foo(aux))    // Foo(42)
println(foobar.foo(foobar)) // Foo(7)

我很高兴摆脱x.asInstanceOf