Version française
Home     About     Download     Resources     Contact us    

This site is updated infrequently. For up-to-date information, please visit the new OCaml website at

Browse thread
RE: [Caml-list] strange behaviour with variants and "cannot be g eneralized"
[ Home ] [ Index: by date | by threads ]
[ Search: ]

[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
Date: 2003-09-10 (09:49)
From: skaller <skaller@o...>
Subject: RE: [Caml-list] strange behaviour with variants and "cannot be g eneralized"
On Wed, 2003-09-10 at 17:10, Beck01, Wolfgang wrote:
> Didier Remy [] wrote:
> > Here is some explanation of 
> > 
> >  1) what happened in version 3.06 and 
> >  2) how this is related to a relaxed form of value restriction, 
> >  3) which is actually orthogonal to the solution implemented in 3.07
> > 
> > [detailed explanation omitted]
> well, I was not aware that compilation of polymorphic variants is an area
> of ongoing research. In the OCaml manual, they are not mentioned under
> "Language extensions" but as a section in the chapter "An introduction to
> Objective Caml". There is a statement
>     "In programs, polymorphic variants work like usual ones. You just
>     have to prefix their names with a backquote character `."
> and this is not true, at least in 3.06. After spending another evening
> with weird type errors, I replaced polymorphic variants with ordinary
> ones. My project looks uglier now since I had to split up some files,
> but at least it compiles and runs.

I use polymorphic variants extensively. Technically, you have to add
the backquote ` and also [] in the type definitions:

	type x = X of int


	type x = [ `X of int ]

If you do both these changes, everything should work, plus
or minus some casts. Occasionally, you will have to
cast some value using single or double coercions:

	(a:t)   (* annotation only *)
	(a:>t)  (* conversion *)
	(a:u:>t) (* double conversion *)

This is quite rare, but it is sometimes necessary
when you have wildcard matches like:

let f e = 
	match e with
	| `A -> ..
	| _ -> ...

How can the compiler know what the type here really is 
supposed to be? Unlike ordinary variants, the tag `A can
occur in any number of types.

if you now use that expression in a context requiring
type [`A | `B] you'll get an error. Perhaps e contained
the tag `C?

So with polymorphic variants, because the typing is so
flexible, you have to use type
annotations and casts a bit more often than ordinary variants.

The situation is entirely different if your code has an
error in it! In this case, you will often get
vvvvvvvveeeeeeeerrrrrrrryyyyyyy long error messages:
in my case hundreds of lines long usually.

This really is a problem, particularly when the source
of the problem could easily be diagnosed in some
cases: for example a missing tag, or a tag with
an incompatible argument. The compiler *does* detect
some of these cases (but not enough yet).

You are therefore advised to make smaller changes to
your program before recompiling, since then you know
the error is in a place you just changed.

Are polymorphic variants worth it?

For simple uses, the answer is no. However,
in a complex program such as a compiler which
can benefit from a large number of types which
are typing different subsets of a universal term
type, polymorphic variants are indispensible.

They not only allow more accurate typing,
they're also *faster*. For example,
consider a restriction of a term type
in which rewriting rules reduce some 
sugars to lower level primitive
(for example macro expansion).

Either you forgoe a typing in which macros
cannot be in the output type of the rewriting,
or you have to convert all the terms from one
variant type to another like

	match e with 
	| A -> AA
	| B -> BB
	| C i -> CC i
	| Macro x -> f x..
which is slower than the polymorphic variant version:

	match e with
	| `Macro x -> f x
	| #nonmacro as x -> x

since there is no need deconstruct and reconstruct
the isomorphic terms, since the isomorphism is
represented by value equality: the same tags

	`A, `B, `C of int

can occur in both the input and output types.

To unsubscribe, mail Archives:
Bug reports: FAQ:
Beginner's list: