Recursion 如何在OCaml中接受没有叶格的递归类型?

Recursion 如何在OCaml中接受没有叶格的递归类型?,recursion,types,ocaml,Recursion,Types,Ocaml,众所周知,OCaml拒绝定义简单的递归类型,例如typet=t->int,而中的Y-combinator示例也不起作用 然而,最近我发现递归类型定义的一些小调整,比如(t->int)的typet=A,效果很好。下面的代码是一些概念验证,用于检查哪一个工作良好 (* OCaml version 4.08.0 *) (* Precisely, ocaml-base-compiler.4.08.0 *) # type t = t -> int;; Error: The type abbrevi

众所周知,OCaml拒绝定义简单的递归类型,例如
typet=t->int
,而中的Y-combinator示例也不起作用

然而,最近我发现递归类型定义的一些小调整,比如(t->int)的
typet=A,效果很好。下面的代码是一些概念验证,用于检查哪一个工作良好

(* OCaml version 4.08.0 *)
(* Precisely, ocaml-base-compiler.4.08.0 *)

# type t = t -> int;;
Error: The type abbreviation t is cyclic

# type t = int -> t;;
Error: The type abbreviation t is cyclic


# type t1 = A of (int -> t1);;
type t1 = A of (int -> t1)

# let v1 = 
    let rec f _ = A f in
    A f;;
val v1 : t1 = A <fun>


# type t2 = B of (t2 -> int);;
type t2 = B of (t2 -> int)

# let v2 =
    let g _ = 3 in
    B g;;
val v2 : t2 = B <fun>


# type t3 = C of (t3 -> t3);;
type t3 = C of (t3 -> t3)

# let v3 = 
    let rec h _ = C h in
    C h;;
val v3 : t3 = C <fun>

(*OCaml版本4.08.0*)
(*准确地说,是ocaml基本编译器.4.08.0*)
#类型t=t->int;;
错误:类型缩写t是循环的
#类型t=int->t;;
错误:类型缩写t是循环的
#类型t1=A的(int->t1);;
类型t1=一个(int->t1)
#设v1=
设rec f u=A f in
A f;;
val v1:t1=A
#类型t2=B的(t2->int);;
类型t2=B(t2->int)
#让v2=
设g=3英寸
B g;;
val v2:t2=B
#t3型=C型(t3->t3);;
类型t3=C(t3->t3)
#设v3=
让rech uch=in
C h;;
val v3:t3=C
我知道该类型可以递归地定义代数数据类型,如
list
tree
类型,但它们都有叶大小写,如
NIL
leaf
构造函数。
t1
t2
t3
都没有叶格,但它们不会被拒绝


我不知道OCaml类型系统如何允许这些类型的定义。您能否解释一下为什么接受
t1
t2
t3
类型,以及如何解释值
v1
v2
v3
的含义?没有叶格的递归类型有什么实际用途吗?

OCaml的早期版本很受欢迎,例如
类型t=t->int
。他们甚至推断出了这一点。问题是,在大多数实际情况下,这种类型只是掩盖了编程错误。因此,根据流行的要求,它们是不允许的,您现在需要一个显式的数据类型。如果在编译器中使用
-rectypes
选项,仍然可以获得旧的行为

这只是一个务实的决定。这些类型没有语义问题,至少在像OCaml这样的语言中没有

数据类型不需要将非递归构造函数作为“叶”情况,只要至少一个构造函数的类型包含不需要定义类型的另一个值的值

比如说,

type 'a list1 = List1 of 'a * 'a list1 option
是表示非空列表的可能类型。这是可行的,因为它包括
List1(x,None)
作为非递归值

从这个意义上讲,函数就是一个类似的例子