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=1.0 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 discorde.inria.fr (discorde.inria.fr [192.93.2.38]) by yquem.inria.fr (Postfix) with ESMTP id 8195DBC69 for ; Fri, 4 May 2007 03:58:27 +0200 (CEST) Received: from ik-out-1112.google.com (ik-out-1112.google.com [66.249.90.179]) by discorde.inria.fr (8.13.6/8.13.6) with ESMTP id l441wRmm016462 for ; Fri, 4 May 2007 03:58:27 +0200 Received: by ik-out-1112.google.com with SMTP id c29so681150ika for ; Thu, 03 May 2007 18:58:26 -0700 (PDT) DKIM-Signature: a=rsa-sha1; c=relaxed/relaxed; d=gmail.com; s=beta; h=domainkey-signature:received:received:message-id:date:from:sender:to:subject:cc:in-reply-to:mime-version:content-type:content-transfer-encoding:content-disposition:references:x-google-sender-auth; b=AEpY2YbHIv8BXmWjct6UCIE6bF8Ejs1ga86Kl2cnqv6NXgZ7je4yPUOW0Ecjtd0tUB3nDSJoJZIvinjz5sRUwpoimU38teDNvfc71BcRlOKtiQSADLrS5hMQSlRZlHCztXGHrzyKhYJ2sc0exRBnI2m2DHi3omfQlij10nzp670= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=beta; h=received:message-id:date:from:sender:to:subject:cc:in-reply-to:mime-version:content-type:content-transfer-encoding:content-disposition:references:x-google-sender-auth; b=MMPi6Wa6WzO9PnOdJVCTlq9mSsd9Z4e6H59SIr/+dqD1++G+p5VJqXWLFJBpjsjGoI3t/yLJOQhXxfkYq9ipi1upZXXjRtmhiERvEjpwohX9oB6Cz61nLbBKdgZdBKP4szjYAysjz+jw6RA16N8GhaZEcksp44fhxqx9+bZ3TOs= Received: by 10.78.17.1 with SMTP id 1mr1238928huq.1178243906708; Thu, 03 May 2007 18:58:26 -0700 (PDT) Received: by 10.78.156.19 with HTTP; Thu, 3 May 2007 18:58:26 -0700 (PDT) Message-ID: <4a051d930705031858vbd0f819p258ddd6006357f6d@mail.gmail.com> Date: Thu, 3 May 2007 21:58:26 -0400 From: "Christopher L Conway" Sender: christopherleeconway@gmail.com To: "Chris King" Subject: Re: [Caml-list] wrapping parameterized types Cc: caml-list@yquem.inria.fr In-Reply-To: <875c7e070705031616w50ca595m2e55bda049ba7aa6@mail.gmail.com> MIME-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Content-Disposition: inline References: <4a051d930705031531m396e42e7i6212137e2fb9cd53@mail.gmail.com> <875c7e070705031616w50ca595m2e55bda049ba7aa6@mail.gmail.com> X-Google-Sender-Auth: 17e36d744e74a811 X-Miltered: at discorde with ID 463A9343.000 by Joe's j-chkmail (http://j-chkmail . ensmp . fr)! X-Spam: no; 0.00; bug:01 mylist:01 strlist:01 mylist:01 strlist:01 o'caml:01 arbitrarily:01 o'caml:01 popping:01 coerced:01 existential:01 prefixing:01 existential:01 val:01 handing:01 Chris, Thanks! This works! There's one tiny little bug in your suggestion. It should be: let app_to_mylist f = function Intlist x -> f.listfun x | Strlist x -> f.listfun x;; Using pattern matching on the function argument leads right back to the original type instantiation problem. Regards, Chris On 5/3/07, Chris King wrote: > On 5/3/07, Christopher L Conway 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 = > > 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 > >