2015-05-04 47 views
0

我有一个集合T,它们的形式为int * < Abstract> * int。如何在OCaml中对抽象数据类型进行模式匹配?

我想找到这组形式的元素,例如4 * < Abstract * 5。

当我尝试使用

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

我得到它说的错误“错误:此表达式的类型为transitionSet但预计类型禄*“一*禄的表现”

如何在集合中找到一个元素?

+0

你似乎匹配要只匹配它的元素之一整套吨。 –

+0

@Sheeft是的。有没有其他的方式比从T列表中,然后检查列表中的每个元素的这种方式? –

回答

2

设置是抽象因此无法模式匹配本身。在OCaml的标准库设置模块,你可以做的是filter集合,然后检查is_empty与否:

Set.(is_empty @@ filter p t) 

其中p是你的断言。

0

我假设你设置的模块被称为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 

如果你想要的不仅仅是一个yes/no的答案,并且希望能够在集合中的所有匹配值的情况下对分支进行任意计算,那么必须使用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.html