Mantis Bug Tracker

View Issue Details Jump to Notes ] Issue History ] Print ]
IDProjectCategoryView StatusDate SubmittedLast Update
0007102OCamltypingpublic2015-12-18 16:522017-04-13 13:18
Reportergasche 
Assigned To 
PrioritynormalSeverityfeatureReproducibilityN/A
StatusacknowledgedResolutionopen 
PlatformOSOS Version
Product Version 
Target VersionFixed in Version 
Summary0007102: Ability to re-export a variant definition with renamed constructors?
DescriptionWe have a bit of an issue in Batteries for the 4.03 transition, as 4.03+dev includes a ('a result) type defined as

  type ('a,'b) result = Ok of 'a | Error of 'b

while Batteries has distributed forever a datatype

  type ('a, 'b) result = Ok of 'a | Bad of 'b


This should, of course, not be blocking for the addition of a result type in 4.02.3, but it would be nice if it were possible to provide a smooth transition path to our users. (We can provide both datatypes, using type-directed constructor disambiguation, but there is still the issue that a number of functions return values of BatPervasives.result type, and we'd rather not duplicate them to have versions returning Pervasives.result).

Would it be possible to declare an alias with constructors of the same structure, but different names?

  type ('a, 'b) result = ('a, 'b) Pervasives.result =
    | Ok of 'a
    | Bad of 'b
TagsNo tags attached.
Attached Files

- Relationships

-  Notes
(0015176)
frisch (developer)
2015-12-18 17:43

If we allow to rename constructors, this should be made explicit, not relying on the ordering of constructors.

E.g.

 type ('a, 'b) result = ('a, 'b) Pervasives.result =
    | Ok of 'a
    | Error as Bad of 'b
(0015180)
garrigue (manager)
2015-12-21 03:05

Unfortunately, I'm afraid this feature first requires some theoretical work.

A first problem is that it breaks the type-erasure semantics of the language: now two constructors are equal if they have the same type (otherwise you cannot compare them) and same name. If they are allowed to have different names, then constructors are something else.

A second problem, which is a consequence of the first, is the interaction with constructor disambiguation. Suppose that you define
  type t = A | B
in some module M1, and re-export it as
  type u = M1.t = A as C | B as D
  type v = M1.t = A as D | B as C
Then you have in the same scope two constructors C and D, which belong to the same type, and whose resolution is ambiguous...

Maybe there is a proper way to do that, but this requires some fundamental work.
Moreover, since this changes the semantics, I would see this as a change to the language itself (not just a comfort improvement, like constructor/field disambiguation or inline records).
(0015182)
gasche (developer)
2015-12-21 09:32
edited on: 2015-12-21 10:11

This is probably due to my very naive point of view, but I don't see
so many difficulties.

> A first problem is that it breaks the type-erasure semantics of the
> language: now two constructors are equal if they have the same type
> (otherwise you cannot compare them) and same name. If they are allowed
> to have different names, then constructors are something else.

I understand the feature as the ability to rebind constructors to
a different name while preserving equality information (in fact using
Alain's explicit syntax one could even rebind a constructor inside its
own declarations: type 'a option = None | Nothing as None | Some of
'a). This means that we need a resolution environment for constructors
(canonicalization/rewriting of constructors), but it is not
incompatible with a type-erased semantics:

- you can perform resolution statically as an elaboration pass,
  replacing occurences of Bad by Error (for example during
  type-checking), which is not in the spirit of type-erasure; but

- you can also maintain a runtime environment of constructor
  definitions, to be used at construction time (Bad v -> Error v)
  and dually at pattern-matching time (Error p -> Bad p).

The elaboration semantics is just a partial-evaluation optimization of
the type-erased runtime semantics, where those rewriting are done
statically instead of at runtime.

> A second problem, which is a consequence of the first, is the interaction with constructor disambiguation. Suppose that you define
> type t = A | B
> in some module M1, and re-export it as
> type u = M1.t = A as C | B as D
> type v = M1.t = A as D | B as C
> Then you have in the same scope two constructors C and D, which belong to the same type, and whose resolution is ambiguous...

This situation can be rejected at declaration-time (or lazily whenever
C needs to be resolved), because the canonicalization environment for
constructor names is inconsistent (C is bound to two
incompatible constructors). If we had designed the feature before
type-directed resolution, we would have probably adopted a shadowing
semantics, but now that all constructors are "in scope" from their
type we shall accordingly guarantee that all their bindings are consistent.

> Maybe there is a proper way to do that, but this requires some
> fundamental work. Moreover, since this changes the semantics,
> I would see this as a change to the language itself (not just
> a comfort improvement, like constructor/field disambiguation or
> inline records).

Ok, we'll have to find another solution then.


- Issue History
Date Modified Username Field Change
2015-12-18 16:52 gasche New Issue
2015-12-18 17:43 frisch Note Added: 0015176
2015-12-21 03:05 garrigue Note Added: 0015180
2015-12-21 09:32 gasche Note Added: 0015182
2015-12-21 10:11 gasche Note Edited: 0015182 View Revisions
2017-02-23 16:45 doligez Category OCaml typing => typing
2017-04-13 13:18 doligez Status new => acknowledged


Copyright © 2000 - 2011 MantisBT Group
Powered by Mantis Bugtracker