caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
From: "Chris King" <colanderman@gmail.com>
To: "Christopher L Conway" <cconway@cs.nyu.edu>
Cc: caml-list@yquem.inria.fr
Subject: Re: [Caml-list] wrapping parameterized types
Date: Thu, 3 May 2007 19:16:42 -0400	[thread overview]
Message-ID: <875c7e070705031616w50ca595m2e55bda049ba7aa6@mail.gmail.com> (raw)
In-Reply-To: <4a051d930705031531m396e42e7i6212137e2fb9cd53@mail.gmail.com>

On 5/3/07, Christopher L Conway <cconway@cs.nyu.edu> wrote:
> # let app_to_mylist f = function Intlist x -> f x | Strlist x -> f x ;;
> Characters 65-66:
>   let app_to_mylist f = function Intlist x -> f x | Strlist x -> f x ;;
>                                                                    ^
> This expression has type string list but is here used with type int list

The problem is, when O'Caml tries to infer the type of f, it
arbitrarily chooses string list -> 'a and dies when it finds it
applied to an int list.  And although the type you want is 'a list ->
'b, O'Caml certainly won't infer this, since you'd have polymorphic
functions like that popping up every time you made a type mistake
(this is the same reason why non-homogenous lists of objects aren't
automatically coerced to a union of their types).

So you might expect that the following would work:

let app_to_mylist (f: 'a list -> 'b) = function Intlist x -> f x |
Strlist x -> f x ;;

but this doesn't force O'Caml to do anything, it's still free to
refine 'a to int or string.  (Just like how if you write "let x: 'a =
5", x is still an int).

The solution is to use existential types.  In a record, you can tell
O'Caml that a particular function _must_ be polymorphic:

type 'b mylistfun = { listfun: 'a. 'a list -> 'b }

Prefixing f's type with "'a." tells O'Caml that 'a is an existential
type variable, meaning that f must be able to work with any 'a.  Note
that 'a doesn't appear in mylistfun's list of type variables (since it
would make no sense to choose a type for 'a).

So armed with mylistfun, you can rewrite app_to_mylist as:

# let app_to_mylist { listfun = f } = function Intlist x -> f x |
Strlist x -> f x;;
val app_to_mylist : 'a mylistfun -> mylist -> 'a = <fun>

and all is well:

#  app_to_mylist { listfun = List.length } (Intlist [1;2;3]);;
- : int = 3

Unfortunately this trick only works with records and objects, so
you're forced to box up the function before handing it to
app_to_mylist.  (I forget the reason why you can't do this in general
but I'm sure someone else can enlighten us both.)

Hope this helps.

- Chris


  reply	other threads:[~2007-05-03 23:16 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-05-03 22:31 Christopher L Conway
2007-05-03 23:16 ` Chris King [this message]
2007-05-04  1:10   ` [Caml-list] " skaller
2007-05-04  8:13     ` Dirk Thierbach
2007-05-04 11:47     ` rossberg
2007-05-04 12:13       ` Andrej Bauer
2007-05-04 13:34         ` Dirk Thierbach
2007-05-04 15:58           ` Christopher L Conway
2007-05-04  1:58   ` Christopher L Conway

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=875c7e070705031616w50ca595m2e55bda049ba7aa6@mail.gmail.com \
    --to=colanderman@gmail.com \
    --cc=caml-list@yquem.inria.fr \
    --cc=cconway@cs.nyu.edu \
    /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).