什么时候应该在OCaml中使用对象? [英] When should objects be used in OCaml?

查看:68
本文介绍了什么时候应该在OCaml中使用对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

通常,可以在有或没有对象的情况下编写OCaml程序.什么时候使用对象最有益,什么时候应该避免使用它们?

Usually, an OCaml program can be written with or without objects. When is it most beneficial to use objects, and when should they be avoided?

推荐答案

一般而言,请勿使用对象.他们带来的额外复杂性并不那么值得.我认为这也是一条适用于其他语言的规则,但这是另一回事了.至少使用OCaml可以客观地(无双关语)说,通常的做法是除非极少数情况下不使用对象.

As a general rule of thumb, don't use objects. The additional complexity they bring in is not that often worth it. I think that's a rule that apply to other languages as well, but that's another story. At least with OCaml one can objectively (no pun intended) say that the common practice is to not use object except in rare cases.

对象提供了以下内容的捆绑包:

Object provide a bundle of:

  1. 用于携带和使用函数记录(可能是多态类型)的标准"样式
  2. 通过self(实现继承)进行开放递归的工具
  3. 具有行多态性(对于开放对象类型)和子类型(对于封闭对象类型)的结构化,可扩展产品类型
  1. A "standard" style for carrying around and using records of functions, with possibly polymorphic types
  2. Facilities for open recursion through self (implementation inheritance)
  3. A structural, extensible product type with row polymorphism (for open object types) and subtyping (for closed object types)

您可以将它们中的任何一个一起使用,也可以单独使用.

You may use any of those together, or separately.

根据我的经验,仅使用点(1)并不是特别值得使用对象:您可以仅使用函数记录,而且也很清楚.

In my experience, point (1) alone is not particularly worth using objects: you can just use records of functions and it is just as clear.

相反,第(2)点是使用面向对象样式的很好理由;例如,Camlp4会以这种方式使用它:Camlp4定义了不进行AST折叠的类,并且您可以继承此遍历对象以仅在所需的语法构造上实现所需的行为(并将无聊的遍历处理延迟到你的妈妈班).

Point (2) on the contrary is a good justification for using an object-oriented style; it is used in this manner by Camlp4 for example: Camlp4 defines classes that fold over an AST doing nothing, and you can inherit this traversal object to implement the behavior you want on only the syntactic constructions you want (and defer the boring traversal plumbing to your mother class).

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

For example, one may extend the Camlp4Ast.map object, that defines a simple map function on the Camlp4 representation of the OCaml Abstract Syntax Trees, just mapping every construct to itself, recursively. If you want to, say, map all (fun x -> e1) e2 expressions to let x = e2 in e1, you inherit from this object, and override the expr method, handling only the case you want (left-hand-side is a function), delegating the other to the inherited behavior. This will give you an object that knows how to apply this transform over a complete program, recursively, without you having to write any boilerplate code; and you can further extend this transformation with additional behavior if you so wish.

第(3)点也是使用对象作为可扩展记录"或类型级数组"的理由;有些库使用对象 types ,但在运行时不使用对象:它们将对象类型用作幻像类型来携带信息,这得益于您可以对对象进行的丰富的类型级操作.此外,结构化类型允许不同的作者具有兼容的类型,而不必依赖于定义他们共享的(名义)类型的通用组件.对象已用于例如输入/输出组件的标准化.

Point (3) is also a justification for using objects as "extensible records", or as "type-level arrays"; some libraries using object types, but not object at runtime: they use object types as phantom types to carry around information, benefiting from the richer type-level operations you can have on objects. Besides, structural typing allow for different authors to have compatible types without strong dependencies to a common component defining the (nominal) types they share; objects have been used for standardization of input/output components for example.

一个不常见,非常简单的用例是一种惯用的方式来表示具有很多参数的类型.而不是写:

A not-uncommon, very simple use case of this is an idiomatic way to represent types that have a lot of parameters. Instead of writing:

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

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

you can use object types as structural "type-level records" to write instead:

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

要更高级地将对象类型用作幻像类型,可以查看 doc )库( Alec Heller和Jesse Tov或我自己的猕猴库(文档 api doc ),它使用对象类型表示SQL值(包括可空性信息)和表行类型.
多态变体(OCaml类型系统的另一个高级功能;在句子中,对象与记录之间的关系与多态变体与代数和类型之间的关系相同)也已用作幻像类型,例如 ,或检查 Ocsigen 框架.

For the more advanced use of object types as phantom types, you can have a look at the ShCaml (doc) library (where it is used to represent which shell commands a string input is compatible with) by Alec Heller and Jesse Tov, or my own Macaque library (doc and api doc), which uses object types to represent SQL values (including nullability information) and table row types.
Polymorphic variants (another advanced feature of OCaml type system; in a sentence, the relation between objects and records is the same as the relation between polymorphic variants and algebraic sum types).have also been used as phantom types, for example in this simple example by Richard Jones, or to check validity of HTML documents in the Ocsigen framework.

但是请注意,那些高级类型的骇客要付出巨大的复杂性代价;在使用它们之前,您必须仔细权衡它们与它们带来的额外表现力和静态安全性.

Beware however that those advanced type hackeries come at a significant complexity cost; before using them, you must carefully balance it with the additional expressivity and static safety that they bring.

  • 作为基本假设,您完全不使用任何对象都是安全的.仅当您感觉缺少某些东西时才应在设计中引入它们,而不是默认情况下

  • as a base assumption, you're safe with not using objects at all; you should only introduce them in your design if you feel you're missing something, not by default

对象对于打开递归/继承很方便:完善默认/无聊情况下已经定义的行为

objects are convenient for open recursion / inheritance: refining a behavior that is already defined in the default/boring cases

当您要根据独立提供一组功能/容量的值进行推理时,结构化键入有时会很有用

structural typing is occasionally useful when you want to reason on values independently providing a set of features/capacities

这篇关于什么时候应该在OCaml中使用对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆