Version française
Home     About     Download     Resources     Contact us    
Browse thread
Overriding an entry in a polymorphic variant
[ Home ] [ Index: by date | by threads ]
[ Search: ]

[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
Date: -- (:)
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