caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
From: skaller <skaller@users.sourceforge.net>
To: Jon Harrop <jon@ffconsultancy.com>
Cc: caml-list@yquem.inria.fr
Subject: Re: [Caml-list] Custom operators in the revised syntax
Date: Sat, 12 May 2007 15:45:13 +1000	[thread overview]
Message-ID: <1178948713.14691.89.camel@rosella.wigram> (raw)
In-Reply-To: <200705120547.06083.jon@ffconsultancy.com>

On Sat, 2007-05-12 at 05:47 +0100, Jon Harrop wrote:

> > I have only seen one algorithm for this an it was
> > extremely complicated. If you know a better way I'd
> > sure like to know what it is.
> 
> AFAIK, you just change the unify to intersect sets of types. 

I have no idea how to unify in the presence of (undiscriminated)
setwise union of polymorphic types. It seems a little easier
if the types are restricted to a finite set of non-polymorphic
types.

> I assume the 
> implementation of polymorphic variants already does this, so take that and 
> make it enforce a single type contructor at function boundaries (maybe 
> defaulting in some cases). If you "polymorphic variant" has more than one 
> constructor then there is an ambiguity and you flag an error asking for a 
> type annotation.

The difference is that polymorphic variants HAVE constructors.
But we're talking about types *without* constructors.

In Felix, the (Ocaml) term combinators actually support typesets.
But the unification engine just throws up when it sees them :)

During overload resolution, you CAN use typesets as constraints.
For example:

	typedef ints = typesetof(int, long);
	fun f[t in ints]: t * t -> t = "$1+$2";

	print$ f 1; // OK!
	print$ f 1L; // OK!
	print$ f 1.0; // ERROR

	fun g[t in ints](x:t)=> f x; // ERORR

The last line illustrates the lack of propagation: the type
of x is actually just 't' at the point f is applied,
and t isn't in the set ints.

The way it works is the argument is first matched against the
unconstrained type (by unification), and then the constraint
such as:

	int in typeset(int,long)

is checked: if it fails that overload candidate is rejected
(but another may still match).

In principle the correct 'subtyping' rule is to use a subset
(or superset depending on +/- position I guess) so that
it should be possible in this case to propagate and make
the function g above work.

The problem is that once you introduce polymorphism,
the type of one function can depend on the type of another,
but that type isn't known until that other is actually
instantiated.

This can not be handled 'properly' by just adding typesets to the 
type system because that would be too general: it fails to
record the dependencies. For example in the f/g case above,
the type of g is NOT

	g: ints -> ints

but rather

	g: { int -> int; long -> long }

and now consider a harder case like:

	t in ints. t * t = { int * int; long * long }

which is quite different to

	ints * ints = { int * int; int * long; long * int; long * long }

So roughly .. we're talking about a unification engine that
can propagate constraints, and a type system which would
seem to at least need to be second order. 

As I said I think this is possible for finite ground types,
but in the presence of polymorphism unification would not be
able to reduce many terms. In turn, this would make overloading
such cases impossible.

In Felix, overloading is done polymorphically, and can't
vary depending on the instantiation of type variables
(you can do that with typeclasses though).

But unless you instantiate the type variables, you can't
reduce the terms. It isn't clear it is even possible to
normalise them for equality check, let alone tell if
one is a specialisation of another.

The result, in Felix, is that overloading would have to
return a SET of functions instead of a single one,
since several functions 'might' match the argument type.
And the set could be large -- it seems exponential in
the length of a call chain. Ouch.

If ANYONE knows an algorithm that can do unification with
sets of types, that is, with a union type, I'd sure like
to know it!

> .NET provides run-time type information so I assume the compiler specializes 
> when types are static and resorts to run-time dispatch otherwise.

That seems right. I think G'Caml tried to do that was well.

> > and this kind of constraint, unfortunately, doesn't propagate
> > (i.e. the above isn't really a type). Propagating ground
> > type sets is actually easy, but once you have higher orders
> > it is probably undecidable.
> 
> I hadn't thought of that. I just discovered that you cannot add vectors of 
> vectors in F#, so it is probably 1st order only.

Hmm, that's a bit surprising if your explanation above is correct,
that is, if it resorts to dynamic typing if it can't resolve
statically.


-- 
John Skaller <skaller at users dot sf dot net>
Felix, successor to C++: http://felix.sf.net


  reply	other threads:[~2007-05-12  5:45 UTC|newest]

Thread overview: 38+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-05-10 20:55 Nicolas Pouillard
2007-05-10 21:35 ` [Caml-list] " Loup Vaillant
2007-05-10 22:25   ` Nicolas Pouillard
2007-05-11  6:52 ` Stefano Zacchiroli
2007-05-11 13:14 ` dmitry grebeniuk
2007-05-11 14:15   ` Loup Vaillant
2007-05-11 14:37     ` Jon Harrop
2007-05-11 14:46       ` Nicolas Pouillard
2007-05-12  2:48         ` Jon Harrop
2007-05-12  4:40           ` skaller
2007-05-12  4:47             ` Jon Harrop
2007-05-12  5:45               ` skaller [this message]
2007-05-12  5:59                 ` Jon Harrop
2007-05-12  6:43                   ` skaller
2007-05-12 10:22             ` Richard Jones
2007-05-13 15:42               ` Arnaud Spiwack
2007-05-13 16:04                 ` ls-ocaml-developer-2006
2007-05-13 20:08                   ` Nicolas Pouillard
2007-05-12  9:49           ` Nicolas Pouillard
2007-05-12 10:09             ` Jon Harrop
2007-05-11 14:52       ` Loup Vaillant
2007-05-11 18:32         ` skaller
2007-05-12  4:48         ` Jon Harrop
2007-05-11 18:23       ` skaller
2007-05-11 14:40     ` Nicolas Pouillard
2007-05-11 18:22     ` skaller
2007-05-11 14:36   ` Nicolas Pouillard
2007-05-11 14:47     ` brogoff
2007-05-11 14:51       ` Nicolas Pouillard
2007-05-11 18:25         ` brogoff
2007-05-11 20:37           ` Nicolas Pouillard
2007-05-12 22:54           ` Nicolas Pouillard
2007-05-13  0:27             ` ketti
2007-05-13  1:05               ` Christian Stork
2007-05-13 10:50                 ` Nicolas Pouillard
2007-05-13  5:52             ` brogoff
2007-05-13  7:36               ` skaller
2007-05-13 13:12                 ` Jacques Carette

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=1178948713.14691.89.camel@rosella.wigram \
    --to=skaller@users.sourceforge.net \
    --cc=caml-list@yquem.inria.fr \
    --cc=jon@ffconsultancy.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).