Version française
Home     About     Download     Resources     Contact us    
Browse thread
anonymous record types in variants
[ Home ] [ Index: by date | by threads ]
[ Search: ]

[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
Date: -- (:)
From: Xavier Leroy <Xavier.Leroy@i...>
Subject: Re: anonymous record types in variants
Christopher Jeris wrote:

> The argument of a variant type constructor cannot be an anonymous record
> type, i.e.:
> 
>   type foo = One of {one: int} | Two of {two: string}
> 
> is rejected at the first {.  Of course this is easy to work around, just
> give the record types names:
> 
>   type foo_one = {one: int}
>   type foo_two = {two: string}
>   type foo = One of foo_one | Two of foo_two
> 
> But, just out of curiosity, is there a quick explanation of why it is this
> way?

Basically, because "{one : int}" is not a type expression, and the
argument of a constructor must be a type expression.

The reason why "{one : int}" is not a type expression but must be
declared and bound to a type name have to do with type inference
and the existence of principal types.  If you allow record types in
type expressions (as in SML), some functions have no principal type,
such as fun x -> x.l.

Manuel Fahndrich wrote:

> I also find this the major annoying feature of CAML records. I frequently
> use variant datatypes with a number of fields. Without records, the field
> order matters and has to be remembered when creating and accessing such
> variants. Anonymous records would be ideal on variants, since they would not
> introduce the extra level of indirection that you get when you declare an
> explicit record type.

It could be implemented this way.  However, if you declare the
datatype as

        type foo = A of {lbl1 : int; lbl2 : int}

you would be forced to pattern-match it as follows

        match x with A{lbl1 = x; lbl2 = y} -> ...

but you can't get access to the record itself and use the dot notation
on it, as in

        match x with A r -> ... r.x ... r.y ...

That's basically the same restrictions we currenty have on
constructors with multiple arguments (A of int * int) vs.
constructors taking a tuple (A of (int * int)), so maybe that's not
too bad.

Anton Moscal wrote:

> I agree. I often need the following usage of anonymous types:
> type text = int(*length*) * (File of string | Str of string | ...)
> (factorizing of the common fields in the variant types).
> SML allow this construction.

No, it doesn't.  It has a "withtype" construct that just works around
the fact that type abbreviations and datatype declarations cannot be
mutually recursive.  But in Caml we don't have this problem.

> Probably an optimal solution would
> be to allow anonymous types in any context.

You can kiss type inference goodbye, then.

Don Syme wrote:

> BTW, the type language of Mercury (and probably some other FP languages?)
> allows variants and records pretty much anywhere in a type structure. 

What kind of type inference do they have?

- Xavier Leroy