请考虑以下代码:
module A =
struct
type r = { i : int; s: string }
end
module B =
struct
type r = { i : int; s : string }
end
let f (x : A.r) : B.r = match x with
{ i; s } -> { i = 2*i; s = "" }
Run Code Online (Sandbox Code Playgroud)
两个模块定义完全相同的记录.函数f将A记录转换为B记录.警告已在编译期间发出,但也可以交互显示.在ocaml cli上,似乎对f的调用完成了预期的事情:
# let x = f { i = 5; s = "ab" };;
Characters 10-29:
let x = f { i = 5; s = "ab" };;
^^^^^^^^^^^^^^^^^^^
Warning 40: this record of type Shadow.A.r contains fields that are
not visible in the current scope: i s.
They will not be selected if the type becomes unknown.
val x : Shadow.B.r = {Shadow.B.i = 10; s = ""}
Run Code Online (Sandbox Code Playgroud)
我在lexifi.com上发现了一篇博文,解释了这个问题和一些常见的解决方案.我不明白的是实际的错误信息:
gsg*_*gsg 15
在这种情况下,记录的类型是已知的,因为您提供了注释.如果删除了注释,则类型将变为未知,代码的含义可能会更改.
OCaml的哲学是添加和删除类型注释不应该影响程序的含义,因此会产生警告.
您可以通过将相关字段放入范围来避免此警告.对模块中定义的字段执行此操作A需要打开A以将其内容放入范围,或者使用模块限定字段名称.例如:
module A = struct ... end
let test r = r.A.field
let test2 r = let open A in r.field
open A
let test3 r = r.field
Run Code Online (Sandbox Code Playgroud)