From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.1.3 (2006-06-01) on yquem.inria.fr X-Spam-Level: X-Spam-Status: No, score=-0.2 required=5.0 tests=AWL,NO_RELAYS autolearn=disabled version=3.1.3 Received: by yquem.inria.fr (Postfix, from userid 24253) id 0B718BC69; Wed, 14 Nov 2007 08:58:28 +0100 (CET) Date: Wed, 14 Nov 2007 08:58:28 +0100 To: Martin Jambon Cc: Yaron Minsky , caml-list Subject: Re: [Caml-list] Compiler feature - useful or not? Message-ID: <20071114075827.GA24058@yquem.inria.fr> References: <473A363F.2080301@gmail.com> <891bd3390711131608g48b584a4n6b0ccab95d7de3f3@mail.gmail.com> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.5.9i From: weis@yquem.inria.fr (Pierre Weis) X-Spam: no; 0.00; compiler:01 weis:01 weis:01 yaron:01 minsky:01 sig:01 val:01 val:01 implements:01 ocaml:01 compiler:01 abbreviation:01 abbreviation:01 failwith:01 mli:01 > On Tue, 13 Nov 2007, Yaron Minsky wrote: > > >There's a simple trick that Steven Weeks introduced to us and that we now > >use at Jane Street for this kind of thing. > > > >You write down a signature: > > > >module type Abs_int : sig > >type t > >val to_int : t -> int > >val of_int : int <- t > >end > > > >And then you write concrete module Int that implements this signature. You > >can then write: > > > >module Row : Abs_int = Int > >module Col : Abs_int = Int > > > >You can now use Row.t and Col.t as abstract types. The boilerplate is > >written once, but can be used over and over. I've personally seen more > >use-cases for this with strings than with ints (to separate out different > >kinds of identifiers) > > That's the best solution I've seen so far. > > Otherwise there's still the following: > http://martin.jambon.free.fr/ocaml.html#opaque > > which in theory doesn't require new module or type declarations, but it > adds type parameters, which can be confusing. > > > Martin In the next version of the compiler, you will have an extension to the definition of types with private construction functions (aka ``private'' types) that just fulfills your programming concern: in addition to usual private sum and record private type definitions, you can now define a type abbreviation which is private to the implementation part of a module (see note 1). Since the values of a private type are concrete, it is much easier for the programmer to use the values of the type abbreviation. Using the new private type abbreviation feature, you can write for instance: row.ml ------ type row = int;; let make i = if i < 0 then failwith "Row: cannot create a negative row" else i;; let from i = i;; row.mli ------- type row = private int;; val make : int -> row;; val from : row -> int;; This solution does not require any additional tagging or boxing, only the usage of injection/projection function for the type. As for usual private types, the injection function is handy to provide useful invariants (in the row type example case, we get ``a row value is always a positive integer''). In addition, the private abbreviation is publicly exposed in the interface file. Hence, the compiler knows about it: it can (and effectively does) optimize the programs that use values of type row in the same way as if the type row were defined as a regular public abbreviation. Last but not least, being an instance of the identity function, the from projection function is somewhat generic: we can dream to suppress the burden of having to write it for each private type definition, if we find a way to have it automatically associated to the new private type by the compiler. Best regards, Note 1: this is a generalization for regular type abbreviations of the polymorphic variants private type definitions that Jacques Garrigue already introduced to provide polymorphic variants (and object) types with private row variables. -- Pierre Weis INRIA Rocquencourt, http://bat8.inria.fr/~weis/