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=AWL autolearn=disabled version=3.1.3 X-Original-To: caml-list@yquem.inria.fr Delivered-To: caml-list@yquem.inria.fr Received: from mail1-relais-roc.national.inria.fr (mail1-relais-roc.national.inria.fr [192.134.164.82]) by yquem.inria.fr (Postfix) with ESMTP id 67BA4BBC4 for ; Wed, 4 Mar 2009 07:11:50 +0100 (CET) X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: ApECAPiqrUnYi40JmWdsb2JhbACBTpM5AQEBAQEICwoHEcErhAgG X-IronPort-AV: E=Sophos;i="4.38,299,1233529200"; d="scan'208";a="25024470" Received: from mail-out9.nyct.net (HELO mail.nyct.net) ([216.139.141.9]) by mail1-smtp-roc.national.inria.fr with ESMTP; 04 Mar 2009 07:11:49 +0100 Received: from beast.local (pool-96-250-132-59.nycmny.east.verizon.net [96.250.132.59]) (authenticated bits=0) by mail.nyct.net (8.14.2/8.14.1) with ESMTP id n246Bix6052207 (version=TLSv1/SSLv3 cipher=DHE-DSS-AES256-SHA bits=256 verify=NO); Wed, 4 Mar 2009 01:11:46 -0500 (EST) (envelope-from bhurt@spnz.org) Date: Wed, 4 Mar 2009 01:11:18 -0500 (EST) From: Brian Hurt X-X-Sender: bhurt@beast To: Jon Harrop Cc: caml-list@yquem.inria.fr Subject: Re: [Caml-list] stl? In-Reply-To: <200903040159.48574.jon@ffconsultancy.com> Message-ID: References: <91a2ba3e0903031340wcdc976cp52522eb35f7ccb73@mail.gmail.com> <200903032342.39527.jon@ffconsultancy.com> <200903040159.48574.jon@ffconsultancy.com> User-Agent: Alpine 2.00 (DEB 1167 2008-08-23) MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII; format=flowed X-Spam: no; 0.00; stl:01 functors:01 ocaml:01 functors:01 abstracting:01 ocaml:01 lacks:01 functor:01 haskell's:01 haskell:01 functor:01 overloading:01 overloading:01 reimplement:01 haskell's:01 On Wed, 4 Mar 2009, Jon Harrop wrote: > On Wednesday 04 March 2009 00:11:32 you wrote: >> On Tue, 3 Mar 2009, Jon Harrop wrote: >>> Functors give you the same capability in OCaml but they are rarely used >>> precisely because the functionality is not very useful. > > Also largely because there is not enough good tutorial information available > explaining how to leverage functors. This is another large factor. The three reasons functors aren't used very much are because: 1) They're a big, scary name, 2) They're slightly less efficient, 3) There are no good tutorials about how to use them, and 4) A fanatical devotion to the pope. I'll come in again... > Efficiency is only important in the context of functors when abstracting very > fast and common functions like arithmetic without defunctorizing your code. I > don't think that is why people avoid functors in OCaml. Arithmetic operators that are themselves very cheap. The cost of functorization is large compared to, say, floating point addition- but small compared to the cost of, say, vector addition. And it's expensive only because Ocaml lacks an obvious optimization (defunctorization). And yet this whole discussion is simply proving my point- we're comparing clock cycles here. Yes, if you're writing the inner loops of a numeric computation that'll take days to run, maybe, *MAYBE*, the cost difference of calling via a functor is worthwhile to worry about. But that's the point where I start being really tempted to drop down to C, or even assembly (for SSE Vectorization). But for the vast bulk of people programming, performance (at least on the clock cycle level) simply isn't that important- as demonstrated by all the "real work" being done in hideously slow languages like Ruby, Python, etc... > I think that is a reflection of what the communities desire rather than what > they already have. OCaml is already fast (particularly on amd64) but OCamlers > always want even better performance. Haskell's development experience is a > real sore point and they want to address that. However, I would also say that > both communities are moving very slowly toward these goals. Both languages have their annoyances. Adjusting for the fact that I'm significantly more familiar with and comfortable with Ocaml, I don't find Haskell that much more difficult to work in. > >> The type classes comparison isn't even an analogy- it's a precise >> relationship. Anywhere you might be thinking, in Ocaml, "this would be a >> nice place to use a type class", use a functor. You want operator >> overloading in Ocaml? You got it: use a functor. > > Functors do not facilitate operator overloading. You still end up with a > combinatorial explosion in the number of operator names. Bwuh? Try this. Let's reimplement Haskell's Fractional class, in Ocaml, and then do Newton's method using this new Fractional class. Then I'll provide implementations that use both floats and ratios (arbitrary precision fractions). First, we need to define Fractional. That's just: module type Fractional = sig type t val ( +. ) : t -> t -> t val ( -. ) : t -> t -> t val ( *. ) : t -> t -> t val ( /. ) : t -> t -> t val fabs : t -> t (* other functions elided from brevity *) end;; Now we write our functorized Newton's method: module Make(F: Fractional) = struct open F;; let rec newtons epsilon f df x = let x' = x -. ((f x) /. (df x)) in if (fabs (x -. x')) < epsilon then x' else newtons epsilon f df x' ;; end;; Now we provide an instance of Fractional for floats: module FloatFractional = struct type t = float let ( +. ) = ( +. );; let ( -. ) = ( -. );; let ( *. ) = ( *. );; let ( /. ) = ( /. );; let fabs x = abs_float x;; end;; module FloatNewtons = Make(FloatFractional);; Now we provide an instance for Ratios: module RatioFractional = struct type t = Ratio.ratio;; let ( +. ) = Ratio.add_ratio;; let ( -. ) = Ratio.sub_ratio;; let ( *. ) = Ratio.mult_ratio;; let ( /. ) = Ratio.div_ratio;; let fabs = Ratio.abs_ratio;; end;; module RatioNewtons = Make(RatioFractional);; Viola. Operator overloading. In Ocaml. And it's not that much worse than Haskell equivalent, once you realize that the definitions of Fractional, FloatFractional, and RatioFractional all should be in the standard library (and the latter two should be just called Float and Ratio). And typeclasses have their problems as well- which are off topic for this list. > >> If this causes you a >> knee jerk reaction about performance, ask yourself this: do you know how >> type classes are implemented in Haskell, and what their performance hit >> there is? Now, imagine programming haskell where typeclasses are only >> used in a very places- Ord, Eq, Monad. No Num. No Monoid. No Show. >> That's Ocaml. Not that it has to be. > > I don't follow your breakdown. OCaml does not have Ord and Eq, it only has a > hack for structural equality. Same for Show. Few people care about Monad, Num > and Monoid. The turn you missed was that I'm say "what if Haskell programmers used type classes as rarely as Ocaml programmers use functors?" Typeclasses are a huge win in Haskell, but primarily because they get *used*. > > However, that is trivial to fix with run-time type information that can convey > per-type functions. Both F# and my HLVM already do that. I suppose we could sit around and whine that Ocaml doesn't have type classes, or reflection, or some other neat feature, that if it only had it, we could all these neat things with them. Or we could use the equivalently powerfull features Ocaml *already* has... Brian