我正在开发一个专门的四叉树来做一些生物信息学。qtree 的类型是:
type base = A | C | G | T | ROOT ;;
type quad_tree = Nd of bases * quad_tree * quad_tree * quad_tree * quad_tree
| Empty
| Leaf of int ref ;;
let init_quad_tree = Nd(ROOT, Empty,Empty,Empty,Empty);;
let new_node b = Nd(b,Empty,Empty,Empty,Empty);;
现在在构建或行走时对这些树进行匹配,最终会得到如下结果:
let rec add_node base k qtree =
let rec aux k' accum qtree' =
if k' = k then
match qtree' with
| Nd(bse, Empty, cc, gg, tt) -> Nd(bse, (Leaf(ref accum)),cc,gg,tt)
| Nd(bse, aa, Empty, gg, tt) -> Nd(bse, aa,(Leaf(ref accum)),gg,tt)
| Nd(bse, aa, cc, Empty, tt) -> Nd(bse, aa,cc,(Leaf(ref accum)),tt)
| Nd(bse, aa, cc, gg, Empty) -> Nd(bse, aa,cc,gg,(Leaf(ref accum)))
| Leaf _ -> qtree'
| Empty -> Leaf(ref accum)
| _ -> qtree'
else
match qtree' with
| Leaf(iref) -> iref := !iref + 1; qtree'
| Nd(bse, Empty,Empty,Empty,Empty) -> (*all empty*)
(
match base with
| A -> Nd(bse,(new_node base),Empty,Empty,Empty)
| C -> Nd(bse,Empty,(new_node base),Empty,Empty)
| G -> Nd(bse,Empty,Empty,(new_node base),Empty)
| T -> Nd(bse,Empty,Empty,Empty,(new_node base))
| _ -> qtree'
)
...
| Nd(bse, Empty,(Nd(_,_,_,_,_) as c),(Nd(_,_,_,_,_) as g),(Nd(_,_,_,_,_) as t)) ->
(
match base with
| A -> Nd(bse,(new_node base),(aux (k'+1) (accum+1) c),(aux (k'+1) (accum+1) g),(aux (k'+1) (accum+1) t))
| C -> Nd(bse,Empty,(aux (k'+1)(accum+1) c),(aux (k'+1)(accum+1) g),(aux (k'+1)(accum+1) t))
| G -> Nd(bse,Empty,(aux (k'+1)(accum+1) c),(aux (k'+1)(accum+1) g),(aux (k'+1)(accum+1) t))
| T -> Nd(bse,Empty,(aux (k'+1)(accum+1) c),(aux (k'+1)(accum+1) g),(aux (k'+1)(accum+1) t))
| _ -> qtree'
)
...
| Nd(bse, (Nd(_,_,_,_,_) as a),(Nd(_,_,_,_,_) as c),(Nd(_,_,_,_,_) as g),(Nd(_,_,_,_,_) as t)) ->
...
你明白了,基本上我需要覆盖那里的所有 16 个组合(4 个子树可以是空的或 Nd)。打字很多,而且容易出错。
然而,它是一个非常规则的结构,适合于代码生成。我打算使用 Ruby 脚本实际生成此代码,但我想知道这是否可以使用 campl4 或新的 -ppx 样式“宏”(因为没有更好的术语)?如果是这样,我怎么能从这两个方向开始呢?