caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
From: Jeremy Yallop <yallop@gmail.com>
To: rouanvd@softwarerealisations.com
Cc: caml-list@yquem.inria.fr
Subject: Re: [Caml-list] Why type inference fails in this code
Date: Fri, 9 Oct 2009 11:22:59 +0100	[thread overview]
Message-ID: <c638851a0910090322q5de28740la78c1116d84844ed@mail.gmail.com> (raw)
In-Reply-To: <53322.41.177.16.252.1255065941.squirrel@41.177.16.252>

Dear Rouan,

2009/10/9  <rouanvd@softwarerealisations.com>:
> 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

This fails because the variable "printerf" is used at different types
inside the body of foo.  OCaml's type system requires function
arguments to be used at the same type everywhere they appear in the
body of the function.  The reason is simple: without this restriction
type inference becomes undecidable.

The most reasonable type for foo seems like the following:

   forall 'b. (forall 'a. ('a -> string) -> 'a -> 'b) -> t -> 'b

which is the type of a function that constructs a value of type 'b
from a value of type t using its argument function; this argument
function takes a printer for any type 'a and a value of type 'a and
constructs a value of type 'b.

We can make two adjustments to "foo" to turn it into something that
OCaml will accept.  The first adjustment is to turn the argument
"printerf" into an object with a single method; polymorphic types
(i.e. types that use "forall") in OCaml must be wrapped in object or
record types.  The second adjustment is to provide a type signature,
which changes the impossible problem of type /inference/ into the
easier problem of type /checking/.  Here is the revised definition:

  let foo : < p : 'a . ('a -> string) -> 'a -> 'b > -> t -> 'b =
    fun printerf -> function
      | MyInt i    -> printerf#p string_of_int i
      | MyFloat x  -> printerf#p string_of_float x
      | MyString s -> printerf#p (fun x -> x) s

In order to call this function we must, of course, ensure that the
first argument is an object.  Here is a simple example, where the
argument just returns the constructed string:

   foo (object method p : 'a. ('a -> string) -> 'a -> string = fun x
-> x end) (MyInt 3)

Hope this helps,

Jeremy.


      parent reply	other threads:[~2009-10-09 10:22 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-10-09  5:25 rouanvd
2009-10-09  6:54 ` [Caml-list] " Vincent Aravantinos
2009-10-09  7:09 ` Gabriel Kerneis
2009-10-09  8:22   ` Virgile Prevosto
2009-10-09  8:41     ` Gabriel Kerneis
2009-10-09  8:59       ` Gabriel Kerneis
2009-10-09 10:22 ` Jeremy Yallop [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=c638851a0910090322q5de28740la78c1116d84844ed@mail.gmail.com \
    --to=yallop@gmail.com \
    --cc=caml-list@yquem.inria.fr \
    --cc=rouanvd@softwarerealisations.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).