开放对象类型统一得太早
Open object type gets unified too soon
我有一个处理大量计算的大 let
块,我试图通过将它的块分解成函数来将它分解成更小的部分。我需要将一个对打开的对象进行操作的函数传递给这些组件,并且 运行 变成了以下简化代码中最能表达的烦恼:
type 'a foo = 'a
constraint 'a = < bar: string option; .. >
type foo' = < bar: string option; >
type bar = < bar: int option; qux: int option >
type ('a, 'b) fn = 'a foo -> 'b foo
let a = object method bar = None method qux = None end
let b = object method bar = None end
(* Doesn't work *)
let xyz fn =
let res = fn a in
let res' = fn b in
res, res'
(* Doesn't work *)
let xyz (fn:('a, 'b) fn) =
let res = fn a in
let res' = fn b in
res, res'
(* Doesn't work *)
type fn' = foo' -> foo'
let xyz (fn:fn') =
let res = fn a in
let res' = fn b in
res, res'
(* Sub-par solution: imagine needing several of these conversions across several
functions, which is the situation I have when trying to decompose a large let
block into component functions like xyz. *)
let xyz (fn:('a, 'b) fn) =
let res = fn (a :> foo') in
let res' = fn b in
res, res'
(* Another sub-par solution: *)
type ('a, 'b) fn'' = { fn: 'a. 'a foo -> 'b foo }
let xyz (fn:('a, 'b) fn'') =
let fn = fn.fn in
let res = fn a in
let res' = fn b in
res, res'
(* What I want: *)
type ('a, 'b) fn''' = 'a. 'a foo -> 'b foo
let xyz (fn:('a, 'b) fn''') =
let res = fn a in
let res' = fn b in
res, res'
(* What I am currently using (don't pass the function around to HOFs: keep the
computation all in a massive let statement. *)
let _ =
let a : foo = object method bar = None method qux = None end in
let b : bar = object method bar = None end in
let fn a = object method bar = a#bar method qux = None end in
(* fn gets the correctly inferred type of < bar : 'a; .. > -> < bar : 'a; qux : 'b option > *)
fn a, fn b
关于为什么我想要的任何指导或理由 impossible/assurance 确实有可能 now/promises 有一天——在一个更光明的世界里——这会奏效,会很重要赞赏。
你想要的是在定义中多态地使用函数参数:即将 fn
应用于 xyz
中不同对象类型的两个值。这称为 Rank-2 多态性 (https://wiki.haskell.org/Rank-N_types),但在 Hindley Milner 类型系统中不受支持(它只能处理 Rank-1)。 OCaml 基于 Hindley Milner,也不直接支持 Rank-N。
目前 OCaml 对 Rank-2 多态性的支持是非常间接的:通过多态记录成员模拟,没有任何类型推断。我猜你的 "Another sub-par solution" 是最好的方法。
我有一个处理大量计算的大 let
块,我试图通过将它的块分解成函数来将它分解成更小的部分。我需要将一个对打开的对象进行操作的函数传递给这些组件,并且 运行 变成了以下简化代码中最能表达的烦恼:
type 'a foo = 'a
constraint 'a = < bar: string option; .. >
type foo' = < bar: string option; >
type bar = < bar: int option; qux: int option >
type ('a, 'b) fn = 'a foo -> 'b foo
let a = object method bar = None method qux = None end
let b = object method bar = None end
(* Doesn't work *)
let xyz fn =
let res = fn a in
let res' = fn b in
res, res'
(* Doesn't work *)
let xyz (fn:('a, 'b) fn) =
let res = fn a in
let res' = fn b in
res, res'
(* Doesn't work *)
type fn' = foo' -> foo'
let xyz (fn:fn') =
let res = fn a in
let res' = fn b in
res, res'
(* Sub-par solution: imagine needing several of these conversions across several
functions, which is the situation I have when trying to decompose a large let
block into component functions like xyz. *)
let xyz (fn:('a, 'b) fn) =
let res = fn (a :> foo') in
let res' = fn b in
res, res'
(* Another sub-par solution: *)
type ('a, 'b) fn'' = { fn: 'a. 'a foo -> 'b foo }
let xyz (fn:('a, 'b) fn'') =
let fn = fn.fn in
let res = fn a in
let res' = fn b in
res, res'
(* What I want: *)
type ('a, 'b) fn''' = 'a. 'a foo -> 'b foo
let xyz (fn:('a, 'b) fn''') =
let res = fn a in
let res' = fn b in
res, res'
(* What I am currently using (don't pass the function around to HOFs: keep the
computation all in a massive let statement. *)
let _ =
let a : foo = object method bar = None method qux = None end in
let b : bar = object method bar = None end in
let fn a = object method bar = a#bar method qux = None end in
(* fn gets the correctly inferred type of < bar : 'a; .. > -> < bar : 'a; qux : 'b option > *)
fn a, fn b
关于为什么我想要的任何指导或理由 impossible/assurance 确实有可能 now/promises 有一天——在一个更光明的世界里——这会奏效,会很重要赞赏。
你想要的是在定义中多态地使用函数参数:即将 fn
应用于 xyz
中不同对象类型的两个值。这称为 Rank-2 多态性 (https://wiki.haskell.org/Rank-N_types),但在 Hindley Milner 类型系统中不受支持(它只能处理 Rank-1)。 OCaml 基于 Hindley Milner,也不直接支持 Rank-N。
目前 OCaml 对 Rank-2 多态性的支持是非常间接的:通过多态记录成员模拟,没有任何类型推断。我猜你的 "Another sub-par solution" 是最好的方法。