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

标签 types ocaml

我有以下代码(有效):

type a = A of int
let print = ref (fun _ -> ())
let f x = !print (A x)

但是以下不起作用:

let print = ref (fun _ -> ())
type a = A of int
let f x = !print (A x)

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

谢谢!

编辑:运行第二个代码时出现以下错误:

Error: This expression has type a but an expression was expected of type 'a
       The type constructor a would escape its scope

最佳答案

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

  let print: ( ??? -> unit) ref  = ref (fun _ -> ())
  type a = A of int

这里,???应该是a,但是类型a还没有定义。

更准确地说,OCaml 中的类型有一个范围,以便检测本地类型何时会脱离其定义和有意义的上下文。例如

let x =
  let module M = struct type t = A end in
  M.A

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

Error: This expression has type M.t but an expression was expected of type 'a The type constructor M.t would escape its scope

在这里,让类型 M.t 转义 x 的定义主体是不好的,因为模块 M 和类型 M.t 未在此定义之外定义。

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

let print = ref (fun _ -> ())

具有类型 ('_weak1 -> unit) ref 其中 '_weak1 是一个未知类型的占位符类型。但是此时引用的 future 类型应该已经存在。

因此,当您定义新类型时

type t = A of int

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

let print': (t -> unit) ref = print

类型检查器在创建类型变量 '_weak1 时提示类型 t 未定义:

Error: This expression has type ('weak1 -> unit) ref but an expression was expected of type (t -> unit) ref The type constructor t would escape its scope

同样,您的函数 f

 let f x = !print (A x)

暗示 !print 的类型将是 t -> unit 并导致类似的错误:

Error: This expression has type t but an expression was expected of type 'weak1 The type constructor t would escape its scope

关于types - 以两种不同方式编写函数时 OCaml 的奇怪行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54856059/

相关文章:

types - isize 和 usize 的可用性如何,为什么它们有利于索引?

types - ocaml 类型构造函数参数

html - 在 OCaml 中读取 URL 的 HTML 内容

arrays - 从数组元素创建列表,生成数字序列

python - Numpy 舍入性能

c# - 需要协变返回类型和 "real"类方差的 Scala 语言如何在 CLR 上运行?

types - 为什么 Rust 有一个 "Never"原始类型?

c++ - 如果 : char x = short y in c++ 会发生什么

gcc - 去掉cpp生成的注释

haskell - 扩大 ocaml 中的类型