Version française
Home     About     Download     Resources     Contact us    
Browse thread
Emulating width subtyping with 1st-class modules
[ Home ] [ Index: by date | by threads ]
[ Search: ]

[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
Date: -- (:)
From: Alain Frisch <alain@f...>
Subject: Re: [Caml-list] Emulating width subtyping with 1st-class modules
On 08/05/2010 05:02 PM, Dario Teixeira wrote:
> I have a problem where some form of width subtyping for records would be
> useful.  At the present I'm taking advantage of the structural subtyping nature
> of Ocaml's object system to emulate the width subtyping.  This works and is
> reasonably compact, but I'm still open to other approaches.  It has occurred
> to me that 3.12's modules-as-first-class-values provide yet another solution:
>...
> While this approach seems awfully verbose, I reckon it could be made much
> more palatable via some Camlp4 sugaring.  Nevertheless, I have a question:
> just how heavy would this approach be when compared to the object one?
> And how would it fare in comparison to regular records?

It depends on what you call "heavy". For the syntactic aspects, as you 
say, Camlp4 can be helpful. One could also imagine future extensions in 
the compiler itself, e.g.:

- Extending the pattern algebra to directly unpack modules
   (allowing to write: "let print_brief (module M : BRIEF) = ....")

- Adding more type inference, to avoid some of the verbosity of 
first-class module. Jacques Garrigue had an experimental extension to 
allow implicit unpacking (when the context gives enough information to 
infer the module type). See the implicit-unpack branch in the OCaml 
Subversion repository.


Compared to object types, modules have some extra flexibility thanks to 
the "include" statement (you cannot "inherit" fields from an existing 
object, only from a class). For instance, you can write a function to 
merge two modules without having to enumerate all their fields:


module type S = sig
   val x: int
   (* ... *)
end

module type T = sig
   val y: int
   (* ... *)
end

module type S_T = sig
   include S
   include T
end

let merge s t =
   (module struct
     include (val s : S)
     include (val t : T)
   end : S_T)



Similar to object types, you cannot use pattern matching to deconstruct 
modules and filter on their fields.

Concerning performance, modules imply some copying to enable width 
subtyping used (in order to forget extra fields), which is not the case 
for objects. The runtime representation for modules is the same as for 
records; field access and value construction are very cheap.



Alain