From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.1.3 (2006-06-01) on yquem.inria.fr X-Spam-Level: X-Spam-Status: No, score=0.9 required=5.0 tests=AWL,SPF_NEUTRAL autolearn=disabled version=3.1.3 X-Original-To: caml-list@yquem.inria.fr Delivered-To: caml-list@yquem.inria.fr Received: from mail2-relais-roc.national.inria.fr (mail2-relais-roc.national.inria.fr [192.134.164.83]) by yquem.inria.fr (Postfix) with ESMTP id C2D09BBAF for ; Fri, 9 Oct 2009 10:22:27 +0200 (CEST) X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AloBAAqQzkqBaB4imWdsb2JhbACbAwEBAQEBCAsKBxO/A4IxgXkE X-IronPort-AV: E=Sophos;i="4.44,530,1249250400"; d="scan'208";a="34573789" Received: from mx1.polytechnique.org ([129.104.30.34]) by mail2-smtp-roc.national.inria.fr with ESMTP/TLS/ADH-AES256-SHA; 09 Oct 2009 10:22:20 +0200 Received: from is010235 (is010235.intra.cea.fr [132.166.133.142]) (using TLSv1 with cipher DHE-RSA-AES128-SHA (128/128 bits)) (No client certificate requested) by ssl.polytechnique.org (Postfix) with ESMTP id 7F6771400008A for ; Fri, 9 Oct 2009 10:22:19 +0200 (CEST) Date: Fri, 9 Oct 2009 10:22:18 +0200 From: Virgile Prevosto To: caml-list@yquem.inria.fr Subject: Re: [Caml-list] Why type inference fails in this code Message-ID: <20091009102218.639677c8@is010235> In-Reply-To: <20091009070935.GA5141@kerneis.info> References: <53322.41.177.16.252.1255065941.squirrel@41.177.16.252> <20091009070935.GA5141@kerneis.info> X-Mailer: Claws Mail 3.6.1 (GTK+ 2.16.1; i486-pc-linux-gnu) Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable X-AV-Checked: ClamAV using ClamSMTP at svoboda.polytechnique.org (Fri Oct 9 10:22:19 2009 +0200 (CEST)) X-Org-Mail: virgile.prevosto.1996@polytechnique.org X-Spam: no; 0.00; inference:01 0200,:01 foo:01 forall:01 ocaml:01 quantifier:01 quantified:01 ocaml:01 quantified:01 existential:01 functors:01 haskell's:01 functor:01 sig:01 val:01 Hello, Le ven. 09 oct. 2009 09:09:35 CEST, Gabriel Kerneis a =C3=A9crit : > On Fri, Oct 09, 2009 at 07:25:41AM +0200, rouanvd@softwarerealisations.co= m wrote: > > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D > > type t =3D MyInt of int | MyFloat of float | MyString of string ;; > >=20 > > let foo printerf =3D function > > | MyInt i -> printerf string_of_int i > > | MyFloat x -> printerf string_of_float x > > | MyString s -> printerf (fun x -> x) s > > ;; > > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D >=20 > Type-inference has nothing to do with it, it's the type system itself > which fails. >=20 > What is the type you would expect? I guess: > (forall 'a. ('a -> string) -> 'a -> 'b) -> t -> 'b >=20 > This is impossible with Ocaml: you cannot have a universal quantifier, > type variables are existantially quantified. >=20 Well, I'm afraid this the other way round: a polymorphic type in Ocaml is implicitly universally quantified: (fun x->x : 'a -> 'a) means the identity function can be applied to an argument of any type, not that there exists a type 'a on which you can apply it. In addition, the desired type for printerf is indeed an existential one (printerf: exists 'a. 'a -> string -> 'a -> 'b): you don't want the first argument to convert any type to a string, just the type of the second argument. A possible but very heavy solution would be to use functors and local modules everywhere (I guess that Haskell's typeclasses would help here). type t =3D MyInt of int | MyFloat of float | MyString of string ;; module type Printerf=3Dfunctor(A:sig type t val to_string: t -> string end) -> sig val print: A.t -> unit end module Foo(Printerf:Printerf) =3D struct let foo =3D function | MyInt i -> let module M =3D Printerf(struct type t =3D int let to_string =3D string_of_int end) in M.print i | MyFloat x -> let module M =3D Printerf(struct type t =3D float let to_string =3D string_of_float end) in M.print x | MyString s -> let module M =3D Printerf(struct type t =3D string let to_string =3D fun x -> x end) in M.print s end ;; but personally I'd do the same thing as you: > In you very specific case, though, I guess refactoring it is possible: > let foo printerf =3D function > | MyInt i -> printerf (string_of_int i) > | MyFloat x -> printerf (string_of_float x) > | MyString s -> printerf s > ;; --=20 E tutto per oggi, a la prossima volta. Virgile