10 views

Skip to first unread message

May 14, 2007, 5:20:32 AM5/14/07

to OCaml

I'm guessing this question is for Jacques:

Given a polymorphic variant type t with a label `B how does one build

the type corresponding to t without the label `B.

(Camlp4 is not an option...)

Regards,

Till Varoquaux

_______________________________________________

Caml-list mailing list. Subscription management:

http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list

Archives: http://caml.inria.fr

Beginner's list: http://groups.yahoo.com/group/ocaml_beginners

Bug reports: http://caml.inria.fr/bin/caml-bugs

May 14, 2007, 6:55:54 AM5/14/07

to caml...@yquem.inria.fr

> Given a polymorphic variant type t with a label `B how does one build

> the type corresponding to t without the label `B.

> the type corresponding to t without the label `B.

So that you could write something like:

type t = [ `A | `B | `C ]

let f x =

match x with

`B -> (* x has type t *)

| #(t minus [ `B ]) as x -> (* x has type [ `A | `C ] *)

I end up having to write lots of tedious extra types to achieve that

normally... I'd find a subtraction syntax very handy too.

On a similar subject, am I the only person who finds I often need to take a

fixed polymorphic variant value and coerce it so that it can just accept

more constructors e.g. (seriously contrived example)...

type t = [ `A | `B | `C ]

let f (x : t) =

match x with

`A -> `D

| _ -> (x : t :> [> t ])

Something more concise than (x : t :> [> t ]) would be nice: e.g. (x ::> t)

But perhaps that really is a job for camlp4!

David

May 15, 2007, 12:44:46 AM5/15/07

to dra-...@metastack.com

From: "David Allsopp" <dra-...@metastack.com>

> > Given a polymorphic variant type t with a label `B how does one build

> > the type corresponding to t without the label `B.

>

> So that you could write something like:

>

> type t = [ `A | `B | `C ]

>

> let f x =

> match x with

> `B -> (* x has type t *)

> | #(t minus [ `B ]) as x -> (* x has type [ `A | `C ] *)

>

> I end up having to write lots of tedious extra types to achieve that

> normally... I'd find a subtraction syntax very handy too.

There is no theoretical difficulty in adding this (when t is defined),

but this would mean yet more syntax...

I would be curious to see code where this becomes such a pain.

In my view, having to name this type should help clarity.

> On a similar subject, am I the only person who finds I often need to take a

> fixed polymorphic variant value and coerce it so that it can just accept

> more constructors e.g. (seriously contrived example)...

>

> type t = [ `A | `B | `C ]

>

> let f (x : t) =

> match x with

> `A -> `D

> | _ -> (x : t :> [> t ])

>

> Something more concise than (x : t :> [> t ]) would be nice: e.g. (x ::> t)

> But perhaps that really is a job for camlp4!

Indeed, this one is just about syntactic sugar, so camlp4 can do it.

An alternative without new syntax would be to let

(x :> [> t]) mean (x : [< t] :> [> t]),

but this would break the invariant that coercions always work when the

coerced value is already an instance of the target type (not that

anybody uses this invariant...)

Jacques Garrigue

May 15, 2007, 5:47:00 AM5/15/07

to Jacques Garrigue, caml...@yquem.inria.fr

A SQL converter I'm writing ends up with these two types:

type t' = [ `CreateDB of ...

| `CreateType of ...

| `CreateTable of ...

| `CreateFunction of ...

| `CreateProcedure of ...

| `CreateRole of ...

| `Eof

]

type t = [ `Comment of ...

| `Block of ...

| `Blank

| t'

]

Solely so that further down the code I can say:

match elt with

`Block block -> ...

| `Comment comment -> ...

| `Blank -> ...

| #t' as elt ->

(* specific code only relevant when elt <> `Block, `Comment or `Blank *)

match elt with

(* Remaining match cases not including the three checked already *)

type t' is only defined for use in # matches (the actual code will translate

a variant-SQL script to T-SQL and is compacting custom blocks of unparsed

SQL code, comments and blank lines into a single `Block before parsing

actual clauses that it understands how to translate). If I don't use #t'

then, as far as I can see, I must either add redundant matches to the second

match block to prevent match warnings (and so have an "Unexpected" exception

or failwith "programmer is an idiot" call for these 'unreachable' match

clauses) or duplicate a lot of code between the match clauses.

I equally get it with certain error handling matches:

e.g. (contrived again, but I'd have to send a lot of code for a real

version... this comes up with error handling between read/write functions in

a socket stream! )

type t' = [ `B | `C ]

type t = [ `A | t' ]

val f : int -> [ `Success of int | `Error of t ]

exception SpecialExceptionForA

exception GeneralException of int

(* NB matter of personal taste: I don't consider x in this function but I

know that's not everyone's view!! *)

let g x =

match x with

`B -> 0

| `C -> 1

match f 0 with

`Success int -> true

| `Error `A -> raise SpecialExceptionForErrorA

| `Error (#t' as x) -> raise (GeneralException(g x))

It would be, I think, clearer (especially when considering ocamldoc

comments**) for the type to be:

type t = [ `A | `B | `C ]

..

match f 0 with

`Success int -> true

| `Error `A -> ...

| `Error (#t minus [ `A ] as x) -> ...

So, in summary, my irritation lies with the need to create extra types just

for the # matches. But I am very fussy :o)

Of course, this is related to a previous thread: http://tinyurl.com/yp7rvy

.. for polymorphic variants, it would be inferring the subtraction of `A

from the type of x automatically because of the previous match clause.

David

** Furthermore, I can't even hide these redundant types in the

implementation:

Foo.mli

type t = [ `A | `B ]

Foo.ml

type t' = [ `A ]

type t = [ `A | t' ]

Is not valid even though t is /effectively/ the same p-variant in both the

mli and .ml

May 15, 2007, 6:23:26 AM5/15/07

to caml...@yquem.inria.fr

David Allsopp wrote:

> ** Furthermore, I can't even hide these redundant types in the

> implementation:

>

> Foo.mli

>

> type t = [ `A | `B ]

>

> Foo.ml

>

> type t' = [ `A ]

> type t = [ `A | t' ]

>

> Is not valid even though t is /effectively/ the same p-variant in both the

> .mli and .ml> ** Furthermore, I can't even hide these redundant types in the

> implementation:

>

> Foo.mli

>

> type t = [ `A | `B ]

>

> Foo.ml

>

> type t' = [ `A ]

> type t = [ `A | t' ]

>

> Is not valid even though t is /effectively/ the same p-variant in both the

>

That's maybe just because of a typo (you wrote `A for `B below) ?

This seems to works with 3.09:

# module M : sig type t = [ `A | `B ] end = struct type t' = [`A] type t

= [`B | t' ] end;;

module M : sig type t = [ `A | `B ] end

Frédéric

May 15, 2007, 1:05:24 PM5/15/07

to caml...@yquem.inria.fr

> That's maybe just because of a typo (you wrote `A for `B below) ?

>

> This seems to works with 3.09:

>

> # module M : sig type t = [ `A | `B ] end = struct type t' = [`A] type t

> = [`B | t' ] end;;

> module M : sig type t = [ `A | `B ] end

>

>

> This seems to works with 3.09:

>

> # module M : sig type t = [ `A | `B ] end = struct type t' = [`A] type t

> = [`B | t' ] end;;

> module M : sig type t = [ `A | `B ] end

>

<blush> my bad! It was indeed a typo...

David

Reply all

Reply to author

Forward

0 new messages

Search

Clear search

Close search

Google apps

Main menu