Types 开放对象类型太快得到统一

Types 开放对象类型太快得到统一,types,ocaml,Types,Ocaml,我有一个大的let块,它处理大量的计算,我正试图通过将块分解成函数将其分解成更小的块。我需要将一个在开放对象上运行的函数传递给这些组件,我遇到的麻烦最好用下面的简化代码表示: type 'a foo = 'a constraint 'a = < bar: string option; .. > type foo' = < bar: string option; > type bar = < bar: int option; qux: int option &

我有一个大的
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
键入'a foo='a
约束'a=
键入foo'=
输入bar=
类型('a,'b)fn='a foo->'b foo
设a=对象方法bar=无方法qux=无结束
设b=对象方法条=无端点
(*不起作用*)
让xyz fn=
设res=fn a in
设res'=fnb为in
res,res'
(*不起作用*)
设xyz(fn:('a,'b)fn)=
设res=fn a in
设res'=fnb为in
res,res'
(*不起作用*)
类型fn'=foo'->foo'
设xyz(fn:fn')=
设res=fn a in
设res'=fnb为in
res,res'
(*低于标准的解决方案:想象一下需要跨多个应用程序进行多个转换
函数,这是我在尝试分解大型let时遇到的情况
块到组件函数中,如xyz.*)
设xyz(fn:('a,'b)fn)=
让res=fn(a:>foo')在
设res'=fnb为in
res,res'
(*另一个低于标准的解决方案:)
类型('a,'b)fn'={fn:'a.'a foo->'b foo}
设xyz(fn:('a,'b)fn')=
设fn=fn.fn为in
设res=fn a in
设res'=fnb为in
res,res'
(*我想要的:)
类型('a,'b)fn'='a.'阿福->阿福
设xyz(fn:('a,'b)fn')=
设res=fn a in
设res'=fnb为in
res,res'
(*我当前使用的(不要将函数传递给HOFs:保留
计算全部在大规模let语句中。*)
让我们=
设a:foo=object方法bar=None方法qux=None结束于
设b:bar=object方法bar=None结束于
设fn a=对象方法bar=a#bar方法qux=None结束于
(*fn获取正确推断的->*)
fn a,fn b

任何关于我想要的东西不可能实现的指导,或者仅仅是理由/保证现在确实可以实现/承诺有一天在一个更光明的世界中这会起作用,我们都将不胜感激。

您想要的是在定义中多形地使用函数参数:即将
fn
应用于两个不同的值
xyz
中的对象类型。这称为秩-2多态性(),但在Hindley-Milner类型系统中不受支持(它只能处理秩-1)。OCaml基于Hindley-Milner,也不直接支持秩-N


目前OCaml对秩-2多态性的支持非常间接:通过多态记录成员进行模拟,没有任何类型推断。我想您的“另一个低于标准的解决方案”是最好的方法。

感谢您的回答和对秩-N类型的引用。为什么类型推断在函数内部有效(最后一个示例),或包装在记录类型中(我的“另一个低于标准的解决方案”)?当它只是一个顶级函数时不起作用,在对象中也不起作用(
'b foo>
)。此外,您知道OCaml是否支持类似的内容吗?最后(感谢您的支持),如果您在这种情况下,您会将函数包装为记录类型吗?最后一个示例之所以有效,是因为它不需要秩-2多义:您不会将
fn
传递给HOF。在“另一个低于标准的解决方案”中没有魔力,您可以自己在多态记录类型定义中给出多态类型,这是OCaml的类型系统无法推断的。
type'b fn''u by_object='b foo>;让xyz(fn:'b fn''u by_object)=fn#fn a,fn#fn b
可以正常工作。您可以在谷歌上搜索“OCaml排名2多态性”看看一些文献。是的,如果我需要模拟排名2,我使用多态记录字段。