【发布时间】:2013-02-17 21:36:30
【问题描述】:
详尽的模式匹配很棒,但它似乎只适用于 case (=>) 运算符的左侧。
我很好奇是否有一种方法可以验证函数(或表达式)的 输出 是否可以绑定到该枚举。目标是让编译器在我忘记从枚举中输出项目时告诉我。
在我的示例中,我使用了以下包含三个项目的枚举:
object MyEnum {
sealed trait t
case object E1 extends t
case object E2 extends t
case object E3 extends t
}
这是一个模式匹配表达式,它会产生编译时警告(我们已经知道):
def foo( e : MyEnum.t ) : Boolean =
e match {
case MyEnum.E1 => true
case MyEnum.E2 => false
case MyEnum.E3 => true // if we leave this line out, we get a warning
}
如果我们将MyEnum.E3 排除在模式匹配表达式之外,Scala 会抱怨,因为它引用了非详尽的模式匹配。这是非常有益的,但我想知道是否可以反过来。
我们能否说明=> 右侧的所有MyEnum.t 情况?
这是一个突出显示这一点的示例:
def bar( s : String ) : Option[MyEnum.t] =
s match {
case "a" => Some(MyEnum.E1)
case "b" => Some(MyEnum.E2)
case "c" => Some(MyEnum.E3) // if we leave this out, no warning
case _ => None
}
在这个例子中,如果我们省略了MyEnum.E3 这一行,那么编译器就会继续运行,就好像没有任何问题一样。我想说的是:
forall MyEnum.t (aliased as e) there exists Some(e) | None
我知道这可以通过运行时测试轻松解决,但我很好奇是否有办法静态检查。
谢谢。
【问题讨论】:
-
您可以轻松地在依赖类型语言中静态地检查这个,但是您必须编写会被检查的证明。在上面的示例中,您只需要简单的满射性证明,在建设性设置中,这相当于给出反函数的一半。您的问题的自动“推断”形式是不可能的,因为可能有任意复杂的逻辑掩盖您的
E1-E3返回值。
标签: scala pattern-matching dependent-type