相互递归的数据类型

时间:2015-06-21 16:34:39

标签: recursion ocaml algebraic-data-types

我正在尝试创建一对相互递归的数据类型来表示OCaml中用于作业分配的红黑树。但是,我对OCaml语言非常不熟悉,所以我遇到了一些语法问题。

这是我到目前为止所提出的:

type 'a red_black_tree =
| RedNode of 'a * ( 'a black_node * 'a black_node )
| BlackNode of 'a black_node
and 'a black_node =
| TwoRedNodes of 'a * ( 'a RedNode * 'a RedNode )
| TwoBlackNodes of 'a * ( 'a black_node * 'a black_node )
| BlackLeaf;;

当我把它输入ocaml时,它给了我:

utop # type 'a red_black_tree =
| RedNode of 'a * ( 'a black_node * 'a black_node )
| BlackNode of 'a black_node
and 'a black_node =
| TwoRedNodes of 'a * ( 'a RedNode * 'a RedNode )
| TwoBlackNodes of 'a * ( 'a black_node * 'a black_node )
| BlackLeaf;;
Error: Syntax error

您是否无法从子类型引用类型的子值?只是语法澄清没有找到问题的实际答案。

更新

我在最初的尝试之后得到了这个,但是教授说它不是一对相互递归的数据类型

type 'a red_black_tree =
| RedNode of 'a red_node
| BlackNode of 'a black_node
and 'a red_node =
| RedTree of 'a * ( 'a black_node * 'a black_node )
and 'a black_node =
| TwoRedNodes of 'a * ( 'a red_node * 'a red_node )
| TwoBlackNodes of 'a * ( 'a black_node * 'a black_node )
| BlackLeaf;;

更新2

问题3 红黑树是一种有时用于组织数字数据的树。它有两种类型的节点,黑节点和红节点。红色节点总是有一个数据和两个子节点,每个节点都是一个黑色节点。黑色节点可以具有:1)一个数据和两个红色节点的子节点; 2)一个数据和两个子节点是黑节点;或3)没有数据,也没有子节点(即叶子节点)。 (这不是对红黑树的精确描述,而是对这项练习有所帮助。)

编写一对相互递归的OCaml数据类型,表示红黑树中的红色节点和黑色节点。数据应该能够具有任何类型,也就是说,您的类型应该是存储在树中的数据类型的多态。

3 个答案:

答案 0 :(得分:4)

type 'a red_node = 'a * ('a black_node * 'a black_node)
and  'a black_node = ('a * ('a node * 'a node)) option
and  'a node =
    Red of 'a red_node
  | Black of 'a black_node

一个表达式,它会告诉你什么类型的节点' n'是,根据您问题的最新更新。

(* to determine if a black node is a type 1 black node *)
match n with
| Black n' ->
    begin match n' with
    | Some n'' ->
        begin match n'' with
        | _, (Red _, Red _) -> "type 1 black node"
        | _, (Black _, Black _) -> "type 2 black node"
        | _ -> raise (Failure "invalid node")
        end
    | None -> "leaf node"
    end
| Red _ -> "red node";;

关于OCaml中类型的语义:OCaml中的类型名称必须始终以小写字母开头(例如listarrayref),但类型构造函数必须以大写字母(例如Some)。该类型是一个涵盖其所有构造函数的伞。

P.S。:我不认为您甚至需要针对此问题的相互递归数据类型。以下应该有效:

type 'a node =
    Red of 'a * ('a node * 'a node)
  | Black of 'a option * ('a node option * 'a node option)

答案 1 :(得分:2)

这是一个错误:

 | TwoRedNodes of 'a * ( 'a RedNode * 'a RedNode )
                            ^^^^^^^      ^^^^^^^

此处RedNode应为类型构造函数,而不是值构造函数。我怀疑,您要再添加一个类型'a red_node并定义您的TwoRedNodes分支,如下所示:

 | TwoRedNodes of 'a * ( 'a red_node * 'a red_node)

答案 2 :(得分:2)

最终,红黑树的一对相互递归数据类型的实现是:

type ’a black_node = Leaf
| RNode of ’a * ’a red_node * ’a red_node
| BNode of ’a * ’a black_node * ’a black_node
and ’a red_node = RedNode of ’a * ’a black_node * ’a black_node;;