好像我做不到。
我想明白为什么我不能。
我肯定可以type 'a entry = Empty | Value of string * 'a * 'a entry;;
,所以如果我想递归定义一个类型,我只能走union
路线吗?
好像我做不到。
我想明白为什么我不能。
我肯定可以type 'a entry = Empty | Value of string * 'a * 'a entry;;
,所以如果我想递归定义一个类型,我只能走union
路线吗?
您的问题令人困惑,因为它只提到了您不想使用的类型!但是,我从您的标题中看到您想使用直接递归类型。
如果要直接递归类型,需要-rectypes
在命令行开启。然而,这并不是你大多数时候真正想做的事情。它允许太多真正不是您想要的类型。
$ ocaml
OCaml version 4.00.0
# type 'a entry = string * 'a * 'a entry;;
Error: The type abbreviation entry is cyclic
# ^D
$ ocaml -rectypes
OCaml version 4.00.0
# type 'a entry = string * 'a * 'a entry;;
type 'a entry = string * 'a * 'a entry
#
默认情况下未启用的原因-rectypes
是它允许将类型赋予许多实际上是编码错误的表达式。总的来说,额外的灵活性不值得放弃额外的错误检测。
这是我在旧的 OCaml 邮件列表消息中找到的示例:
$ ocaml -rectypes
OCaml version 4.00.0
# let f x = x :: x;;
val f : ('a list as 'a) -> 'a list = <fun>
#
-rectypes
打开后,这个相当荒谬的功能就被接受了。但实际上它只适用于相当奇怪的列表类型。程序员很可能打算使用@
而不是::
. 不幸的是,直到很久以后才会检测到此错误-rectypes
。
作为旁注,正如 newacct 指出的那样,您可能很快就会发现标题中的类型不是那么有用。它实际上只能表示循环或无限结构。这是另一个工作不-rectypes
那么困难的原因。
当你这样做时type something = another type
,你正在做一个类型同义词,就像typedef
C 中的 a 一样。它创建了一个别名,你可以将其用作引用另一种类型的快捷方式。它本身并没有定义新的类型。因此,它不能是递归的。
当你这样做时type something = SomeContructor of ...
,它定义了一个新的代数数据类型。这可以是递归的。
(Haskell 和 SML 对此更清楚;他们使用type
类型同义词和data
(Haskell)/ datatype
(SML) 来定义新的代数数据类型。)
代数数据类型不一定需要有多个替代项。它在语法上是有效的
type 'a entry = Value of string * 'a * 'a entry
但是,在这种情况下,这可能没有用,因为,它怎么会结束呢?