From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail4-relais-sop.national.inria.fr (mail4-relais-sop.national.inria.fr [192.134.164.105]) by walapai.inria.fr (8.13.6/8.13.6) with ESMTP id p3TD9Lfp026703 for ; Fri, 29 Apr 2011 15:09:22 +0200 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AnkAAF23uk2LEwExhWdsb2JhbACmGAEBAQoLCxsFIIhxrgEBji8FhX6TA4oF X-IronPort-AV: E=Sophos;i="4.64,287,1301868000"; d="scan'208";a="94080161" Received: from infao0809.mpi-sb.mpg.de (HELO hera.mpi-sb.mpg.de) ([139.19.1.49]) by mail4-smtp-sop.national.inria.fr with ESMTP/TLS/AES256-SHA; 29 Apr 2011 15:09:15 +0200 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=mpi-sb.mpg.de; s=mail200803; h=From:To:In-Reply-To:Subject: References:Message-Id:Content-Type:Content-Transfer-Encoding: Mime-Version:Date:Cc; bh=gVr4Mfu8Z8Zb1FeeJq1S27iKvE7Jf9TxYxAykxL niIc=; b=T1Gk6tklIreoHIzcoYkNXIMm2kbpEWB9GcqzB9G1MxhJrRQzqJBk5UO UgdnCoiXiAJnOymWx1/kxMuxgxOXkkraFYLxXICJ5HO/RyQ1tPdNfYbpNUJQKs+s XSf2q8U9Io7LEiLWbCjCpNFXkYUiT7t2NfoYZWk3YrOFKHsw7CxM= Received: from infao0525.mpi-klsb.mpg.de ([139.19.1.26]:55461 helo=maniac.mpi-klsb.mpg.de) by hera.mpi-sb.mpg.de (envelope-from ) with esmtp (Exim 4.69) id 1QFnRY-0006lm-Ov; Fri, 29 Apr 2011 15:09:15 +0200 Received: from [24.104.44.194] (port=11978 helo=[172.28.172.108]) by maniac.mpi-klsb.mpg.de (envelope-from ) with esmtpsa (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.69) id 1QFnRX-0007Je-ID; Fri, 29 Apr 2011 15:09:12 +0200 From: Andreas Rossberg To: Lucas Dixon In-Reply-To: References: Message-Id: <1CD0C5CF-4339-4365-A05C-58A12EE7AE2D@mpi-sws.org> Content-Type: text/plain; charset=US-ASCII; format=flowed; delsp=yes Content-Transfer-Encoding: 7bit Mime-Version: 1.0 (Apple Message framework v936) Date: Fri, 29 Apr 2011 15:09:07 +0200 Cc: caml-list@inria.fr X-Mailer: Apple Mail (2.936) Subject: [Caml-list] Re: functors and modules (was "What is an applicative functor?") On Apr 28, 2011, at 07:06, Lucas Dixon wrote: > 1. I think you want to have a reasonable language to modify signatures > - one that has all the obvious set-stuff, e.g. remove/add etc. > (basically following the paper on an expressive language for > signatures). Agreed. > 2. the resulting signature of a Functor should be able to refer to the > input signatures. This would allow multiple inheritance in a natural > way: functor S2(S1) : S1 + sig val f : S1.t -> int end; I don't understand. Is S1 a signature or structure here? In the former case, how is this different from: functor S2(X : S1) : sig include S1 val f : X.t -> int end In the latter case, how is it different from saying (in OCaml 3.12): module S2(S1 : SIG) : sig include module type of S1 val f : S1.t -> int end Granted, it would be much nicer with mixin composition. ;) > 3. implicit signature dependencies: > let S1 : SIG1 ... in > functor F1(S2) = ... > functor F2(S3) = ... > end; > = > functor F1(S1 and S2) = ... > functor F2(S1 and S3) = ... Again, I don't understand what universes your Si are in, nor what you mean by "implicit signature dependency" or the "and" keyword. Assuming the Si are module identifiers, then isn't that just a nested functor? functor F (S1 : SIG1) = struct functor F1 (S2 : SIG2) = ... functor F2 (S3 : SIG3) = ... end which in this case is isomorphic to the use of currying: functor F1 (S1 : SIG1) (S2 : SIG2) = ... functor F2 (S1 : SIG1) (S3 : SIG3) = ... All this can be done in OCaml and in several SML implementations. > 4. sharing of structures should allow be fine-grained modification, > and should have sensible syntax (it's not a symmetric operation, so > don't use a symmetric syntax: use <= instead of =): > e.g.. > sharing (S1 except S1.t) <= S2 Sharing constraints a la SML are an anachronism. You simply want transparent (aka manifest) module specifications. E.g. in OCaml (or similarly in some SML dialects): sig ... module S1 = S2 ... end or S with module S1 = S2 Not sure what you intend with the "except", though. > Also when types are ground, if they are the same, then it shouldn't > complain. Yes, don't use structure sharing in SML. Ever. It was merely a backwards compatibility device for SML'90 code. >> No, I meant it literally. One common idiom with functors is to re- >> export all parameter structures in the result, in order to have a >> self- >> contained result signature (and ease sharing later on). When you >> continue doing that up the entire dependency graph, then signatures >> can grow exponentially (in the depth of the dependency chain). > > While the number of paths to the sub-structures is exponential, the > number of actual signatures is not. If the implementation does a > reasonable job at only storing one copy when they are shared, then I > don't think this is a problem. The size of a signature includes nested ones. You still have to do all the signature matching on the full thing, which is structural and involves varying instantiations, so you cannot generally "cache" it. > I think it is a problem if people don't specify their dependencies > correctly, and the language should make it easy. Providing > sub-structures to hold everything is not a good idea. So in some sense > I agree: we need the right syntax for expressing what our > dependencies. The alternative to nesting the full structures is just flattening out their relevant type members. That makes the overall signature smaller, and is indeed the style used in most ML functor code today. But now it is just the number of direct type members that grows exponentially (at least in the worst case), which tends to be even more annoying to write down (although I could imagine you often can use some idiom of packaging them up in a single substructure that you can then include, but that still is kind of unpleasant). > I think you want a reasonable language for specifying dependencies, > and actually I think functors, with some tweaks to the signature > language, would be pretty good. I can't see any better than saying > what you need and what you provide, which is essentially all that a > functor does. Well, there is a difference between referring to a concrete module you need, just by name (a definite reference) or abstracting over the concrete module, by giving its complete interface specification (an indefinite reference). I'm just saying you want both, scoping and functorisation, depending on whether the modules are in the same "package" or not. Always having to give the full signature spec is just way too inconvenient. >> I guess the underlying question is what constitutes a module? I think >> you have to distinguish modules (as individual abstractions) from >> components/libraries/packages/whatever you like to call them. The >> latter can consist of many modules. > > I don't see why they need to be separate... I think structures can be > individual modules as well as packages. A package is typically too large to be written in one source file. So you want to split it into several modules without having to functorise everything by everything. OTOH, you actually want to functorise the whole thing in the end, and that is something you cannot do with the language as is. (OCaml provides some extra-linguistic means to do the former, via the compiler's -pack option, but nothing for the latter.) Cheers, /Andreas