OCaml - 使用对普通树的引用来转换树

时间:2015-01-18 12:18:13

标签: tree ocaml

我有两种树种:

type ref_tree = Node of int * ref_tree list ref
type tree = Node of int * tree list

我想编写一个函数convert: ref_tree -> tree,它将邻居保存的树作为包含它们的列表的引用,并输出一个树,其中引用更改为普通列表。这是我试过的:

let rec convert t =
        match t with
        | Node (x, l) ->
            if (!l = []) then Node (x, []) else
            Node (x, (List.map convert !l))

但OCaml在尝试编译时会返回错误:

if (!l = []) then Node (x, []) else
Error: This expression has type 'a list
       but an expression was expected of type tree list ref

This expression位于Node (x, [])内的空列表中。为什么类型不匹配?

2 个答案:

答案 0 :(得分:2)

这里的问题是你定义了两个构造函数Node,第二个定义(type tree = Node of …)遮蔽了第一个构造函数。

这意味着当您与t匹配并将其解构为 Node(x, l),OCaml将此视为tree,而不是ref_tree(因此l视为tree list而不是ref_tree list ref

解决此问题的一种方法是更改​​ref_tree构造函数:

# type ref_tree = Ref_node of int * ref_tree list ref;;
type ref_tree = Ref_node of int * ref_tree list ref

# let rec convert t =
          match t with
          | Ref_node (x, l) ->
              if (!l = []) then Node (x, []) else
              Node (x, (List.map convert !l));;
val convert : ref_tree -> tree = <fun>

(另一种方法是在模块TreeRefTree中定义这些类型并使用Tree.NodeRefTree.Node

答案 1 :(得分:1)

编译器在两个Node构造函数(ref_tree之一和tree之一)之间混淆。您可以通过各种方式提供帮助,包括:

let rec convert t =
  match (t : ref_tree) with
  | Node (x, l) ->
     if (!l = []) then Node (x, []) else
       Node (x, (List.map convert !l))