Recursion Ocaml自参考

Recursion Ocaml自参考,recursion,ocaml,ref,Recursion,Ocaml,Ref,我已经创建了int*t ref的类型t=Test 如何创建任何类型为t的对象?正如delnan所说,您可以使用循环值: let rec x = Test (0, ref x) 虽然递归通常用于定义函数,但也可以用于某些值。这在一般情况下是不可能的,有一些限制 其思想是该值是堆分配的,因此递归使用它很容易:首先为“Test”构造函数分配空间,然后可以使用分配的构造函数的地址为“x”定义其字段,即使它指向尚未完全定义的值。函数、惰性值、对、记录等都遵循此模式。当然,该规范并不是那么低级(“heap

我已经创建了int*t ref的类型t=Test


如何创建任何类型为t的对象?

正如delnan所说,您可以使用循环值:

let rec x = Test (0, ref x)
虽然递归通常用于定义函数,但也可以用于某些值。这在一般情况下是不可能的,有一些限制

其思想是该值是堆分配的,因此递归使用它很容易:首先为“Test”构造函数分配空间,然后可以使用分配的构造函数的地址为“x”定义其字段,即使它指向尚未完全定义的值。函数、惰性值、对、记录等都遵循此模式。当然,该规范并不是那么低级(“heap allocated”没有在OCaml手册中定义),还有一个稍微严格一些的语法规范

一旦引导了逐值递归,就可以构建更复杂的值:

let rec x = Test (0, ref x)
let y = Test (1, ref x)
let (Test (_, r)) = x in r := y
你也可以直接这样做

let rec x = Test (0, ref y)
and y = Test (1, ref x)
也可以使用由
Obj
产生的“虚拟值”,尽管实际上并不推荐。这就是标准库的
队列
模块的实现方式

此定义的一个问题是,值是循环的。如果您计划对这些值的“尾部”进行迭代,则可能会出现问题。如果您计划使用int字段跟踪结构的“尾部长度”(0表示引用是不应遵循的伪指针),这正是
队列
模块的实现方式

还有其他可能的选择。例如,您可以使用一个模型,其中尾部指针的可空性通过使用选项类型显式设置:

type t' = Test of int * t' option ref

let x = Test (0, ref None)
let y = Test (0, ref (Some x))

let rec length (Test (_, tail)) =
  match !tail with
  | None -> 0
  | Some tl -> 1 + length tl 
在这种情况下,不需要递归来引导类型,
None
就足够了。当然,由于选项类型具有间接性,因此性能成本适中

PS:请注意,对于这种构造函数类型,您最好使用记录类型:

type t = {
  field : int;
  tail : t ref;
 }
让rec x=Test(0,ref x)
似乎可以编译。无论如何,我怀疑这种类型有什么用处。如果您想要类似列表的内容,则需要一个
Nil
构造函数。