如何进行OCAML中抽象数据类型的模式匹配



我有一个t,它具有form int*&lt的元素;摘要>*int。

我想找到该集合的一个元素,例如4*<摘要>*5。

当我尝试使用

match T with 
|(4,_,5) -> Printf.printf "yes"
|(_,_,_) -> Printf.printf "no"

我正在遇到一个错误,上面写着"错误:此表达式具有类型过渡集,但期望类型Loc *'a * loc"

的表达式。

如何在集合中找到元素?

集合是抽象的,因此无法匹配模式。在OCAML的标准库集模块中,您可以做的是filter集合,然后检查is_empty是否:

Set.(is_empty @@ filter p t)

其中 p是您的谓词。

我假设您的设置模块称为TSet,并且您使用的是OCAML标准库集。我还假设您的集合并不称为T,因为这不是OCAML变量的有效名称。

如果您仅关心是否存在单个匹配值的答案,则可以:

let result =
  TSet.exists
    (function
    | 4, _, 5 -> true
    | _       -> false)
    t in
if result then print_endline "yes" else print_endline "no"

通常,无论您的谓词是什么,您都可以做

TSet.exists p t

如果您想要的是是/否答案,并且希望能够在集合中所有匹配值的情况下执行任意计算,则必须将folditer与模式匹配使用。例如,如果您想将所有第一个整数添加在一起,但是只有当最后一个整数为5:

TSet.fold
  (fun element accumulator ->
    match element with
    | x, _, 5 -> x + accumulator
    | _       -> accumulator)
  t 0

如果您只想在第一个匹配元素上执行计算,则可以在例外进行短路评估。例如:

exception Found of int
try
  TSet.iter
    (function
    | x, _, 5 -> raise_notrace (Found x)
    | _       -> ())
    t;
  None
with Found x -> Some x

最后一个一遍又一遍地笨拙。您可以使用参考和内置Exit异常来编写多态函数来解决您自己的短路模式匹配搜索的问题。我将其作为练习。

使用raise_notrace是一个好主意,因为该例外已用于正常流量控制。如果您的程序是有一天启用了堆栈跟踪的一天,则raise_notrace在抛出异常时会省略堆栈跟踪,如果您的功能经常被调用,则可以使您的程序更快。

供您参考,http://caml.inria.fr/pub/docs/manual-ocaml/libref/set.s.s.html

最新更新