当前位置: 首页 > 编程笔记 >

OCaml 否定范式:深度模式匹配

曾德水
2023-03-14
本文向大家介绍OCaml 否定范式:深度模式匹配,包括了OCaml 否定范式:深度模式匹配的使用技巧和注意事项,需要的朋友参考一下

示例

模式匹配允许解构复杂的值,并且绝不限于值表示的“最外部”级别。为了说明这一点,我们实现了将布尔表达式转换为布尔表达式的函数,其中所有否定都仅存在于原子上,即所谓的否定范式和谓词可识别这种形式的表达式:

我们定义布尔表达式的类型,其原子由字符串标识为

type expr =
| Atom of string
| Not of expr
| And of expr * expr
| Or of expr * expr

让我们首先定义一个谓词,它以否定正态形式识别表达式:

let rec is_nnf = function
| (Atom(_) | Not(Atom(_))) -> true
| Not(_) -> false
| (And(expr1, expr2) | Or(expr1, expr2)) -> is_nnf expr1 && is_nnf expr2

如您所见,可以与嵌套模式匹配。现在,我们实现一个函数,将一个布尔表达式映射为一个否定正态形式的等效布尔表达式:Not(Atom(_))

let rec nnf = function
| (Atom(_) | Not(Atom(_))) as expr -> expr
| Not(And(expr1, expr2)) -> Or(nnf(Not(expr1)),nnf(Not(expr2)))
| Not(Or(expr1, expr2)) -> And(nnf(Not(expr1)),nnf(Not(expr2)))
| And(expr1, expr2) -> And(nnf expr1, nnf expr2)
| Or(expr1, expr2) -> Or(nnf expr1, nnf expr2)
| Not(Not(expr)) -> nnf expr

第二个功能更多地使用了嵌套模式。最终,我们可以在隐含否定的条件下在顶层测试我们的代码

# let impl a b =
Or(Not(a), b);;
  val impl : expr -> expr -> expr = <fun>
# let expr = Not(impl (Atom "A") (Atom "B"));;
val expr : expr = Not (Or (Not (Atom "A"), Atom "B"))
# nnf expr;;
- : expr = And (Atom "A", Not (Atom "B"))
# is_nnf (nnf expr);;
- : bool = true

OCaml类型的系统能够验证模式匹配的穷尽性。例如,如果我们Not(Or(expr1, expr2))在nnf函数中省略大小写,则编译器会发出警告:

# let rec non_exhaustive_nnf = function
| (Atom(_) | Not(Atom(_))) as expr -> expr
| Not(And(expr1, expr2)) -> Or(nnf(Not(expr1)),nnf(Not(expr2)))
| And(expr1, expr2) -> And(nnf expr1, nnf expr2)
| Or(expr1, expr2) -> Or(nnf expr1, nnf expr2)
| Not(Not(expr)) -> nnf expr;;
          Characters 14-254:
  ..............function
  | (Atom(_) | Not(Atom(_))) as expr -> expr
  | Not(And(expr1, expr2)) -> Or(nnf(Not(expr1)),nnf(Not(expr2)))
  | And(expr1, expr2) -> And(nnf expr1, nnf expr2)
  | Or(expr1, expr2) -> Or(nnf expr1, nnf expr2)
  | Not(Not(expr)) -> nnf expr..
Warning 8: this pattern-matching is not exhaustive.
Here is an example of a case that is not matched:
Not (Or (_, _))
val non_exhaustive_nnf : expr -> expr = <fun>

(-w @8在调用编译器或解释器时,使用选项可以将此警告视为错误。)

此功能可提高编译器接受的程序的安全性和正确性。但是,它还有其他用途,例如可以在探索性编程中使用。从正常情况下简单的函数版本开始,并使用编译器提供的不匹配案例的示例来完善处理,将转换编写为普通形式非常有趣。

 类似资料:
  • 问题内容: 我想检查一个字符串是否匹配1-2个字母,1-4个数字和1个字母的模式。(例如: CC44C , C4444C )。 我知道这将完全匹配2个字母,4个数字和1个字母的模式。(例如: CC4444C ) 但是,如何使它与范围(即1-2个字母,1-4个数字)匹配的模式呢? 我已经尝试过,但是它给了我以下错误: 问题答案: 您需要将{1-2}更改为{1,2},您可以理解为{minimun,ma

  • 本文向大家介绍OCaml 具有模式匹配的递归列表处理,包括了OCaml 具有模式匹配的递归列表处理的使用技巧和注意事项,需要的朋友参考一下 示例 在这里,我们演示了如何使用OCaml的模式匹配语法来递归处理列表。 在这种情况下,模式[]匹配空列表,而hd::tl匹配任何具有至少一个元素的列表,hd并将列表的第一个元素分配给,列表的其余部分(可以为空)分配给tl。 请注意,这hd::tl是一种非常通

  • 模式,是Rust另一个强大的特性。它可以被用在let和match表达式里面。相信大家应该还记得我们在复合类型中提到的关于在let表达式中解构元组的例子,实际上这就是一个模式。 let tup = (0u8, 1u8); let (x, y) = tup; 而且我们需要知道的是,如果一个模式中出现了和当前作用域中已存在的同名的绑定,那么它会覆盖掉外部的绑定。比如: let x = 1; let c

  • 本文向大家介绍Rust 绑定模式匹配,包括了Rust 绑定模式匹配的使用技巧和注意事项,需要的朋友参考一下 示例 可以使用@以下方式将值绑定到名称: 这将打印:            

  • 一、模式匹配 Scala 支持模式匹配机制,可以代替 swith 语句、执行类型检查、以及支持析构表达式等。 1.1 更好的swith Scala 不支持 swith,可以使用模式匹配 match...case 语法代替。但是 match 语句与 Java 中的 switch 有以下三点不同: Scala 中的 case 语句支持任何类型;而 Java 中 case 语句仅支持整型、枚举和字符串常

  • 主机权限和 内容脚本匹配 是基于匹配模式定义的一组 URL。匹配模式本质上是一个以允许的 schema(http,https,file 或ftp 开头)的URL,并且可以包含 “*” 字符。特殊模式 < all_urls > 匹配以允许的 schema 开头的任何 URL。 每个模式包含 3 个部分: schema - 例如,http 或file 或 * 注意:对文件 URL 的访问不是自动的。用