我有以下代码(有效):
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)
简而言之,必须在创建引用之前定义引用的类型:您应该能够注释print第一次定义它时的类型.而通过交换的定义a和print,你这最后一点是不可能的:
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)
意味着类型!print会t -> unit导致类似的错误:
错误:此表达式具有类型t但是表达式期望类型为"weak1"类型构造函数t将转义其范围