以两种不同的方式编写函数时OCaml的奇怪行为

dzh*_*qjk 2 ocaml types

我有以下代码(有效):

type a = A of int
let print = ref (fun _ -> ())
let f x = !print (A x)
Run Code Online (Sandbox Code Playgroud)

但以下不起作用:

let print = ref (fun _ -> ())
type a = A of int
let f x = !print (A x)
Run Code Online (Sandbox Code Playgroud)

我想知道为什么交换两行导致代码无效.

谢谢 !

编辑:运行第二个代码时,我收到以下错误:

Error: This expression has type a but an expression was expected of type 'a
       The type constructor a would escape its scope
Run Code Online (Sandbox Code Playgroud)

oct*_*ron 8

简而言之,必须在创建引用之前定义引用的类型:您应该能够注释print第一次定义它时的类型.而通过交换的定义aprint,你这最后一点是不可能的:

  let print: ( ??? -> unit) ref  = ref (fun _ -> ())
  type a = A of int
Run Code Online (Sandbox Code Playgroud)

这里???应该是,a但类型a尚未定义.

更确切地说,OCaml中的类型具有范围,以便检测本地类型何时将逃避定义和有意义的上下文.例如

let x =
  let module M = struct type t = A end in
  M.A
Run Code Online (Sandbox Code Playgroud)

失败与第二个示例相同的错误

错误:此表达式具有类型Mt但是表达式需要类型'a类型构造函数Mt将逃避其范围

这里,让类型M.t转义定义的主体x将是坏的,因为模块M和因此类型M.t没有在此定义之外定义.

您的示例因类似原因而失败.变量

let print = ref (fun _ -> ())
Run Code Online (Sandbox Code Playgroud)

具有类型('_weak1 -> unit) ref,其中'_weak1是一个尚未知类型的占位符类型.但是此时参考的未来类型应该已经存在.

因此,当您定义新类型时

type t = A of int
Run Code Online (Sandbox Code Playgroud)

并尝试将此类型分配给'_weak1弱类型变量,

let print': (t -> unit) ref = print
Run Code Online (Sandbox Code Playgroud)

typechecker抱怨创建t类型变量时类型未定义'_weak1:

错误:此表达式具有类型('weak1 - > unit)ref但是表达式需要类型(t - > unit)ref类型构造函数t将转义其范围

同样,你的功能 f

 let f x = !print (A x)
Run Code Online (Sandbox Code Playgroud)

意味着类型!printt -> unit导致类似的错误:

错误:此表达式具有类型t但是表达式期望类型为"weak1"类型构造函数t将转义其范围