2015-05-04 55 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