caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* RE: anonymous record types in variants
@ 1999-02-15 18:03 Manuel Fahndrich
  0 siblings, 0 replies; 14+ messages in thread
From: Manuel Fahndrich @ 1999-02-15 18:03 UTC (permalink / raw)
  To: caml-list


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.

-Manuel 

-----Original Message-----
From: Don Syme [mailto:dsyme@microsoft.com]
Sent: Monday, February 15, 1999 2:30 AM
To: 'Christopher Jeris'; caml-list@inria.fr
Subject: RE: anonymous record types in variants



FTR, I've also had a few situations where it seemed most natural to write
similar constructs, but I couldn't.

Cheers,
Don
> 
> 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?
> 
> thanks & peace,
> 
> Chris Jeris	MIT math grad student and novice OCaml music programmer
> 




^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: anonymous record types in variants
  1999-02-22 16:37 Manuel Fahndrich
@ 1999-02-22 17:56 ` Pierre Weis
  0 siblings, 0 replies; 14+ messages in thread
From: Pierre Weis @ 1999-02-22 17:56 UTC (permalink / raw)
  To: Manuel Fahndrich; +Cc: caml-list

> I don't agree with Anton. The reason I want variants with anonymous record
> arguments is to name the fields explicitly. I don't want to incur a runtime
> cost of an extra indirection. The compilation of named fields vs. tuples
> would be the same. That's why a construction like 
> 
> >         match x with A r -> ... r.x ... r.y ...
> 
> would not be desirable, since it requires the record r to be stored as  a
> separate block from the A r value. If you restrict record access for these
> anonymous records as Xavier pointed out
> 
> >         match x with A{lbl1 = x; lbl2 = y} -> ...
> 
> 
> then you can implement them as efficiently as a variant with a tuple
> argument.
> 
> -Manuel

An even better scheme would be to allow access to the fields with the
dot notation, considering that a value of type

type t = A of {labl1 : int; labl2 : bool}

is in fact a tuple with named field tagged with A (the treatment is
completely similar to constructors with tuple arguments, and as the
value A (..., ...)  cannot be pattern matched to extract the tuple,
then A {...} could not be pattern matched to extract the record).

Then

match expr with A {lbl1 = _; lbl2 = _} as x -> x.lbl1 ... x.lbl2

is conceivable (easy to compile, not too difficult to type check).

Moreover, this could be easily extended to mutable labels, using the
usual syntax: if t is defined as

type t = A of {mutable labl1 : int; mutable labl2 : bool}

we could write

match expr with
 A {lbl1 = _; lbl2 = _} as x ->
   x.lbl1 <- x.lbl1 + 1 ... x.lbl2 <- not x.lbl2

I think this is not too difficult to understand (given the simliarity
with the actual semantics of constructors in Objective Caml) and not
too difficult to implement. Last but not least, it does not require
any extra syntax!

Pierre Weis

INRIA, Projet Cristal, Pierre.Weis@inria.fr, http://cristal.inria.fr/~weis/





^ permalink raw reply	[flat|nested] 14+ messages in thread

* RE: anonymous record types in variants
@ 1999-02-22 16:37 Manuel Fahndrich
  1999-02-22 17:56 ` Pierre Weis
  0 siblings, 1 reply; 14+ messages in thread
From: Manuel Fahndrich @ 1999-02-22 16:37 UTC (permalink / raw)
  To: caml-list


I don't agree with Anton. The reason I want variants with anonymous record
arguments is to name the fields explicitly. I don't want to incur a runtime
cost of an extra indirection. The compilation of named fields vs. tuples
would be the same. That's why a construction like 

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

would not be desirable, since it requires the record r to be stored as  a
separate block from the A r value. If you restrict record access for these
anonymous records as Xavier pointed out

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


then you can implement them as efficiently as a variant with a tuple
argument.

-Manuel

-----Original Message-----
From: Anton Moscal [mailto:msk@post.tepkom.ru]

> 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 ...

But why? Natural semantic for anonymous types is the following: each
anonymous record or algebraic types declaration introduces new type
declaration in the current scope with some temporary type name. I.e.

        type ('a, 'b) foo = A of 'a * {l : 'b; l2: int}

is a shortcut for:

        type ('a, 'b) temp_name = {l1 : 'b; l2: int}
        and  ('a, 'b) foo = A of 'a * ('a, 'b) temp_name

Regards,
Anton Moscal




^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: anonymous record types in variants
  1999-02-22  8:44   ` Anton Moscal
@ 1999-02-22 13:00     ` Pierre Weis
  0 siblings, 0 replies; 14+ messages in thread
From: Pierre Weis @ 1999-02-22 13:00 UTC (permalink / raw)
  To: Anton Moscal; +Cc: caml-list

> But why? Natural semantic for anonymous types is the following: each
> anonymous record or algebraic types declaration introduces new type
> declaration in the current scope with some temporary type name. I.e.
> 
> 	type ('a, 'b) foo = A of 'a * {l : 'b; l2: int}
> 
> is a shortcut for:
> 
> 	type ('a, 'b) temp_name = {l1 : 'b; l2: int}
> 	and  ('a, 'b) foo = A of 'a * ('a, 'b) temp_name
> 
> Regards, 
> Anton Moscal

I proposed once (10 years ago ?) to have an ``as'' construct in data
type definitions: you could introduce a new datatype definition anywhere
in a datatype definition by writing

 (type_definition_body as type_name)

 with type_definition_body being one of the following:
  [ | C1 {of t1} | C2 {of t2} | ...] for sum types
  { lab1 : t1; lab2 : t2; ... } for record types
  type_expression for abbreviation types

the semantics you expect would then have been written as:

 	type ('a, 'b) foo = A of 'a * ({l : 'b; l2: int} as 'b temp_name)

This way the user could control the naming and number of type
arguments of the ``anonymous'' types defined, which is mandatory for
error messages from the typechecker, documentation purposes and clean
interfaces of modules.

As you mentioned it, such a scheme poses no problems at all to the
compiler, since it is just a shorthand for existing data type
definitions. On the other hand, it is conceivable to let the programmer
to expand this construct by hand, since it is just a few more lines to
write. That's the actual situation in the Caml light and Objective
Caml compilers.

Pierre Weis

INRIA, Projet Cristal, Pierre.Weis@inria.fr, http://cristal.inria.fr/~weis/





^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: anonymous record types in variants
  1999-02-17  9:32 ` Xavier Leroy
  1999-02-17 18:09   ` Christopher Jeris
@ 1999-02-22  8:44   ` Anton Moscal
  1999-02-22 13:00     ` Pierre Weis
  1 sibling, 1 reply; 14+ messages in thread
From: Anton Moscal @ 1999-02-22  8:44 UTC (permalink / raw)
  To: Xavier Leroy; +Cc: caml-list

On Wed, 17 Feb 1999, Xavier Leroy wrote:

> 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 ...

But why? Natural semantic for anonymous types is the following: each
anonymous record or algebraic types declaration introduces new type
declaration in the current scope with some temporary type name. I.e.

	type ('a, 'b) foo = A of 'a * {l : 'b; l2: int}

is a shortcut for:

	type ('a, 'b) temp_name = {l1 : 'b; l2: int}
	and  ('a, 'b) foo = A of 'a * ('a, 'b) temp_name

Regards, 
Anton Moscal




^ permalink raw reply	[flat|nested] 14+ messages in thread

* RE: anonymous record types in variants
@ 1999-02-18 14:03 Don Syme
  0 siblings, 0 replies; 14+ messages in thread
From: Don Syme @ 1999-02-18 14:03 UTC (permalink / raw)
  To: 'Xavier Leroy', Christopher Jeris, caml-list


> >   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.

I think all we're thinking of is a mechanism so the user doesn't have to
write
nonsense type names such as foo_one and foo_two as in the above example.  
Within a (mutually recursive) type declaration, shouldn't it
be feasible to use tuples, records and variants freely, as long as all the
names 
of all the fields and constructors are used at only one place in the
declaration?
Of course you would always need named types for recursive type constructors.

Cheers & thanks,
Don

------------------------------------------------------------------------
At the lab:                                     At home:
Microsoft Research Cambridge                    11 John St
St George House                                 CB1 1DT
Cambridge, CB2 3NH, UK
Ph: +44 (0) 1223 744797                         Ph: +44 (0) 1223 722244
http://research.microsoft.com/users/dsyme
email: dsyme@microsoft.com
   "You've been chosen as an extra in the movie
        adaptation of the sequel to your life"  -- Pavement, Shady Lane
------------------------------------------------------------------------




^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: anonymous record types in variants
@ 1999-02-18 10:13 Frank A. Christoph
  0 siblings, 0 replies; 14+ messages in thread
From: Frank A. Christoph @ 1999-02-18 10:13 UTC (permalink / raw)
  To: caml-list

Xavier Leroy wrote:
>> 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?

The undecidable kind. :/

--FC



^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: anonymous record types in variants
  1999-02-17 18:09   ` Christopher Jeris
@ 1999-02-17 19:14     ` Didier Remy
  0 siblings, 0 replies; 14+ messages in thread
From: Didier Remy @ 1999-02-17 19:14 UTC (permalink / raw)
  To: Christopher Jeris; +Cc: Xavier Leroy, caml-list

> But an analogous construction already exists in the object system:

I was expecting this question...  

Yes, it is possible to have anonymous records and still keep principal
types, using `polymorphic' records (a restriction of `extensible records')
--this is the way objects are typed.

However, this will cost at runtime, unless there are very severe,
complicated compile-time/link-time optimizations. (In the case of objects,
this cost is expected because you are programming by message invocation.)

Since there are already objects in Ocaml, the need for
polymorphic/extensible records is not so strong. This would be convenient
but would not add much expressivity (you can always use objects).  Hence the
gain may be insufficient to justify a complication of the language and of
the implementation.

> Another thing that kind of confuses me is open object types.  Can the open
> object type < one : int; .. > be defined directly in any way ?
> 
>   type foo = < one : int; .. >

Yes, but since this is a polymorphic type you have to write:

        type 'a foo  = 'a constraint 'a = < one : int; ..>;;

This captures the polymorphic row variable `..' (that you are not allowed to
name directly) within the constrained type parameter 'a.

    Didier.




^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: anonymous record types in variants
  1999-02-17  9:32 ` Xavier Leroy
@ 1999-02-17 18:09   ` Christopher Jeris
  1999-02-17 19:14     ` Didier Remy
  1999-02-22  8:44   ` Anton Moscal
  1 sibling, 1 reply; 14+ messages in thread
From: Christopher Jeris @ 1999-02-17 18:09 UTC (permalink / raw)
  To: Xavier Leroy, caml-list


On Wed, 17 Feb 1999, Xavier Leroy wrote:
> 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.

But an analogous construction already exists in the object system:

# let f x = x#foo;;
val f : < foo : 'a; .. > -> 'a = <fun>

And indeed I can replace records by objects in my first example:

  type foo = One of < one : int > | Two of < two : string >

But this doesn't solve the problem since (I think) I now have to name the
object type in order to create objects which belong to it.  So "open
record types" { one : int; .. } are just not a good idea ?

Another thing that kind of confuses me is open object types.  Can the open
object type < one : int; .. > be defined directly in any way ?

  type foo = < one : int; .. >

is rejected since .. is unspecified.  It seems that open object types can
result from inferences about the types of other objects/functions, but not
named directly ?  (Or am I trying to do the wrong thing ?)

Sorry if these questions are kind of elementary.  I'm still chewing on the
c/c0/c1/m example about 2/3 of the way through "Objects in Caml" :)

thanks & peace,

Chris Jeris	MIT Math grad student & novice OCaml music programmer




^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: anonymous record types in variants
  1999-02-12 20:53 Christopher Jeris
  1999-02-16 10:57 ` Anton Moscal
@ 1999-02-17  9:32 ` Xavier Leroy
  1999-02-17 18:09   ` Christopher Jeris
  1999-02-22  8:44   ` Anton Moscal
  1 sibling, 2 replies; 14+ messages in thread
From: Xavier Leroy @ 1999-02-17  9:32 UTC (permalink / raw)
  To: Christopher Jeris, caml-list

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




^ permalink raw reply	[flat|nested] 14+ messages in thread

* RE: anonymous record types in variants
@ 1999-02-16 17:40 Don Syme
  0 siblings, 0 replies; 14+ messages in thread
From: Don Syme @ 1999-02-16 17:40 UTC (permalink / raw)
  To: 'Anton Moscal', Christopher Jeris; +Cc: caml-list


Again, I've also needed to factorize the common fields of variants as in
Anton's example.

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

Don

> 
> On Fri, 12 Feb 1999, 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}
> > 
> 
> 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. Probably an optimal solution would
> be to allow anonymous types in any context.
> 
> Regards,
> Anton Moscal
> 




^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: anonymous record types in variants
  1999-02-12 20:53 Christopher Jeris
@ 1999-02-16 10:57 ` Anton Moscal
  1999-02-17  9:32 ` Xavier Leroy
  1 sibling, 0 replies; 14+ messages in thread
From: Anton Moscal @ 1999-02-16 10:57 UTC (permalink / raw)
  To: Christopher Jeris; +Cc: caml-list



On Fri, 12 Feb 1999, 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}
> 

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. Probably an optimal solution would
be to allow anonymous types in any context.

Regards,
Anton Moscal




^ permalink raw reply	[flat|nested] 14+ messages in thread

* RE: anonymous record types in variants
@ 1999-02-15 10:30 Don Syme
  0 siblings, 0 replies; 14+ messages in thread
From: Don Syme @ 1999-02-15 10:30 UTC (permalink / raw)
  To: 'Christopher Jeris', caml-list


FTR, I've also had a few situations where it seemed most natural to write
similar constructs, but I couldn't.

Cheers,
Don
> 
> 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?
> 
> thanks & peace,
> 
> Chris Jeris	MIT math grad student and novice OCaml music programmer
> 




^ permalink raw reply	[flat|nested] 14+ messages in thread

* anonymous record types in variants
@ 1999-02-12 20:53 Christopher Jeris
  1999-02-16 10:57 ` Anton Moscal
  1999-02-17  9:32 ` Xavier Leroy
  0 siblings, 2 replies; 14+ messages in thread
From: Christopher Jeris @ 1999-02-12 20:53 UTC (permalink / raw)
  To: caml-list


(Sorry only in English.)

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?

thanks & peace,

Chris Jeris	MIT math grad student and novice OCaml music programmer




^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~1999-02-22 17:56 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1999-02-15 18:03 anonymous record types in variants Manuel Fahndrich
  -- strict thread matches above, loose matches on Subject: below --
1999-02-22 16:37 Manuel Fahndrich
1999-02-22 17:56 ` Pierre Weis
1999-02-18 14:03 Don Syme
1999-02-18 10:13 Frank A. Christoph
1999-02-16 17:40 Don Syme
1999-02-15 10:30 Don Syme
1999-02-12 20:53 Christopher Jeris
1999-02-16 10:57 ` Anton Moscal
1999-02-17  9:32 ` Xavier Leroy
1999-02-17 18:09   ` Christopher Jeris
1999-02-17 19:14     ` Didier Remy
1999-02-22  8:44   ` Anton Moscal
1999-02-22 13:00     ` Pierre Weis

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).