数据中的<周期>是什么?

let*_*rec 4 evaluation ocaml

(我使用OCaml版本4.02.3)

我定义了一个类型 self

# type self = Self of self;;
type self = Self of self 
Run Code Online (Sandbox Code Playgroud)

及其实例 s

# let rec s = Self s;;
val s : self = Self <cycle>
Run Code Online (Sandbox Code Playgroud)

由于OCaml是一种严格的语言,我希望定义s会陷入无限递归。但是口译员说s确实有价值Self <cycle>

我还将一个功能应用于s

# let f (s: self) = 1;;
val f : self -> int = <fun> 
# f s;;
- : int = 1 
Run Code Online (Sandbox Code Playgroud)

似乎s未在函数应用程序之前进行评估(例如使用非严格语言)。

OCaml如何处理像循环数据sSelf <cycle>是正常形式吗?

oct*_*ron 5

OCaml确实是一种渴望的语言,但是它s是一个完全有效且经过充分评估的术语,恰好包含一个循环。例如,此代码产生预期的结果:

let f (Self Self x) = x
f s == s;; 
Run Code Online (Sandbox Code Playgroud)

更准确地说,将具有n个参数的构造函数的内存表示形式装箱,并按以下方式读取:

?—————————————————————————————————————————————?
| header | field[0] | field[1] | ? | fiekd[n] |
?—————————————————————————————————————————————?
Run Code Online (Sandbox Code Playgroud)

标头包含元数据,而field[k]OMACl值是OCaml值,即整数或指针。在的情况下sSelf只有一个参数,因此只有一个字段field[0]。然后,值field[0]仅仅是指向块开始的指针。s因此,该术语在OCaml中可以完美地表示。

此外,顶级打印机能够检测到此类循环并打印,<cycle>以避免在打印的值时陷入无限递归s。在这里,<cycle><abstr>或一样<fun>,只是顶级打印机无法打印的一种值。

但是请注意,在许多情况下,循环值将触发无限递归,例如f s = s(=)结构相等而不是物理等式(i.e. (==))触发这种递归的情况下,另一个示例是

let rec ones = 1 :: ones;; (* prints [1;<cycle>] *)
let twos = List.map ((+) 1) ones;; (* falls in an infinite recursion *)
Run Code Online (Sandbox Code Playgroud)

  • &lt;cycle&gt;的打印仅是顶级打印机的功能,它确实是4.02中引入的(请参阅https://caml.inria.fr/mantis/view.php?id=6228)。但是,可以从OCaml 1.0开始定义循环值(请参见http://caml.inria.fr/pub/docs/manual-ocaml-4.04/extn.html#sec217);但是,Try Ocaml可能在使用此类值时会遇到一些困难。 (2认同)