|Anonymous | Login | Signup for a new account||2014-03-10 08:51 CET|
|Main | My View | View Issues | Change Log | Roadmap|
|View Issue Details|
|ID||Project||Category||View Status||Date Submitted||Last Update|
|0005584||OCaml||OCaml general||public||2012-04-11 23:09||2014-02-27 18:01|
|Target Version||Fixed in Version|
|Summary||0005584: Open Extensible Types|
OCaml already has one open extensible type (exn), it would be useful to extend this and allow abstract types to be declared open.
This could be particularly useful when combined with GADTs.
open type foo
extend foo with Constr of int
open type 'a bar
extend _ bar with Gadt1: int bar
extend char bar with Gadt2
I've attached a patch (tested with revision 12270) and more details can be found at:
Note that this patch does not yet add these extensions to the camlp4 parser, and may break existing camlp4 code.
|Attached Files|| extension.patch-1.0.2 [^] (289,214 bytes) 2012-04-11 23:09|
extension.patch-2.0.0 [^] (203,216 bytes) 2012-05-18 13:11
extension.patch-3.0.0 [^] (305,465 bytes) 2014-02-27 17:54
edited on: 2012-04-12 20:06
I like the proposal very much, but I'm not so fond of the proposed syntax.
1. "open type foo" seems to indicate that one wants to open the type foo. For instance, if foo had been declared as a record type (e.g. in a different module, or with labels that have been shadowed by another declaration), this could mean that one wants to bring its labels in scope. Here, the intention is to declare a new datatype, so the syntax should start with "type foo" like for any other type declaration. For instance: "type foo = open" or "type foo = ..".
2. "extend foo with Constr of int" introduces a new keyword, which is rather common and is thus likely to break existing code. From my experience, there is little chance this can be accepted in OCaml. Another proposal: "type foo += Constr of int". This also has the advantage that one can add several cases:
type foo += Foo of int | Bar of string
3. "type foo = A | .." could be a short-hand for "type foo = .. ;; type foo += A".
I agree that the proposed syntax is not very good. Regarding the above suggestions:
For type declaratons, I think that the "type 'a foo = .." syntax would be fine. Another alternative would be "type > 'a foo", borrowing the ">" from polymorphic variants.
Whichever syntax is used for type declarations, I think that it should definitely allow type abbreviations to be checked for their openness. For instance:
type foo = bar
should create a type abbreviation that is open if bar is open, but
type > foo = bar
should check that bar is open and create a type abbreviation.
2 and 3.
I like the "type foo +=" syntax, it is certainly preferable to a new keyword. The only downside is that it provides no obvious syntax for rebinding extensions, but I don't think that this is a particularly useful feature anyway.
I'm not sure about allowing multiple extensions to be declared at once, or allowing extensions to be declared within the type declaration, because:
type foo = A | B | ..
will be compatible with
type foo = B | A | ..
which could cause confusion.
I also think that if it is too easy to create an open type and extensions that are equivalent to an ordinary variant type, then people will create them unnecessarily. Essentially, the additional runtime cost of using extensions compared to ordinary variants should be reflected by the syntax in some way.
edited on: 2012-04-13 13:53
1. I strongly prefer "type 'a foo = .." to "type > 'a foo". We are declaring a type, which happens to be of a new kind (previously, we had only "abstract", "variant", "record"; now there is "open"). Now similarly to other kinds of type declarations with a manifest type, we can write both:
type bar = foo
type bar = foo = ..
2. For rebinding, what about: "type foo += M.X = X of int * int"?
I agree with your remark about defining constructors directly within the type declaration. But I don't see the problem with multiple extensions:
type foo = ..
type foo += A of int | B of string
edited on: 2012-04-13 16:34
For the rebinding it would be more like: "type foo += X = M.Y", which is probably fine.
I think that having all of
"type foo += A of int | B of string"
"type foo += B of string | A of int"
"type foo += A of int
type foo += B of string"
as equivalent definitions may cause confusion, because there aren't really any other features in OCaml that allow similar duplication.
Such syntactic sugar might be better added using camlp4.
I have not yet tried the patch, but the idea seems fine.
Concerning the syntax, I would vote for
type open foo = ...
type foo += ...
Since open is already a keyword there is no problem.
By the way I believe that private should have been the same way, but wasn't for historical reasons.
Also, private was originally intended to apply to individual constructors, so it would make sense to use it with that meaning.
Last, I believe that you should allow
type foo += A of int | B of bool
Since the syntax follows the one for variants, there is no reason have people write more than necessary.
For me the advantage of extensible types is double:
* allow extension of an already defined type (but this was already possible with exn)
* allow GADT constructors (which is difficult with polymorphic variants)
The real goal of polymorphic variants was to allow reusing the same constructor in different types, with fine grain pattern-matching, and this is orthogonal to this.
I have attached a new version of the patch (tested with revision 12464).
The new version uses the syntax:
type 'a foo = ..
to define open types. To match this the behaviour has been changed so that open types are a new kind of type, rather than a property of types.
The syntax for adding extensions has also been changed to:
type 'a foo +=
A of 'a
| B: int foo
To match this syntax, these have been changed to behave more like extensions to a type's definition, rather than declarations of constructors. Intuitively, they behave like:
type 'a foo_new = 'a foo + A of 'a | B: int foo_new
and can be used wherever the definition:
type 'a foo_new = 'a foo = ..
would be allowed.
In the above definition, although A and B are defined in a single extension, they are separate members of a module signature so that the following definitions are equivalent to the one above:
type 'a foo += A of 'a
type 'a foo += B: int foo
Extensions can be made private using the expected syntax:
type 'a foo += private C of int
They can also be rebound:
type 'a foo += D = A
The patch also changes the implementation to use Alain's suggestion of using an object tag instead of needing a new tag for extensions.
I have added the extension to Ocamldoc and the other tools, but I did not add the new syntax to either camlp4 or the emacs mode, as I thought that was better left to someone who knows more about them.
|Is this patch still being considered for inclusion? I tried applying patch 2.0.0 against the trunk revision 12594 and it does not apply cleanly.|
|I don't know whether it's being considered for inclusion, but patch 2.0.0 was made for revision 12464 and should work with that one. I wasn't planning on rebasing the patch on a newer revision until OCaml version 4.0.0 is released.|
|Will there be an update to this patch now that 4.00.0 is out?|
The latest version of this patch (currently about 6 months behind trunk) can be found at https://github.com/lpw25/ocaml-open/. [^]
There is also a version built against 4.00.1 at https://github.com/lpw25/ocaml-open/archive/4.00.1+open_types.tar.gz [^]
|I've finally brought my patch up to date. The attached patch (extension.patch-3.0.0) was tested with revision 14443. To make review easier I've also added a pull request to the Github mirror (https://github.com/ocaml/ocaml/pull/18 [^]).|
|2012-04-11 23:09||lpw25||New Issue|
|2012-04-11 23:09||lpw25||File Added: extension.patch-1.0.2|
|2012-04-12 20:04||frisch||Note Added: 0007346|
|2012-04-12 20:06||frisch||Note Edited: 0007346||View Revisions|
|2012-04-13 13:40||lpw25||Note Added: 0007350|
|2012-04-13 13:48||frisch||Note Added: 0007351|
|2012-04-13 13:53||frisch||Note Edited: 0007351||View Revisions|
|2012-04-13 16:33||lpw25||Note Added: 0007353|
|2012-04-13 16:34||lpw25||Note Edited: 0007353||View Revisions|
|2012-04-13 17:16||garrigue||Note Added: 0007354|
|2012-05-02 16:50||doligez||Assigned To||=> doligez|
|2012-05-02 16:50||doligez||Status||new => acknowledged|
|2012-05-18 13:11||lpw25||File Added: extension.patch-2.0.0|
|2012-05-18 13:28||lpw25||Note Added: 0007443|
|2012-06-09 20:40||hcarty||Note Added: 0007534|
|2012-06-09 21:37||lpw25||Note Added: 0007535|
|2012-08-09 08:46||doligez||Assigned To||doligez =>|
|2012-08-10 03:53||hcarty||Note Added: 0007937|
|2013-01-09 19:05||lpw25||Note Added: 0008730|
|2013-12-05 15:44||doligez||Tag Attached: patch|
|2014-02-27 17:54||lpw25||File Added: extension.patch-3.0.0|
|2014-02-27 18:01||lpw25||Note Added: 0010980|
|Copyright © 2000 - 2011 MantisBT Group|