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.4 required=5.0 tests=SPF_NEUTRAL autolearn=disabled version=3.1.3 Received: from mail4-relais-sop.national.inria.fr (mail4-relais-sop.national.inria.fr [192.134.164.105]) by yquem.inria.fr (Postfix) with ESMTP id A4B60BC69 for ; Tue, 13 Nov 2007 20:13:07 +0100 (CET) X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AgAAAJOFOUdIDtbnfGdsb2JhbACOfAEBCQQEERMF X-IronPort-AV: E=Sophos;i="4.21,411,1188770400"; d="scan'208";a="19244082" Received: from hu-out-0506.google.com ([72.14.214.231]) by mail4-smtp-sop.national.inria.fr with ESMTP; 13 Nov 2007 20:13:07 +0100 Received: by hu-out-0506.google.com with SMTP id 40so2678530hub for ; Tue, 13 Nov 2007 11:13:06 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=beta; h=domainkey-signature:received:received:subject:from:to:in-reply-to:references:content-type:date:message-id:mime-version:x-mailer:content-transfer-encoding; bh=IzC+b38G2ZUn23NXfH20o5vi3zsc0vldBA8NnPoqMt8=; b=eEUas9qzuGLlMT1DObIUF0SIxC3oXxQ84RwGq+Rl+aa5AJf0kbVQw8pwDftx3viWFBYMaTyUYZzZR46/PR6fFJq5cmmWFN89+Pv+XFUKbgQe10vtLCCtyYTjJEr3v0efx7QSslj0zhLy4Dyka/U5pMssVC3VK29RNGlILvFPHhg= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=beta; h=received:subject:from:to:in-reply-to:references:content-type:date:message-id:mime-version:x-mailer:content-transfer-encoding; b=TnSVahZf79/IRdWuW9ZWg/x3pqBxD+AAk5yu16zIZn2eXi7OosDDQEeqga/PeBfItRhCFR0y8liMDxd2PeOqXnMe7sc16SIwpV4El/fuxdVOJzBJYcVIaBo1nJAOj0z8HgK4VQtmQUWdh6DwIqhF3FevuIEmlwekkiBkBteNV8g= Received: by 10.67.32.14 with SMTP id k14mr931822ugj.1194981186116; Tue, 13 Nov 2007 11:13:06 -0800 (PST) Received: from ?192.168.0.10? ( [82.237.227.151]) by mx.google.com with ESMTPS id 28sm9096304fkx.2007.11.13.11.13.05 (version=SSLv3 cipher=RC4-MD5); Tue, 13 Nov 2007 11:13:05 -0800 (PST) Subject: Re: [Caml-list] polymorphic lists, existential types and asorted other hattery From: Benjamin Canou To: caml-list In-Reply-To: <473A197D.7070403@tepkom.ru> References: <200711131227.18910.peng.zang@gmail.com> <473A139E.80408@tepkom.ru> <200711131324.53588.peng.zang@gmail.com> <473A197D.7070403@tepkom.ru> Content-Type: text/plain; charset=UTF-8 Date: Tue, 13 Nov 2007 20:13:04 +0100 Message-Id: <1194981184.6402.33.camel@benjamin-laptop> Mime-Version: 1.0 X-Mailer: Evolution 2.12.0 Content-Transfer-Encoding: 8bit X-Spam: no; 0.00; existential:01 simulated:01 ocaml:01 ocamlopt:01 pred:01 iter:01 pred:01 iter:01 printf:01 printf:01 bool:01 ocaml:01 existential:01 functors:01 re-implement:01 Hi, I've simulated objects with records like this in the past in when I didn't need method resolution, and this thread made me worry about the execution speed of such a pattern compared to ocaml objects. So I made a little comparison between records and classes to do this task (the code follows my message). Here is the result : benjamin@benjamin-laptop:~/Work/Stuff$ ocamlopt classesvsrecords.ml -o classesvsrecords && ./classesvsrecords Classes: build = 1.316082, apply = 2.324145 Records: build = 1.872116, apply = 2.320145 Basically, objects are created faster than records (I think that an object is created in O(1) whereas a record takes O(number of closures) to be filled). Calls take the same time. So, if you have to allocate a great number of values, then I think you should consider using objects, otherwise, records wrapping the values seem to be a correct option. Benjamin. (* classes *) let show l = List.map (fun x -> x#show) l class integer x = object method show = print_int x method to_string = string_of_int x end class floating x = object method show = print_float x method to_string = string_of_float x end (* records *) type element = { show : unit -> unit ; to_string : unit -> string } let wrap_int x = { show = (fun () -> print_int x) ; to_string = (fun () -> string_of_int x) } let wrap_float x = { show = (fun () -> print_float x) ; to_string = (fun () -> string_of_float x) } (* bench *) let test_classes () = let rec build_classes n acc = if n <= 0 then acc else build_classes (pred n) ((new floating (float_of_int n)) :: (new integer n) :: acc) in let t1 = Sys.time () in let list = build_classes 1000000 [] in let t2 = Sys.time () in List.iter (fun x -> ignore (x#to_string)) list ; t2 -. t1, Sys.time () -. t2 let test_records () = let rec build_records n acc = if n <= 0 then acc else build_records (pred n) ((wrap_float (float_of_int n)) :: (wrap_int n) :: acc) in let t1 = Sys.time () in let list = build_records 1000000 [] in let t2 = Sys.time () in List.iter (fun x -> ignore (x.to_string ())) list ; t2 -. t1, Sys.time () -. t2 let _ = let tci, tca = test_classes () and tri, tra = test_records () in Printf.printf "Classes: build = %f, apply = %f\nRecords: build = %f, apply = %f \n" tci tca tri tra Le mardi 13 novembre 2007 à 21:39 +0000, Dmitri Boulytchev a écrit : > Are structures allowed? :) > > type t = {show : unit -> string} > > let show l = List.map (fun x -> x.show ()) l > > let integer x = {show = fun () -> string_of_int x} > let floating x = {show = fun () -> string_of_float x} > let boolean x = {show = fun () -> string_of_bool x} > > let _ = > List.iter > (Printf.printf "%s\n") > (show > [ > integer 10; > floating 3.14; > boolean true; > ] > ) > > OCaml does not have Haskell-style existential types (I don't exactly > know why, but can > presume that they may interfere with objects, which considered to be > much more worthy). > I like modules and functors very much, too, but, first, modules are > not "first-class > citizens", and second, there may be no need to re-implement all your > stuff to > start using objects --- OCaml is fairy orthogonal language. > > Best regards, > DB. > > P.S. Objects are efficient :) > > > > > Ahh, right! Sorry, I forgot to mention I'm looking for a possible > > solution > > without classes. > > > > I ask because most of my code base is modules and functor based and it > > would > > be a pain to convert over. Also because performance is typically > > better with > > just functions and data types. > > > > I feel like a solution without the OO side is possible through perhaps an > > analog of existential types? > > > > Peng > > > > On Tuesday 13 November 2007 04:14:06 pm Dmitri Boulytchev wrote: > > > > > Try using classes for this purpose: > > > > >let show l = List.map (fun x -> x#show) l > > > > >class integer x = > > > object > > > method show = string_of_int x > > > end > > > > >class floating x = > > > object > > > method show = string_of_float x > > > end > > > > >class boolean x = > > > object > > > method show = string_of_bool x > > > end > > > > > > >let _ = > > > List.iter > > > (Printf.printf "%s\n") > > > (show > > > [ > > > new integer 10; > > > new floating 3.14; > > > new boolean true; > > > ] > > > ) > > > > > Best regards, > > > Dmitri Boulytchev, > > > St.Petersburg State University. > > > > >>Hi, > > >> > > >>Is there a way to create lists in which the elements may be of > > >>differing types but which all have some set of operations defined > > >>(eg. tostr) in common? One can then imagine mapping over such lists > > >>with "generic" versions of those common operations. Here's a concrete > > >>example of what I mean: > > >> > > >> module Int = struct > > >> type t = int > > >> let show x = string_of_int x > > >> end > > >> module Float = struct > > >> type t = float > > >> let show x = string_of_float x > > >> end > > >> module Bool = struct > > >> type t = bool > > >> let show x = string_of_bool x > > >> end > > >> > > >> let xs = [`Int 1; `Float 2.0; `Bool false] > > >> let showany x = match x with > > >> > > >> | `Int x -> Int.show x > > >> | `Float x -> Float.show x > > >> | `Bool x -> Bool.show x > > >> > > >> ;; > > >> List.map showany xs;; > > >> > > >>Essentially we have ints, floats and bools. All these types can be > > >>shown. It would be nice to be able to create a list of them [1; 2.0; > > >>false] that you can then map a generalized show over. In the above > > >>example, I used polymorphic variants in order to get them into the > > >>same list and then had to define my own generalized show function, > > >>"showany". This is fine as there is only one shared operation but if > > >>there is a large set of these common operations, it becomes > > >>impractical to define a generalized version for each of them. > > >> > > >>I've come across a way to do this in haskell using what they call > > >>"existential types". > > >> > > >> http://www.haskell.org/haskellwiki/Existential_type > > >> > > >>I don't really understand existential types however and don't know if > > >>OCaml has them nor how to use them. > > >> > > >>So. How can one do this in OCaml? Is there perhaps a camlp4 > > >>extension that can do this? Is there a possible functor trick that > > >>can take N modules as arguments and spit out a new module with a > > >>generalized type that can take on any of the types in the arguments > > >>and also make generalized versions of operations common to the N > > >>modules? Are there existential types or equivalents in OCaml? If so > > >>how does one go about using them? > > >> > > >>Thanks in advance to anyone who forays into this bundle of questions. > > >> > > >>Peng > > > > >_______________________________________________ > > >Caml-list mailing list. Subscription management: > > >http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list > > >Archives: http://caml.inria.fr > > >Beginner's list: http://groups.yahoo.com/group/ocaml_beginners > > >Bug reports: http://caml.inria.fr/bin/caml-bugs > > > > > > > > _______________________________________________ > Caml-list mailing list. Subscription management: > http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list > Archives: http://caml.inria.fr > Beginner's list: http://groups.yahoo.com/group/ocaml_beginners > Bug reports: http://caml.inria.fr/bin/caml-bugs > > > _______________________________________________ > Caml-list mailing list. Subscription management: > http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list > Archives: http://caml.inria.fr > Beginner's list: http://groups.yahoo.com/group/ocaml_beginners > Bug reports: http://caml.inria.fr/bin/caml-bugs