我正在实现一棵树。在我的程序执行期间,数据被添加到节点。
下面的代码显示了我的第一个实现:
type 'a tree =
| Node of 'a
| Leaf
type nodata_node =
{
b: nodata_node tree;
}
type data_node =
{
a: int;
b: data_node tree;
}
此实现的问题在于,我无法在以下代码段中表示值b
:
let a = { b = Node { b = Leaf } }
let b = { b = Node { a = 1; b = Leaf } }
我需要能够代表一个node
没有data
却又有孩子的type _ data =
| Unknown : unit -> unit data
| SomeInt : int -> int data
type 'a tree =
| Node of ('a, 'a) node
| Leaf
and ('a, 'b) node =
{
a: 'a data;
b: 'b tree;
}
let a = { a = Unknown (); b = Node { a = Unknown (); b = Leaf } }
let b = { a = Unknown (); b = Node { a = SomeInt 1; b = Leaf } }
。
所以我想出了以下实现:
type 'a tree =
| Node of ('a, 'a) node
| Leaf
and ('a, 'b) node =
{
a: 'a;
b: 'b tree;
}
let a = { a = (); b = Node { a = (); b = Leaf } }
let b = { a = (); b = Node { a = 1; b = Leaf } }
可以,但是首先有一个空字段,然后填充它似乎有点笨拙。我想知道是否存在一种与第二种等效的解决方案,但其解决方案与第一种类似,因为没有数据的节点不会由带有空数据字段的结构表示。
编辑: 现在我意识到我对GADT的使用并没有给我提出的问题带来太多帮助,因此,这是第二次尝试的简单版本:
{{1}}
EDIT2:我想有一种方法可以使用函子和相互递归定义。我对不依赖函子的解决方案感兴趣。
答案 0 :(得分:2)
如果您希望保留'a tree
类型的构造函数,则可以申请:
type 'a tree =
| Node of 'a
| Leaf
type child_node = {data:int; x: child; y:child}
and child = child_node tree
type parent = child tree
let x: parent = Node (Node {data=0; x=Leaf; y = Leaf})