caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
From: Jacques Garrigue <garrigue@math.nagoya-u.ac.jp>
To: yminsky@gmail.com
Cc: caml-list@inria.fr
Subject: Re: [Caml-list] -principal
Date: Fri, 3 May 2013 10:28:30 +0900	[thread overview]
Message-ID: <7EC5410C-F995-4353-8DC1-BA7A3EABC101@math.nagoya-u.ac.jp> (raw)
In-Reply-To: <CADKNfh+c85f1R3BFwabbznEBCxbVnamQzdunkawm8B_UnhndWQ@mail.gmail.com>

On 2013/05/03, at 6:16, Yaron Minsky <yminsky@gmail.com> wrote:

> Can anyone describe the pluses and minuses of turning on -principal?
> Is it considered to be good practice for codebases that are compatible
> with it?  Can it change behavior of currently working code?

Turning on -principal allows detecting "risky" uses of type information to
help type inference.
By risky I mean that success or failure of type inference may depend
on the order in which subexpressions are typed.
This kind of type information is only used by a limited number of features:
* polymorphic methods
* using different order of labeled arguments in a function
* some discarding of optional arguments
* choice of the source type in a coercion (i.e. automatic upgrading of
   (expr :> t2) into (expr : t1 :> t2) when the type of expr is closed).
  This is particularly useful for private type abbreviations.
* GADTs
* disambiguation of record field and constructor names (new in trunk)

The technical definition is based on polymorphism, but the intuition
is that type information follows the (functional) flow of data, even going
through polymorphic functions (being conservative when merging flows).
So a simple way to understand is: supposing that type annotation physically
adds type information to the expression they decorate, will all values
reaching the use point be decorated?
It also flows backward (the expected type is propagated), but does not
go through functions in that case.

# type t = < id: 'a. 'a -> 'a >;;
type t = < id : 'a. 'a -> 'a >
# let f (x : t) = x, x#id;;     (* safe code: the type of x is known at all its use points *)
val f : t -> t * ('a -> 'a) = <fun>
# let f x = (x : t), x#id;;     (* unsafe code: the type is only known because typing goes from left to right *)
Warning 18: this use of a polymorphic method is not principal.
val f : t -> t * ('a -> 'a) = <fun>
# let f x = x#id, (x : t);;    (* just exchanging the members of the pair causes a failure *)
Error: This expression has type < id : 'a; .. >
       but an expression was expected of type t
       The universal variable 'a0 would escape its scope

In an ideal world, I would suggest systematically using -principal, as it makes
the notion of "known type" well-defined.
However, there are drawbacks to -principal
* type inference is slower (more copying occurs)
* cmi's become bigger
The first point is mainly a problem if you use objects.
The second one if you have already problems with cmi size (again, mostly objects)

As a result the suggested approach is to only compile with -principal once in a while.
This is reasonable because if compiling with -principal works, in theory it is guaranteed
that the program will be accepted without -principal too. Of course the semantics do
not change.

However there is a difficulty: since the generated cmi's may differ, in general one
has to maintain completely separate builds.
If you have a complete set of mli's, then a solution is to always compile mli's with
(or without) -principal. (Compiling the mli without principal may in theory cause
propagation to fail in some cases, but you are on the safe side, and I have
never observed it)

So yes, it is good practice. But I'm afraid few invested the effort in doing it.
Looking at the features you use in Core, this may be a good idea to try.
(My understanding is that Lexifi tried, but they had problems because they
use big object types).
By the way, the ocaml compiler itself doesn't use any of the above features,
so it is not directly concerned.

Jacques Garrigue


      reply	other threads:[~2013-05-03  1:28 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-05-02 21:16 Yaron Minsky
2013-05-03  1:28 ` Jacques Garrigue [this message]

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=7EC5410C-F995-4353-8DC1-BA7A3EABC101@math.nagoya-u.ac.jp \
    --to=garrigue@math.nagoya-u.ac.jp \
    --cc=caml-list@inria.fr \
    --cc=yminsky@gmail.com \
    /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).