On Sun, May 31, 2009 at 7:08 PM, Dario Teixeira wrote: > > I also meant "heavier" in terms of efficiency. And like David said, it > does > feel wrong to carry the performance penalty of the object system solely > because > I need the structural subtyping features. If you're willing to give up some of the syntactic niceties of records (and the ability to pattern-match) you can get what you want using an abstract type. module type S = sig type 'a t val create_t1 : a : int -> b : int -> c : int -> [ `a | `b | `c ] t val create_t2 : a : int -> b : int -> c : int -> d : int -> [ `a | `b | `c | `d ] t val create_t3 : b : int -> c : int -> d : int -> [ `b | `c | `d ] t val a : [> `a ] t -> int val b : [> `b ] t -> int val c : [> `c ] t -> int val d : [> `d ] t -> int end module M : S = struct type u = { a: int; b: int; c :int; d: int } type 'a t = u let default = { a = 0; b = 0; c = 0; d = 0 } let create_t1 ~a ~b ~c = { default with a = a; b = b; c = c } let create_t2 ~a ~b ~c ~d = { a = a; b=b; c=c; d=d; } let create_t3 ~b ~c ~d = { default with b=b; c=c; d=d } let a t = t.a let b t = t.b let c t = t.c let d t = t.d end let f x = M.a x + M.b x let g () = f (M.create_t1 ~a:0 ~b:0 ~c:0) (* accepted by compiler *) let g () = f (M.create_t2 ~a:0 ~b:0 ~c:0 ~d:0) (* accepted by compiler *) let g () = f (M.create_t3 ~b:0 ~c:0 ~d:0) (* rejected by compiler *) The compiler error you get on that last line is this: Error: This expression has type [ `b | `c | `d ] M.t but is here used with type [> `a | `b ] M.t The first variant type does not allow tag(s) `a Here, we've chosen to use a default value for fields that we don't fill in. We could just as well have used options here. The performance of the above will be roughly the same as the performance of a simple record. Obviously, all of the different "subtypes" have the full record stored at a physical level. y