pattern-matching - 模棱两可的守卫模式

标签 pattern-matching ocaml

OCaml 的 future 4.03 版本增加了一个新警告,57 , 防止 ambiguous guarded pattern .也就是说,问题在于带有 when 的 or 模式。子句,如果 or-pat 的第一部分匹配,但 when评估为 false ,完整的模式将被丢弃,尽管 or-pat 的另一个变体可能会成功。例如,在以下代码中,ko将绑定(bind)到1 ,这可能令人惊讶:

type t = A of string | B of string

let bad x y =
  match x,y with
  | A s, _ | _, A s when s = "foo" -> 0
  | _, _ -> 1

let ok = bad (A "foo") (A "bar")
let ko = bad (A "bar") (A "foo")

在 4.03 中,OCaml 会提示 Warning 57: Ambiguous guarded pattern, variable s may match different or-pattern arguments ,建议您检查一下您是否真的有意这样做。

但是,警告在以下定义中模式匹配的第二行也处于事件状态:
let f x y =
  match  x,y with
  | A _, A _ -> 0
  | A s, _  | _, A s when s = "foo" -> 1
  | _ -> 2

在这里,我认为不会出现歧义,因为 A _, A _由第一行匹配,因此,如果程序到达这一点,则 or-pattern 的组件最多可以匹配。这个推理正确吗?

如果答案是肯定的,我还想知道是否可以在此特定分支上消除此警告。确实,我可以做match [@warning "-57"] x,y with ,但是如果稍后有人在那里引入另一个模棱两可的模式,这将使警告静音。我试图将属性放在模式级别( | A s, _ | _, A s [@warning "-57"] when s = "foo" ),但这没有效果。

注意:我知道在这种特定情况下,我可以用 | A s, B _ | B _, A s when s = "foo" 替换包罗万象的内容。使歧义消失,但请考虑这只是一个简化的例子。

最佳答案

该警告适用于不知道 when 的人守卫不是模式的一部分,想象一下 A s, _ | _, A s when s = ""A s, _ | (_, A s when s = "") 相同这在语法上是无效的。

保留警告似乎是个好主意,尽管如果显式括号阻止它会很好,例如(A s, _ | _, A s) when s = "" .

您建议编译器应该比普通读者更聪明,并根据不明显的规则抑制警告。换句话说,您的推理是正确的,但对于习惯于依赖警告的程序员来说,开销太大了。

关于pattern-matching - 模棱两可的守卫模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35510124/

相关文章:

Scala 2.8.0.RC2 编译器关于模式匹配语句的问题?

reference - 循环变量前的 `&`有什么作用?

debugging - 堆栈溢出后,如何在 OCaml 中获得完整的、未截断的堆栈跟踪?

makefile - 我的 Makefile 中有硬编码路径 - 如何使用 ocamlfind 消除这些路径? (或如何改用 ocamlbuild 或 omake)

tdd - 如何进行测试驱动开发?

f# - 匹配可区分联合时的类型通配符

java - 无法将 [ 替换为 {

Java正则表达式匹配多行

syntax-error - 仿函数中的 OCaml 语法错误

makefile - 强制 make 不重新排序自动变量扩展中的先决条件