[
Home
]
[ Index:
by date
|
by threads
]
[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
Date: | 2006-08-31 (23:29) |
From: | skaller <skaller@u...> |
Subject: | Re: [Caml-list] Re: Overriding an entry in a polymorphic variant |
On Thu, 2006-08-31 at 18:04 -0400, Yaron Minsky wrote: > On 8/31/06, Yaron Minsky <yminsky@cs.cornell.edu> wrote: > Does anyone know if there is a clean way of overriding a field > in a polymorhphic variant. I want to do something like this: > > type bot = [ `bot ] > type top = [`bot | `top] > type t = [ `a of bot | `b of bot | `c of bot | `d of bot | `e > of bot ] > type t1 = [ t | `c of top | `e of top ] > > the desired end result being that t1 is actually [ `a of bot | > `b of bot | `c of top | `d of bot | `e of top ]. I'm hoping > to do this largely to enable some phantom-types hackery I'm > working on. I'm not sure it matters from the point of view of > whether this is doable, but it is potentially relevant that > bot is a subtype of top. > > Small addendum: I'm still not sure this is relevant, It is .. > but I did get my example slightly backwards. top should be a subtype > of bot, not the other way. So the definitions of bot and top should > be: > > type bot = [ `bot | `top] > type top = [`top] Polymorphic variants are covariant in their arguments. The first version in Ocaml did not support covariant arguments. The current version does: excuse annotations but I always get sub and super types mixed up. (* subtypes have subset of cases *) type top = [ `bot | `top ] (* super type *) type bot = [ `bot ] (* sub type *) ;; ( `bot : bot :> top ) (* cast from sub to super type adds cases *) ;; type sub = [ `a of bot | `b of bot | `c of bot | `d of bot ];; (* same constructor names, but arguments of `c,`d have more cases so it is a supertype of sub *) type super = [ `a of bot | `b of bot | `c of top | `d of top ];; let c : sub = `c `bot;; match c with | `c x -> `c (x: bot :> top) (* coerce argument *) | _ -> assert false ;; ( c : sub :> super ) (* directly coerce the type *) ;; This wasn't your original question, but is the important part of the answer. The trivial part is: no you cannot "override" a type constructor: # type a = [`A of int | `A of string];; This variant type contains a constructor [ `A of string ] which should be [ `A of int ] Within a single type, a constructor can only have one argument type, and the [ ... ] notation using an alias is just sugar for the expansion of the alias. But there is no need: just partition the constructors: type base = [`a of bot | `b of bot] type sub = [ base | `c of bot | `d of bot] type super = [ base | `c of top | `d of top] If you REALLY want to be sexy, you can make the argument type parametric: type 'b ext = [`c of 'b | `d of 'b ] type sub = [ base | bot ext ] type super = [ base | top ext ] -- John Skaller <skaller at users dot sf dot net> Felix, successor to C++: http://felix.sf.net