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=0.0 required=5.0 tests=none autolearn=disabled version=3.1.3 X-Original-To: caml-list@yquem.inria.fr Delivered-To: caml-list@yquem.inria.fr Received: from concorde.inria.fr (concorde.inria.fr [192.93.2.39]) by yquem.inria.fr (Postfix) with ESMTP id 0A89FBC69 for ; Sat, 24 Feb 2007 15:43:46 +0100 (CET) Received: from fmmailgate02.web.de (fmmailgate02.web.de [217.72.192.227]) by concorde.inria.fr (8.13.6/8.13.6) with ESMTP id l1OEhjQx014895 for ; Sat, 24 Feb 2007 15:43:45 +0100 Received: from smtp08.web.de (fmsmtp08.dlan.cinetic.de [172.20.5.216]) by fmmailgate02.web.de (Postfix) with ESMTP id 66B91623FB72 for ; Sat, 24 Feb 2007 15:43:45 +0100 (CET) Received: from [84.165.194.184] (helo=wiko) by smtp08.web.de with smtp (WEB.DE 4.107 #114) id 1HKy7k-0008IX-00 for caml-list@inria.fr; Sat, 24 Feb 2007 15:43:45 +0100 Message-ID: <00c401c75824$36265fe0$15b2a8c0@wiko> From: "Andreas Rossberg" To: References: <6CB0D237-F894-4AC3-BDBE-2BB484928D3C@gmail.com> <007401c75780$c87c53d0$15b2a8c0@wiko> <1172285488.23720.53.camel@rosella.wigram> Subject: Re: [Caml-list] Instruction selection in the OCaml compiler:Modulesor classes? Date: Sat, 24 Feb 2007 15:58:12 +0100 MIME-Version: 1.0 Content-Type: text/plain; format=flowed; charset="iso-8859-1"; reply-type=original Content-Transfer-Encoding: 7bit X-Priority: 3 X-MSMail-Priority: Normal X-Mailer: Microsoft Outlook Express 6.00.2900.3028 X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2900.3028 Sender: AndreasRossberg@web.de X-Sender: AndreasRossberg@web.de X-Miltered: at concorde with ID 45E04F21.000 by Joe's j-chkmail (http://j-chkmail . ensmp . fr)! X-Spam: no; 0.00; rossberg:01 ocaml:01 compiler:01 functor:01 functor:01 sig:01 struct:01 ocaml:01 semantically:01 implicitly:01 functors:01 generative:01 functors:01 sml:01 applicative:01 "skaller" : > > It seems like a module functor allows both anonymous > signatures (structural) and also anonymous argument > modules (structural), yet you cannot have > anonymous functor applications: you have to bind the application to > a module name. Not at all. For instance, given module Id(X : sig type t end) = X module A = struct type t = int end it is perfectly legal to write: module A' = Id(Id(Id(A))) Obviosuly, the inner applications of Id are all "anonymous". Likewise, you can say (3 : Id(Id(A)).t) Also purely anonymous applications. > C++ template applications can be anonymous, and that gives them > a major edge over Ocaml modules. This is not really an issue of anonymity, but rather a matter of implicit vs. explicit sharing. In C++, all "equivalent" applications of the same template are - at least semantically - implicitly shared (where "equivalent" is rather ill-defined when it comes to non-type template arguments). In OCaml, all type instantiations are shared (sharing is based on a purely syntactic notion of module expression equivalence that is rather weak). But for the value part, which might involve state, you have to be explicit about sharing, and thus explicit about separate instantiation. After all, it makes a crucial semantic difference if you copy the state, and multiple instantiations may be desired. C++ cannot express this directly. (As an aside, module theorists argue that it is incoherent to share types across instantiations of functors that are stateful. In such cases you rather want so-called generative functors, which OCaml does not have. SML has the latter, but in turn does not offer OCaml-style "applicative" functors, which is just as bad. More recent type theories for modules incorporate both.) > Similarly, when you're lucky > enough to be able to use non-modular functor (a function with > polymorphic type) it is much more convenient. For example Hashtbl > provides both alternatives, whereas Set and Map do not (a fact > many people complain about). Yes, the fact that there is an overlap between functors and core-language polymorphism is a bit unfortunate. It is one of the advantages of Haskell-style type classes over ML modules that they blend seamlessly with polymorphism. Of course, they have other disadvantages instead, implicit sharing being one of them. > *** more precisely, we probably don't want to eliminate the name > most of the time, but we would like to be able to use a > 'Set of int' in several modules without having to *export* > the type in another module so it can be reused. You can more or less do that already, as long as you introduce a suitable global module to host the integer type: module Int = struct type t = int let compare = compare end signature A = sig ... val foo : u -> Set.Make(Int).t -> unit ... end signature B = sig ... val bar : v -> w -> Set.Make(Int).t ... end Admittedly, the type looks a bit ugly, and it would be even nicer if Int was in the stdlib. But that are merely a questions of library design. Due to the "weak syntactic notion of module equivalence" I was mentioning earlier you have to make sure that all these type expressions really refer to the same Int module. This is a limitation of OCaml's module type system, and may be what sometimes gives the impression of "nominal" typing. The limitation has long been solved in theory, but a full-fledged theory has not made it into any concrete ML implementation yet. Moscow ML probably comes closest. > This is particularly annoying when it is intractable: for > example I have variant terms some of which contain sets > of terms .. the recursion is easy to represent with > lists but you can't do it with modular data structures. > The way I do it is make sets of integers instead and > keep a term table indexed by the integers. But this isn't > really safe. There's probably a better way but the fact > remains if I want the type safety I have to use lists > or some other non-modular data structure: the modules > actually get in the way of type safety instead of > enhancing it. I guess the 'recursive modules' stuff will > help fix this? Yes, with recursive modules you should be able to express this. Something like: module rec Term : Set.OrderedType = struct type t = A | B of TermSet.t let compare = compare end and TermSet : (Set.S with type elt = Term.t) = Set.Make(Term) or even: module rec Term : Set.OrderedType = struct type t = A | B of Set.Make(Term).t let compare = compare end - Andreas