模式匹配抽象类型与折叠

时间:2014-05-29 13:27:46

标签: scala pattern-matching scala-macros

这是previous question I asked的后续行动,远未完成。随后的所有代码都在Scala控制台中编译并运行良好。

考虑以下抽象数据类型,以及作为类型类必须支持的操作:

trait SIG {
  type XOrY
  type X <: XOrY
  type Y <: XOrY
}

trait SIGOps[Sig <: SIG] {
  def makeX(s: String): Sig#X
  def makeY(i: Int): Sig#Y
  // the disjunction is enforced with that fold
  def fold[T](xy: Sig#XOrY)(isX: String => T, isY: Int => T): T
  // the following is for convenience, as we want to mimick case classes
  object X {
    def apply(s: String): Sig#X = makeX(s)
    def unapply(xy: Sig#XOrY): Option[String] = fold(xy)(s => Some(s), i => None)
  }
  object Y {
    def apply(i: Int): Sig#Y = makeY(i)
    def unapply(xy: Sig#XOrY): Option[Int] = fold(xy)(s => None, i => Some(i))
  }
}

现在,这是签名的可能实现。类型类实例位于伴随对象中以便于发现。

trait EitherSig extends SIG {
  type XOrY = scala.util.Either[String, Int]
  type X = scala.util.Left[String, Int]
  type Y = scala.util.Right[String, Int]
}

object EitherSig {

  implicit object EitherSIGOps extends SIGOps[EitherSig] {
    def makeX(s: String): EitherSig#X = scala.util.Left[String, Int](s)
    def makeY(i: Int): EitherSig#Y = scala.util.Right[String, Int](i)
    def fold[T](xy: EitherSig#XOrY)(isX: String => T, isY: Int => T): T = xy match {
      case Left(s) => isX(s)
      case Right(s) => isY(s)
    }
  }

}

最后,这里是人们如何编写依赖于抽象签名的代码。

class Example[Sig <: SIG](implicit ops: SIGOps[Sig]) {
  import ops._
  def main(args: Array[String]): Unit = {
    val xy: Sig#XOrY = X("foo")
    xy match {
      case X(s) => println("X: "+s)
      // Scala does not see that the pattern matching is not exhaustive if when I comment the following line
      // case Y(i) => println("Y: "+i)
    }
  }
}

object ConcreteExample extends Example[EitherSig]

它按预期工作:

scala> ConcreteExample.main(Array())
X: foo

问题如下:我如何教Scala识别模式匹配何时不像上述那样详尽?

可能有a way to communicate this information to the typechecker,但我不知道如何。

1 个答案:

答案 0 :(得分:0)

Jason Zaugg给了an answer on Twitter

  

[...]我们没有扩展点。只考虑密封的层次结构。

Travis Brown proposedWrite a matchExhaustive macro that inspects the partial function但不认为是Worth the trouble when you've got the fold

现在对这个问题没有真正的解决方案。