Types 为什么我的类型定义在声明为变量时被拒绝为循环,但在其他情况下被接受?
我在使用OCaml实现Chris Okasaki的纯功能数据结构中的一些数据结构时遇到了这种类型定义:Types 为什么我的类型定义在声明为变量时被拒绝为循环,但在其他情况下被接受?,types,functional-programming,ocaml,ml,cyclic,Types,Functional Programming,Ocaml,Ml,Cyclic,我在使用OCaml实现Chris Okasaki的纯功能数据结构中的一些数据结构时遇到了这种类型定义: type tree = Node of int * int * tree list;; 我认为它不需要标记,因为它不是联合类型,所以我尝试删除该标记,但出现以下错误: # type tree = int * int * tree list;; Characters 5-33: type tree = int * int * tree list;; ^^^^^^^^^^^^^^
type tree = Node of int * int * tree list;;
我认为它不需要标记,因为它不是联合类型,所以我尝试删除该标记,但出现以下错误:
# type tree = int * int * tree list;;
Characters 5-33:
type tree = int * int * tree list;;
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Error: The type abbreviation tree is cyclic
为什么两个看似等价的类型定义会出现这种情况?在类似ML的语言中,递归类型的定义是递归不通过变量类型的定义。这是一个实用的定义,因为它倾向于导致更有用的类型检查 递归类型没有什么难办的。您可以使用
-rectypes
标志在OCaml中启用对递归类型的支持
$ ocaml -rectypes
OCaml version 4.02.1
# type tree = int * int * tree list;;
type tree = int * int * tree list
# let x: tree = (3, 3, [(4, 4, [])]);;
val x : tree = (3, 3, [(4, 4, [])])
当启用递归类型时,所有通常的强类型保证都存在。主要的缺点是许多非预期的项目被接受。换句话说,递归类型的存在通常表示编程错误。第一个类型定义定义了新类型。当您省略构造函数名称时,您实际上是在引入类型缩写,而不是定义新类型。默认情况下,类型缩写不允许是递归的,因为这通常不是您的意思 您可以使用定义新类型的任何类型定义语法来创建递归类型,而不仅仅是变量。例如,记录也会起作用
type tree = { node : int * int * tree list }
甚至更好
type tree = {
value : int;
depth : int;
children : tree list;
}
(注意:字段名是任意选择的,因为我不知道它们的原始用途)
总之,sum类型不仅用于引入不相交的类型集,还用于创建新类型,因此:
type t = Constr x
介绍了类型
t
,它可以用构造函数Constr
从类型x
的值构造,我对ocaml一无所知,但是如果没有的节点,所讨论的类型是否意味着“一个int、一个int和一棵树”,这意味着它的大小未知?在.NET(我效忠的框架)中,这将被称为“结构”。基本上,每棵树都是两个整数+一棵树,这棵树的大小是未知的,除非允许允许空指针的指针(或者在ocaml中调用的任何指针)?我的一个朋友刚刚告诉我,这是由于ML试图完全扩展第二棵树,而只键入第一棵树创建的检查值造成的。因为在第一种情况下,程序员有责任创建终止的值。问题不应该是:为什么我的类型定义在声明为变量时被接受,而在声明为变量时被拒绝?