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.1 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 1DD12BC0A for ; Thu, 21 Jun 2007 16:08:34 +0200 (CEST) Received: from nz-out-0506.google.com (nz-out-0506.google.com [64.233.162.227]) by discorde.inria.fr (8.13.6/8.13.6) with ESMTP id l5LE8W30020886 for ; Thu, 21 Jun 2007 16:08:33 +0200 Received: by nz-out-0506.google.com with SMTP id s1so490714nze for ; Thu, 21 Jun 2007 07:08:32 -0700 (PDT) DKIM-Signature: a=rsa-sha1; c=relaxed/relaxed; d=gmail.com; s=beta; h=domainkey-signature:received:received:message-id:date:from:to:subject:cc:in-reply-to:mime-version:content-type:content-transfer-encoding:content-disposition:references; b=K34wLieqeED1NjNJsIXx8KEL6G1DJ/ECfAHGZeGkdXejduhOKZJf+lD9wLAdOt4NoUuPMxLhR9eRnKS/qJisuR9JMuOhpdBxdM/Ffha65lzX/mkMwIqvdKFnXn3/Cets+w2Ek62Fg7ApHDIFbqqooYCkMx1aDXbPcgafs1lzf1s= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=beta; h=received:message-id:date:from:to:subject:cc:in-reply-to:mime-version:content-type:content-transfer-encoding:content-disposition:references; b=Bei0gAmg7Jaa+JQNdwcaZv4E+Q6/n09/DiB+OEuFeFv3q+E1l2S5hLLFxummtDczbf0hEmVaOPphEe8KTwgtX2ROKBlF8bg3yIe+oNOFXTsWmEYAT86WdN1Z1VZBF4mtDpjwXYjWGPdxNsI5AXHgCD2sF6tgshCbMUsYrgXeo30= Received: by 10.114.152.17 with SMTP id z17mr1642150wad.1182434911972; Thu, 21 Jun 2007 07:08:31 -0700 (PDT) Received: by 10.114.235.10 with HTTP; Thu, 21 Jun 2007 07:08:31 -0700 (PDT) Message-ID: <875c7e070706210708u2ab3719er6e24f4ec52bf6398@mail.gmail.com> Date: Thu, 21 Jun 2007 10:08:31 -0400 From: "Chris King" To: "Jonathan T Bryant" Subject: Re: [Caml-list] Functors + polymorphism = confusion Cc: caml-list@yquem.inria.fr In-Reply-To: <6372856.1182410172319.JavaMail.jtbryant@valdosta.edu> MIME-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Content-Disposition: inline References: <6372856.1182410172319.JavaMail.jtbryant@valdosta.edu> X-j-chkmail-Score: MSGID : 467A8661.000 on discorde : j-chkmail score : X : 0/20 1 0.000 -> 1 X-Miltered: at discorde with ID 467A8661.000 by Joe's j-chkmail (http://j-chkmail . ensmp . fr)! X-Spam: no; 0.00; functors:01 polymorphism:01 functor:01 functor:01 sig:01 val:01 derivation:01 syntax:01 sig:01 val:01 struct:01 restricting:01 wrote:01 abstract:01 abstract:01 The important thing to remember with Caml modules is that it will hide type relations unless you tell it otherwise: On 6/21/07, Jonathan T Bryant wrote: > module BindFunction : > functor (F : PolyFunction) -> > functor (A : Message) -> > functor (B : Message) -> > Function Recall your definition of Function above: > module type Function = > sig > module A : Message > module B : Message > val f : A.t -> B.t > end Here modules A and B are of type Message, which define an abstract type t. Caml doesn't automatically fill in this type definition for you, so the module returned by BindFunction will only be able to operate over a pair of abstract types. Not good! The solution to this (which you will see used in functorized library modules such as Map and Set) is to add the derivation of types A.t and B.t to your output signature using the "with" syntax: module BindFunction : functor (F : PolyFunction) -> functor (A : Message) -> functor (B : Message) -> Function with type A.t = A.t and type B.t = B.t This tells Caml to modify the Function signature so that, instead of having abstract types A.t and B.t, it contains those type equations. So the actual output signature will look like this: sig module A : sig type t = A.t val to_string : t -> string val of_string : string -> t end module B : sig type t = B.t val to_string : t -> string val of_string : string -> t end val f : A.t -> B.t end > module Parallelize : functor (F : Function) -> ParallelFunction You'll need to do the same thing here, tell Caml that the abstract types within ParallelFunction are really the same as the types in F: module Parallelize : functor (F : Function) -> ParallelFunction with type A.t = F.A.t and type B.t = F.B.t Note that you can actually do this at the module level, too: module Parallelize : functor (F : Function) -> ParallelFunction with module A = F.A and module B = F.B In this case it only serves to save a couple keystrokes but it is useful if either (a) you have lots of types you want to copy en masse to the output signature or (b) the output signature contains a restricted form of one of the input modules and you want to retain the extra types and values. > module BindMessage = > functor (P : PolyMessage) -> > functor (M : Message) -> > struct > module P = P (M) > type t = M.t P.t > let to_string m = P.to_string m > let of_string s = P.of_string s > end Because you are not restricting the output signatures in your implementation, Caml preserves the type relationships (it only discards them at the interface level). However if you did specify the output signature here (as the library modules do) you would need to use the same construct. Hope this helps... I can attest that this stuff is pretty confusing at first. :) - Chris