繁体   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