Browse thread
Why type inference fails in this code
[
Home
]
[ Index:
by date
|
by threads
]
[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
Date: | 2009-10-09 (08:22) |
From: | Virgile Prevosto <virgile.prevosto@m...> |
Subject: | Re: [Caml-list] Why type inference fails in this code |
Hello, Le ven. 09 oct. 2009 09:09:35 CEST, Gabriel Kerneis <kerneis@pps.jussieu.fr> a écrit : > On Fri, Oct 09, 2009 at 07:25:41AM +0200, rouanvd@softwarerealisations.com wrote: > > ====================================================== > > type t = MyInt of int | MyFloat of float | MyString of string ;; > > > > let foo printerf = function > > | MyInt i -> printerf string_of_int i > > | MyFloat x -> printerf string_of_float x > > | MyString s -> printerf (fun x -> x) s > > ;; > > ====================================================== > > Type-inference has nothing to do with it, it's the type system itself > which fails. > > What is the type you would expect? I guess: > (forall 'a. ('a -> string) -> 'a -> 'b) -> t -> 'b > > This is impossible with Ocaml: you cannot have a universal quantifier, > type variables are existantially quantified. > 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 = MyInt of int | MyFloat of float | MyString of string ;; module type Printerf=functor(A:sig type t val to_string: t -> string end) -> sig val print: A.t -> unit end module Foo(Printerf:Printerf) = struct let foo = function | MyInt i -> let module M = Printerf(struct type t = int let to_string = string_of_int end) in M.print i | MyFloat x -> let module M = Printerf(struct type t = float let to_string = string_of_float end) in M.print x | MyString s -> let module M = Printerf(struct type t = string let to_string = 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 = function > | MyInt i -> printerf (string_of_int i) > | MyFloat x -> printerf (string_of_float x) > | MyString s -> printerf s > ;; -- E tutto per oggi, a la prossima volta. Virgile