我有两种树种:
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, [])
内的空列表中。为什么类型不匹配?
答案 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>
(另一种方法是在模块Tree
和RefTree
中定义这些类型并使用Tree.Node
和RefTree.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))