Version française
Home     About     Download     Resources     Contact us    
Browse thread
[Caml-list] Polymorphic variant abbreviations
[ Home ] [ Index: by date | by threads ]
[ Search: ]

[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
Date: -- (:)
From: Patrick M Doane <patrick@w...>
Subject: Re: [Caml-list] Polymorphic variant abbreviations
On Wed, 19 Sep 2001, Jacques Garrigue wrote:

> > I have some code that would like to use polymorphic type abbreviations
> > along with labels.  It seems to be not behaving quite like I expected.
> > What could I do to make this shorter:
> > 
> >   type a = [ `A ]
> > 
> >   let f ~a:(#a as a) = ...
> 
> Nothing. But this doesn't strike me as a very frequent idiom.

I'll motivate how I came to using this feature.

I am working with a protocol that sends messages containing data as typed
s-expressions.  A natural representation with standard variants would be:

type data =
  | List of data list
  | Int of int
  | String of string
  (* there are about a dozen or so types in reality *)

There is a limited set of messages that can be sent and they have specific
type constraints on their data.  My hope was to express many of these
constraints using polymorphic variants and then check the rest at runtime.
Without polymorphic variants, I'm forced to do all checks at runtime.

So, I start with a function like this:

  let msg1 arg1 arg2 =
    { name = "msg1";
      data = `List [arg1; arg2] }

Now, the protocol defines type constraints for the arguments to all
messages. So, I create some type abbreviation for each kind of argument
that is used:

type arg1 = [ `String of string ]
type arg2 = [ `Int ]

So now I would like to require that the arguments to msg1 have the correct
type: 

  (* this doesn't work - types are too constrained *)
  let msg1 (arg1 : #arg1) (arg2 : #arg2) = ...


  (* need to use the 'as' form like this to get better typing *)
  let msg1 (#arg1 as arg1) (#arg2 as arg2) = ...

And finally, I want the message arguments to be labeled by their name.
Hence:

  let msg1 ~arg1:(#arg1 as arg1) ~arg2:(#arg2 as arg2) = ...

Maybe I'm trying to push the system too far. I found this methodology
worked pretty well until I came to lists. I have not been able to restrict
the elements of a list to be a specific type.

> >   let f ~a:#a = ...
> > 
> > but then it says that 'a' is unbound.
> 
> Sure, nothing binds a here: ~a: is a label, and #a an abbreviation for
> `A.

Well, '~a' implies the binding '~a:a'. I don't see why it is unreasonable
to assume a similar case applies with patterns.

> > I also find that the error messages are not as useful as they could be
> > with the type abbreviations. E.g:
> > 
> >   This expression has type ... but is here used with #a as 'a = 'a
> 
> Could you give me the code leading to this error message?
> This is clearly a bug.

This seems to happen in all cases I have tried:

# type t = [`A];;
type t = [ `A]
# let f1 (x:#t) = x;;
val f1 : (#t as 'a) -> 'a = <fun>
# let f2 (#t as x) = x;;
val f2 : #t -> [> `A] = <fun>
# let f3 ~x:(#t as x) = x;;
val f3 : x:#t -> [> `A] = <fun>
# f1 `B;;
Characters 3-5:
This expression has type [> `B] but is here used with type #t as 'a = 'a
# f2 `B;;
Characters 3-5:
This expression has type [> `B] but is here used with type #t as 'a = 'a
# f3 `B;;
Characters 3-5:
This expression has type [> `B] but is here used with type #t as 'a = 'a
# 

Thanks very much for everyone's help!

Patrick

-------------------
Bug reports: http://caml.inria.fr/bin/caml-bugs  FAQ: http://caml.inria.fr/FAQ/
To unsubscribe, mail caml-list-request@inria.fr  Archives: http://caml.inria.fr