什么时候应该在 OCaml 中使用对象?

2024-01-09

通常,OCaml 程序可以使用或不使用对象来编写。什么时候使用物品最有利,什么时候应该避免使用物品?


作为一般经验法则,不要使用对象。它们带来的额外复杂性通常并不值得。我认为这也是适用于其他语言的规则,但那是另一回事了。至少对于 OCaml,人们可以客观地(没有双关语)说,除了极少数情况之外,常见的做法是不使用对象。

对象提供了一系列:

  1. 用于携带和使用函数记录的“标准”样式,可能具有多态类型
  2. 通过以下方式进行开放递归的设施self(实现继承)
  3. 具有行多态性(对于开放对象类型)和子类型(对于封闭对象类型)的结构性、可扩展的产品类型

您可以一起使用其中任何一个,也可以单独使用。

根据我的经验,仅第(1)点并不是特别值得使用对象:您可以只使用函数记录,并且它同样清晰。

开放式递归/继承的用例

相反,第 (2) 点是使用面向对象风格的一个很好的理由; Camlp4 就以这种方式使用它,例如:Camlp4 定义了不执行任何操作的 AST 折叠类,并且您可以继承此遍历对象以仅在您想要的语法结构上实现您想要的行为(并将无聊的遍历管道推迟到你的妈妈班)。

例如,可以扩展Camlp4Ast.map https://github.com/ocaml/camlp4/blob/trunk/camlp4/Camlp4/Sig.ml#L264-L316对象,它在 OCaml 抽象语法树的 Camlp4 表示上定义了一个简单的映射函数,只是递归地将每个构造映射到其自身。如果你想映射所有(fun x -> e1) e2表达式到let x = e2 in e1,您从该对象继承,并覆盖expr方法,仅处理您想要的情况(左侧是一个函数),将其他情况委托给继承的行为。这将为您提供一个对象,该对象知道如何在完整的程序中递归地应用此转换,而无需编写任何样板代码;如果您愿意,您可以通过其他行为进一步扩展此转换。

对象类型的乐趣

第 (3) 点也是使用对象作为“可扩展记录”或“类型级数组”的理由;一些使用对象的库types,但不是运行时的对象:它们使用对象类型作为幻像类型来携带信息,从而受益于可以对对象进行的更丰富的类型级操作。此外,结构类型允许不同的作者拥有兼容的类型,而无需强烈依赖于定义他们共享的(名义)类型的公共组件;例如,对象已用于输入/输出组件的标准化。

一个并不罕见且非常简单的用例是表示具有大量参数的类型的惯用方式。而不是写:

type ('name, 'addr, 'job, 'id) person = ....
val me : (string, string, Job.t, Big_int.big_int) person

您可以使用对象类型作为结构“类型级记录”来编写:

type 'a person = .... constraint 'a = < name:'n; addr:'a; job:'j; id:'i >
val me : < name:string; addr:string; job:Job.t; id:Big_int.big_int > person

对于对象类型作为幻像类型的更高级使用,您可以查看ShCaml http://www.eecs.harvard.edu/%7Etov/code/shcaml/ (doc http://www.eecs.harvard.edu/%7Etov/code/shcaml/doc/) 库(用于表示字符串输入与哪些 shell 命令兼容)由 Alec Heller 和 Jesse Tov 或我自己的库Macaque http://macaque.forge.ocamlcore.org/图书馆 (doc http://darcs.ocamlcore.org/cgi-bin/darcsweb.cgi?r=macaque;a=headblob;f=/README and api doc http://darcs.ocamlcore.org/cgi-bin/darcsweb.cgi?r=macaque;a=headblob;f=/src/sql.mli),它使用对象类型来表示 SQL 值(包括可为空性信息)和表行类型。
多态变体(OCaml 类型系统的另一个高级功能;在一个句子中,对象和记录之间的关系与多态变体和代数和类型之间的关系相同)。也被用作幻像类型,例如在这个简单的例子中 http://camltastic.blogspot.fr/2008/05/phantom-types.html作者:Richard Jones,或检查 HTML 文档的有效性Ocsigen http://ocsigen.org/tyxml/api/HTML5_sigs.T框架。

但请注意,这些高级类型的黑客攻击会带来巨大的复杂性成本;在使用它们之前,您必须仔细平衡其与它们带来的额外表现力和静态安全性。

加起来

  • 作为一个基本假设,你根本不使用对象是安全的;只有当您觉得缺少某些东西时,才应该在设计中引入它们,而不是默认情况下

  • 对象对于开放式递归/继承很方便:改进默认/无聊情况下已经定义的行为

  • 当您想要独立地推理值并提供一组功能/功能时,结构类型有时会很有用

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

什么时候应该在 OCaml 中使用对象? 的相关文章

随机推荐