[英]Ocaml recursion: Pattern Matching
我試圖寫入遞歸fn,使用輔助函數將未標記的樹更改為標記的樹。
必填信息:
type nucleotide =
| G | C
| A | T
type helix = nucleotide list
type tree =
| Leaf of helix
| Node of tree * tree
type labeled_tree =
| LLeaf of helix
| LNode of labeled_tree * helix * labeled_tree
這是輔助函數:
let rec guess_parent_helix (x1: helix) (x2: helix) : helix =
begin match (x1, x2) with
([], []) -> []
| (h1 :: t1, h2 :: t2) ->
(if h1 = h2 then h1 else A) :: guess_parent_helix t1 t2
| _ -> failwith "invalid input: x1 and x2 have unequal lengths"
end
我編寫了以下函數,但無法編譯,因為它說我沒有用盡模式匹配:Node((Node(_,_),_))。 我不明白的是,這不包括在Node(rt,lt)模式匹配中:
let rec add_ancestor_labels (r: tree) : labeled_tree =
begin match r with
| Leaf x -> LLeaf x
| Node (lt,rt) ->
begin match r with
| Leaf x -> LLeaf x
| Node (Leaf[m], Leaf[n]) ->
LNode (add_ancestor_labels lt, guess_parent_helix [m] [n], add_ancestor_labels rt)
end
end
這是不完整的內在比賽。 外圍的比賽很好。
更新
現在的代碼沒有多大意義。 匹配r
並發現它是一個內部節點后,再次匹配r
。 沒有必要這樣做,你已經知道它是一個內部節點。
由於我不知道標簽應該是什么樣子,所以很難給出具體的建議。 這里有一些代碼將每個標簽設置為它下面的核苷酸的連接:
let labeled_tree_of_tree tree =
let rec go t =
match t with
| Leaf x -> (x, LLeaf x)
| Node (lt, rt) ->
let (llabel, llt) = go lt in
let (rlabel, lrt) = go rt in
let label = llabel @ rlabel in
(label, LNode (llt, label, lrt))
in
let (_, ltree) = go tree in
ltree
也許這會讓你感受到代碼的外觀。 毫無疑問,它會比這更復雜。
窮舉檢查僅適用於單個匹配的情況。 關於哪些情況可能的信息將不會傳播到嵌套匹配,這有時會導致一些“不可能”的情況。
在可能的情況下,最好使用以下附加案例擴展匹配:
let rec add_ancestor_labels = function
| Leaf x -> LLeaf x
| Node (Leaf x, Leaf y) ->
LNode (LLeaf x,
guess_parent_helix x y,
LLeaf y)
| Node (Leaf x, Node (l, r)) ->
LNode (LLeaf x,
...,
LNode (add_ancestor_labels l,
...,
add_ancestor_labels r))
| Node (Node ..., Leaf x) -> ...
| Node (Node ..., Node ...) -> ...
重復最外層構造函數的另一種方法是將參數綁定到變量,然后匹配這些變量:
let rec add_ancestor_labels = function
| Leaf x -> LLeaf x
| Node (l, r) ->
begin
match l, r with
| ...
end
最后,請注意Leaf [m]
僅匹配長度為1的螺旋葉 - 其他長度的螺旋葉未處理。 目前尚不清楚這是否符合您的意圖,但如果您忘記處理其他長度的葉子,則詳盡無遺檢查會發出警告。
OCaml為非窮舉匹配提供的警告消息應包括一些缺失的情況,因此請仔細閱讀。
至於你的功能,我認為會這樣寫:
let add_ancestor_labels tree =
let rec label = function
| Leaf x -> x, LLeaf x
| Node (left, right) ->
let llabel, ltree = label left in
let rlabel, rtree = label right in
let l = guess_parent_helix llabel rlabel in
l, LNode (ltree, l, rtree) in
snd (label tree)
(這與傑弗里的建議非常相似。)
let rec add_ancestor_labels (r: tree) : labeled_tree =
begin match r with
| Leaf x -> LLeaf x
| Node (lt,rt) ->
begin match (lt, rt) with
| (Leaf m, Leaf n) ->
LNode (LLeaf m, guess_parent_helix m n,
LLeaf n)
| (lt,Leaf n)-> LNode(add_ancestor_labels lt,
guess_parent_helix (helix_of_tree (add_ancestor_labels lt)) n, LLeaf n)
| (Leaf m,rt)->LNode(LLeaf m, guess_parent_helix
(helix_of_tree(add_ancestor_labels rt)) m, add_ancestor_labels rt)
| (_,_)-> failwith"invalid input"
end
end
管理完成它。 謝謝您的幫助。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.