From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Delivered-To: caml-list@yquem.inria.fr Received: from concorde.inria.fr (concorde.inria.fr [192.93.2.39]) by yquem.inria.fr (Postfix) with ESMTP id 18C24BB91 for ; Mon, 10 Jan 2005 01:24:04 +0100 (CET) Received: from pauillac.inria.fr (pauillac.inria.fr [128.93.11.35]) by concorde.inria.fr (8.13.0/8.13.0) with ESMTP id j0A0O3fx008500 for ; Mon, 10 Jan 2005 01:24:03 +0100 Received: from concorde.inria.fr (concorde.inria.fr [192.93.2.39]) by pauillac.inria.fr (8.7.6/8.7.3) with ESMTP id BAA01330 for ; Mon, 10 Jan 2005 01:24:03 +0100 (MET) Received: from smtp1.adl2.internode.on.net (smtp1.adl2.internode.on.net [203.16.214.181]) by concorde.inria.fr (8.13.0/8.13.0) with ESMTP id j0A0O0uf008491 for ; Mon, 10 Jan 2005 01:24:02 +0100 Received: from [192.168.1.200] (ppp201-179.lns1.syd3.internode.on.net [203.122.201.179]) by smtp1.adl2.internode.on.net (8.12.9/8.12.9) with ESMTP id j0A0Nn3D093287; Mon, 10 Jan 2005 10:53:54 +1030 (CST) Subject: Re: [Caml-list] generic functions From: skaller Reply-To: skaller@users.sourceforge.net To: Brian Hurt Cc: wiedergaenger@fastmail.fm, caml-list In-Reply-To: References: Content-Type: text/plain Message-Id: <1105316629.2647.119.camel@pelican.wigram> Mime-Version: 1.0 X-Mailer: Ximian Evolution 1.2.2 (1.2.2-4) Date: 10 Jan 2005 11:23:49 +1100 Content-Transfer-Encoding: 7bit X-Miltered: at concorde with ID 41E1CB23.000 by Joe's j-chkmail (http://j-chkmail.ensmp.fr)! X-Miltered: at concorde with ID 41E1CB20.000 by Joe's j-chkmail (http://j-chkmail.ensmp.fr)! X-Spam: no; 0.00; caml-list:01 sourceforge:01 wrote:01 foo:01 foo:01 ocaml:01 compilation:01 ocaml:01 overloading:01 inference:01 overloading:01 overload:01 inference:01 deduced:01 variants:01 X-Spam-Checker-Version: SpamAssassin 3.0.0 (2004-09-13) on yquem.inria.fr X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=disabled version=3.0.0 X-Spam-Level: On Mon, 2005-01-10 at 02:48, Brian Hurt wrote: > > let foo (x : int) = x*x;; > > let foo (x : float) = x*.x;; > The short answer is no. For two reasons- first, Ocaml doesn't keep type > information (in most cases) of data at run time, the type information is > used during compilation and then tossed. Which means that Ocaml doesn't > have a way at run time to tell which version of the function to call. And > second, and more importantly, overloading (like you're doing above) would > make type inference extremely difficult if not impossible. Felix is an ML like language which does provide overloading. It does overload resolution at compile time. As Brian mentions this makes full type inference hard, however this isn't nearly so much of a problem as you might think You have to annotate function argument types, however function return types and variable types are still deduced. For this extra effort you get three positive benefits: (a) better documented code (b) better diagnostic messages on type errors (c) overloading In addition, some of the newer Ocaml features like polymorphic variants require type annotations or coercions to be used at times anyhow, and such annotation is common for functions in separately compiled files, which often have interface specifications (which require type annotations). The two principal advantages of inference would appear to be: (a) for quick and dirty code and small functions where the extra clutter would reduce clarity and increase coding time. (b) for complex functions with nasty types The brevity argument is context dependent. I have just written in Felix a function which converts a complex parse tree into a string. This function has to decode around 100 variants from 40 or so types to produce the result. In Felix all these functions are called 'str', and I can just write code like fun str : product_list_t -> string = | product_list_1 (?s,?sl) => str s + " * " + str sl | product_list_2 ?s => str s ; fun str : term_t -> string = | term_1 (?t,?p) => str t + " / " + str p | term_2 (?t,?p) => str t + " % " + str p | term_3 ?pr => str pr ; .. Without overloading I would have to invent a discrete name for each function, which would certainly reflect the argument type, so this is balances out in favour of overloading. In the actual use of the function there is no doubt that overloading is briefer than inference without it, since I can use the 'str' name without knowing which function is applied. In Ocaml, this program would be almost untenable. I would try to avoid this problem by using polymorphic variants instead of ordinary ones (and then write one big 'str' function for all the variants). Bottom line: I have used two similar languages, one with type inference and one with overloading, and in general I could pick between them like this: Overloading (in the Felix and C++ style) only works on direct calls where the function is named. It doesn't work with closures, for example variables containing function values, including parameters. So I would say inference is better when you're doing lots of higher order work, and overloading is better for more mundane industrial applications. BTW: it would be interesting to provide a better integration of both features. G'Caml is one idea. Polymorphic variants are another. In Felix you can write: fun swap(x,y) => y,x; without type annotations: type variables are assumed but they're independent. This precludes code like fun apply(f,x)=> f x; but it is clear some localised inference in this case would allow this. It is also known that overloading CAN work with inference with some contraints -- there is a paper somewhere on Citeseer on this topic (sorry don't have the URL at the moment, if someone finds it please let me know..) -- John Skaller, mailto:skaller@users.sf.net voice: 061-2-9660-0850, snail: PO BOX 401 Glebe NSW 2037 Australia Checkout the Felix programming language http://felix.sf.net