【问题标题】:Pattern matching for abstracted case classes抽象案例类的模式匹配
【发布时间】:2012-01-02 18:12:37
【问题描述】:

我正在尝试使用依赖方法类型和编译器的夜间构建 (2.10.0.r26005-b20111114020239) 来抽象模块中的案例类。我从Miles Sabin' example 中找到了一些灵​​感。

我真的不明白下面的(独立的)代码有什么问题。输出取决于foo 中模式的顺序。

// afaik, the compiler doesn't not expose the unapply method
// for a companion object
trait Isomorphic[A, B] {
  def apply(x: A): B
  def unapply(x: B): Option[A]
}

// abstract module
trait Module {
  // 3 types with some contraints
  type X
  type Y <: X
  type Z <: X
  // and their "companion" objects
  def X: Isomorphic[Int, X]
  def Y: Isomorphic[X, Y]
  def Z: Isomorphic[Y, Z]
}

// an implementation relying on case classes
object ConcreteModule extends Module {
  sealed trait X { val i: Int = 42 }
  object X extends Isomorphic[Int, X] {
    def apply(_s: Int): X = new X { }
    def unapply(x: X): Option[Int] = Some(x.i)
  }
  case class Y(x: X) extends X
  // I guess the compiler could do that for me
  object Y extends Isomorphic[X, Y]
  case class Z(y: Y) extends X
  object Z extends Isomorphic[Y, Z]
}

object Main {
  def foo(t: Module)(x: t.X): Unit = {
    import t._
    // the output depends on the order of the first 3 lines
    // I'm not sure what's happening here...
    x match {
      // unchecked since it is eliminated by erasure
      case Y(_y) => println("y "+_y)
      // unchecked since it is eliminated by erasure
      case Z(_z) => println("z "+_z)
      // this one is fine
      case X(_x) => println("x "+_x)
      case xyz => println("xyz "+xyz)
    }
  }
  def bar(t: Module): Unit = {
    import t._
    val x: X = X(42)
    val y: Y = Y(x)
    val z: Z = Z(y)
    foo(t)(x)
    foo(t)(y)
    foo(t)(z)
  }
  def main(args: Array[String]) = {
    // call bar with the concrete module
    bar(ConcreteModule)
  }
}

有什么想法吗?

【问题讨论】:

  • 我刚刚尝试了最新的主干,但它不能为我编译:35:错误:非法依赖方法类型。使用 2.10.0.r26037-b20111121020211。它可能不适合工作?
  • 刚刚用 2.10.0.r26037-b20111121020211 进行了测试,它可以为我编译。我复制粘贴了整个块,然后Main.main(Array())

标签: scala types pattern-matching type-erasure dependent-method-type


【解决方案1】:

警告是正确的并且是意料之中的,因为从foo 内部观察,YZ 都将被删除到它们的界限内,即。 X.

更令人惊讶的是,无论是与Y 的匹配还是与Z 的匹配都会挫败与X 的匹配,即。在这种情况下,

def foo(t: Module)(x: t.X): Unit = {
  import t._
  // the output depends on the order of the first 3 lines
  // I'm not sure what's happening here...
  x match {
    // unchecked since it is eliminated by erasure
    // case Y(_y) => println("y "+_y)
    // unchecked since it is eliminated by erasure
    // case Z(_z) => println("z "+_z)
    // this one is fine
    case X(_x) => println("x "+_x)
    case xyz => println("xyz "+xyz)
  }
}

结果是,

x 42
x 42
x 42

这似乎是合理的,而早期的比赛之一已恢复,

def foo(t: Module)(x: t.X): Unit = {
  import t._
  // the output depends on the order of the first 3 lines
  // I'm not sure what's happening here...
  x match {
    // unchecked since it is eliminated by erasure
    case Y(_y) => println("y "+_y)
    // unchecked since it is eliminated by erasure
    // case Z(_z) => println("z "+_z)
    // this one is fine
    case X(_x) => println("x "+_x)
    case xyz => println("xyz "+xyz)
  }
}

结果是,

xyz AbstractMatch$ConcreteModule$X$$anon$1@3b58fa97
y AbstractMatch$ConcreteModule$X$$anon$1@3b58fa97
xyz Z(Y(AbstractMatch$ConcreteModule$X$$anon$1@3b58fa97))

这不是:我看不出有什么充分的理由为什么额外的情况会导致xyz 被选择而不是X,所以我认为你在模式匹配器中遇到了一个错误。我建议您在 Scala JIRA 中搜索类似的问题,如果找不到,请打开一张票,其中包含从上面提取的最小化重现示例。

老实说,在上面的第二个示例中,由于Y 被删除为XY 案例在@987654338 之前,我本来希望在所有三个实例中都选择Y 案例@ 匹配表达式中的大小写。但是我们在这里处于不受控制的领域,我对自己的直觉并不是 100% 有信心。

【讨论】:

    猜你喜欢
    • 2017-02-25
    • 2013-11-28
    • 1970-01-01
    • 2017-04-25
    • 2013-05-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-27
    相关资源
    最近更新 更多