caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
From: skaller <skaller@ozemail.com.au>
To: "Beck01, Wolfgang" <BeckW@t-systems.com>
Cc: caml-list@inria.fr
Subject: RE: [Caml-list] strange behaviour  with variants and "cannot be g eneralized"
Date: 10 Sep 2003 19:48:42 +1000	[thread overview]
Message-ID: <1063187322.2119.118.camel@localhost.localdomain> (raw)
In-Reply-To: <ADD42C8394EBD4118A3D0003470C18F00950F3D8@G9JJT.mgb01.telekom.de>

On Wed, 2003-09-10 at 17:10, Beck01, Wolfgang wrote:
> Didier Remy [mailto:remy@morgon.inria.fr] 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

becomes

	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 caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners


  parent reply	other threads:[~2003-09-10  9:49 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2003-09-10  7:10 Beck01, Wolfgang
2003-09-10  8:12 ` Fernando Alegre
2003-09-10  8:18 ` Jacques Garrigue
2003-09-10 10:39   ` skaller
2003-09-10  9:48 ` skaller [this message]
2003-09-10 11:34   ` Frederic De Jaeger
  -- strict thread matches above, loose matches on Subject: below --
2003-09-09 14:13 Beck01, Wolfgang
2003-09-09 19:17 ` Didier Remy

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1063187322.2119.118.camel@localhost.localdomain \
    --to=skaller@ozemail.com.au \
    --cc=BeckW@t-systems.com \
    --cc=caml-list@inria.fr \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).