簡體   English   中英

Ocaml遞歸:模式匹配

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM