`let` 从 ocaml 中的记录中进行双关语
`let` field punning from records in ocaml
非常微不足道的问题,但这是否有效
type rtype = { field : int }
let r : rtype = assert false
let _ = r |> fun { field } -> 0
let _ = let { field } = r in 0
而这不会
module type rsig = sig
type r = { somefield : 'a. 'a -> int }
val inj : r
end
module R : rsig = struct
type r = { somefield : 'a. 'a -> int }
let inj : r = { somefield = (fun _ -> 0) }
end
let _ = R.inj |> fun { somefield } -> 0
let _ = let { somefield } = R.inj in 0 (* Unbound record field somefield *)
不是因为 let 双关,而是因为类型驱动 record field names disambiguation。它不是主要的,甚至会有警告告诉您您的代码取决于它的存在。在第一种情况下,类型检查器从应用程序中推断出函数的类型。在第二种情况下,它没有信息类型来推断 somefield
来自模块 R
1.
在OCaml中,字段名是在模块的命名空间中定义的,所以最好明确指定模块名,例如
let _ = let { R.somefield} = R.inj in 0
或者,您可以限制类型以确保类型检查器在消除记录名称歧义时知道类型,例如,
let {somefield} : R.r = R.inj in 0
或者,
let foo : R.r -> unit = function {somefield} -> ()
1)在第二种情况下,let {somefield} = R.inj in 0
类型检查器从左侧开始推理,并且还不知道右侧具有类型 R.r
,如果您将代码重写为 let r = R.inj in r.somefield; 0
,它将计算出 somefield
来自 R
.
非常微不足道的问题,但这是否有效
type rtype = { field : int }
let r : rtype = assert false
let _ = r |> fun { field } -> 0
let _ = let { field } = r in 0
而这不会
module type rsig = sig
type r = { somefield : 'a. 'a -> int }
val inj : r
end
module R : rsig = struct
type r = { somefield : 'a. 'a -> int }
let inj : r = { somefield = (fun _ -> 0) }
end
let _ = R.inj |> fun { somefield } -> 0
let _ = let { somefield } = R.inj in 0 (* Unbound record field somefield *)
不是因为 let 双关,而是因为类型驱动 record field names disambiguation。它不是主要的,甚至会有警告告诉您您的代码取决于它的存在。在第一种情况下,类型检查器从应用程序中推断出函数的类型。在第二种情况下,它没有信息类型来推断 somefield
来自模块 R
1.
在OCaml中,字段名是在模块的命名空间中定义的,所以最好明确指定模块名,例如
let _ = let { R.somefield} = R.inj in 0
或者,您可以限制类型以确保类型检查器在消除记录名称歧义时知道类型,例如,
let {somefield} : R.r = R.inj in 0
或者,
let foo : R.r -> unit = function {somefield} -> ()
1)在第二种情况下,let {somefield} = R.inj in 0
类型检查器从左侧开始推理,并且还不知道右侧具有类型 R.r
,如果您将代码重写为 let r = R.inj in r.somefield; 0
,它将计算出 somefield
来自 R
.