这是 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但我不知道怎么做。
最佳答案
Jason Zaugg 给了 an answer on Twitter :
[...] we don't have an extension point for that. Only sealed hierarchies are considered.
特拉维斯·布朗 proposed 编写一个检查部分函数的 matchExhaustive 宏
,但不认为它是当你得到 fold 时值得麻烦
。
所以目前这个问题还没有真正的解决方案。
关于scala - 具有折叠的抽象类型的模式匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23934528/