我正在尝试写入递归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
答案 0 :(得分:2)
内在的比赛是不完整的。外围的比赛很好。
<强>更新强>
现在的代码并没有多大意义。匹配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
也许这会让您感受到代码的外观。毫无疑问,它会比这更复杂。
答案 1 :(得分:1)
穷举检查仅适用于单个匹配的情况。关于哪些情况可能的信息不会传播到嵌套匹配,这有时会导致一些“不可能”的情况。
在可能的情况下,最好使用以下其他案例扩展匹配:
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)
(这与杰弗里的建议非常相似。)
答案 2 :(得分:1)
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
管理完成它。谢谢你的帮助。