如何强制OCaml中的对象参数

如何强制OCaml中的对象参数,ocaml,Ocaml,我一直在玩弄OCaml对象系统,并且通常都会键入。最近,我一直在玩多态变量和对象,我遇到了一些麻烦,让类型系统做我想要的 这是我的工作成果,很有意义 给定一些类型和函数定义: type variant1 = [`Type1 | `Type2] type variant2 = [`Type1 | `Type3] type func1 = variant1 -> unit type func2 = variant2 -> unit let f1 : func1 = fun _ ->

我一直在玩弄OCaml对象系统,并且通常都会键入。最近,我一直在玩多态变量和对象,我遇到了一些麻烦,让类型系统做我想要的

这是我的工作成果,很有意义

给定一些类型和函数定义:

type variant1 = [`Type1 | `Type2]
type variant2 = [`Type1 | `Type3]
type func1 = variant1 -> unit
type func2 = variant2 -> unit
let f1 : func1 = fun _ -> ()
let f2 : func2 = fun _ -> ()

(* Fails, but makes sense *)
let f3 : [`Type1] -> unit = f1
(* Error: This expression has type func1 = [ `Type1 | `Type2 ] -> unit
   but an expression was expected of type [ `Type1 ] -> unit
   The second variant type does not allow tag(s) `Type2 *)

(* Works, and is what I'd expect *)
let f3 : [`Type1] -> unit = (f1 : [`Type1] -> unit)
到目前为止,这是有道理的,任何可以接受`Type1+`Type2的函数都应该能够在只需要`Type1'的地方使用。这主要适用于对象:

type obj1 = < f : variant1 -> unit >
type obj2 = < f : variant2 -> unit >
type obj3 = < f : [`Type1] -> unit >
let o1 : obj1 = object method f = f1 end
let o2 : obj2 = object method f = f2 end
let o3 : obj3 = o1 (* Fails *)
let o3 : obj3 = (o1 :> obj3) (* Works *)
但是,当对象类型具有需要强制的方法参数时,情况就不一样了,我不知道如何说服编译器进行转换:

type obj1 = < f : (variant1 -> unit) -> unit >
type obj2 = < f : ([`Type1] -> unit) -> unit >
let o1 : obj1 = object method f p = () end
let o2 : obj2 = (o1 :> obj2) (* Fails *)

Error: Type obj1 = < f : func1 -> unit > is not a subtype of
     obj2 = < f : ([ `Type1 ] -> unit) -> unit > 
   Type [ `Type1 ] -> unit is not a subtype of
     func1 = [ `Type1 | `Type2 ] -> unit 
   The second variant type does not allow tag(s) `Type2

在我看来,将obj1类型强制为obj2类型仍然有效。这是正确的吗?这可能吗?也许我误解了什么?

您的问题是子类型关系的方向相反:

 let obj2 : obj2 = object method f p = p `Type1 end 
 let o3 = (o2 : obj2 :> obj1);;
因为函数的参数是相反的

理解为什么,例如考虑Obj1:0/P>类型的这个具体值


如果我能发送一个不能处理'Type2'的函数给o1,它就会失败。因此,obj1不是obj2的子类型。相反,obj2类型的对象承诺只使用'Type1'上的函数参数,因此将它们用作obj1并不成问题,因为它们始终会收到可以处理'Type1'以上的函数参数。

您的问题是子类型关系的方向相反:

 let obj2 : obj2 = object method f p = p `Type1 end 
 let o3 = (o2 : obj2 :> obj1);;
因为函数的参数是相反的

理解为什么,例如考虑Obj1:0/P>类型的这个具体值


如果我能发送一个不能处理'Type2'的函数给o1,它就会失败。因此,obj1不是obj2的子类型。相反,obj2类型的对象承诺只使用'Type1'上的函数参数,因此将它们用作obj1并没有问题,因为它们将始终接收可以处理'Type1'以上的函数参数。

Ah!我现在明白了。非常感谢。啊!!我现在明白了。非常感谢。