ocaml - 如何在 OCaml 中强制对象参数
问题描述
我一直在玩 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);;
因为函数相对于它们的论点是逆变的。
要了解原因,请考虑例如 type 的这个特定值obj1
:
let o1 : obj1 = object method f p = p `Type1; p `Type2 end;;
如果我可以发送一个无法处理的函数,`Type2
它将o1
失败。因此,obj1
不是 的子类型obj2
。相反,对象类型obj2
承诺只在 上使用函数参数`Type1
,因此将它们用作 没有问题obj1
,因为它们总是会收到可以处理超过 的函数参数`Type1
。
推荐阅读
- shell - Shell使用&符号从字符串执行多个命令(后台进程)
- java - 未来取消不适用于多个线程的 executorService
- amazon-web-services - AWS CORS 启用 - 需要在哪里启用?圣杯?动态数据库?还是S3?
- javafx - 如何定义滚动窗格的值?
- obd-ii - 需要有关 OBD 扫描仪的信息
- android - Android,无法转换为 Fragment
- java - Android Studio 3 的代理问题
- symfony - 学说复合键和一对多
- android - 使用架构组件构建的应用程序是否使其成为“MVVM”,如果是,应用程序的哪些部分与 MVVM 的哪一层相关?
- android - 在特定日期之后设置每周警报