caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* Re: [Caml-list] A G'Caml question" + additional info
@ 2001-07-11 23:10 Krishnaswami, Neel
  2001-07-12  0:08 ` Brian Rogoff
  0 siblings, 1 reply; 12+ messages in thread
From: Krishnaswami, Neel @ 2001-07-11 23:10 UTC (permalink / raw)
  To: caml-list

Brian Rogoff [mailto:bpr@best.com] wrote:
> >
> > For instance, I recently wrote yet another set 
> > implementation, because the functorial interface to the Set module 
> > in the standard library wouldn't let me use it in a fully polymorphic
> > fashion. If the Set library had been written using OCaml's object
> > system, then I would not have had to redo my own. 
> 
> That's odd. If the Set library had been implemented using the object
> system, it seems that you would have less (parametric) polymorphism 
> since OCaml doesn't (yet?) have polymorphic methods. 

I don't know enough type theory to argue, except that in practice
I seem to be getting more polymorphic types with objects than with 
functors. I guess I'll go ahead and post the example -- it's possible
that I just don't know enough yet! 

So, let's take the example of a priority queue implemented using a
binary search tree. The usual functorial approach to this looks like:

module type ORD =
  sig
    type t
    val cmp : t -> t -> bool
  end

module Queue(Elt : ORD) =
  struct
    type elt = Elt.t
    type t = Nil | Tree of t * elt * t

    let empty = Nil

    let rec min = function
        | Nil -> raise Not_found
        | Tree(Nil, x, r) ->  x
        | Tree(l, x, r) -> min l 

    let rec add x = function
      | Nil ->
          Tree(Nil, x, Nil)
      | Tree(l, y, r) as t ->
          if Elt.cmp x y then
            Tree(add x l, y, r)
          else if Elt.cmp y x then
            Tree(l, y, add x r)
          else
            Tree(l, x, r)
  end

To specialize this a structure satisfying the ORD signature is 
applied to the functor. The obvious approach with classes looks 
very similar, except that the Elt functor argument becomes a method 
to be overridden: 

type 'a tree = Nil | Tree of 'a tree * 'a * 'a tree

class virtual ['a] q =
  object(self)
    val tree = Nil

    method virtual cmp : 'a -> 'a -> bool

    method min =
      let (<) = self#cmp in
      let rec loop = function
        | Nil -> raise Not_found
        | Tree(Nil, x, r) -> x
        | Tree(l, x, r) -> loop l
      in loop tree

    method add x =
      let (<) = self#cmp in
      let rec loop = function
        | Nil ->
            Tree(Nil, x, Nil)
        | Tree(l, y, r) as t ->
            if x < y then
              Tree(loop l, y, r)
            else if y < x then
              Tree(l, y, loop r)
            else
              Tree(l, x, r)
      in
      {< tree = loop tree >}
  end

To specialize this we just subclass and add a cmp method. So far
so good.

However, suppose I have a type 

type 'a tag = int * 'a

This is a value that has an integer priority plus some arbitrary 
data, and I'd like to make a priority queue that stores tagged 
values. Since the type 'a tag is polymorphic, AFAICT there's no 
way of writing a structure that satisfies the ORD signature.

However, writing a class that can accept this is easy --

class ['a] taggedq =
  object
    inherit ['a] q
    constraint 'a = 'b tag

    method cmp = fun a b -> (fst a) < (fst b)
  end

will Just Work(tm). This is why I called the class "more polymorphic."
If my terminology is wrong, corrections will be gratefully accepted. 


--
Neel Krishnaswami
neelk@cswcasa.com
-------------------
Bug reports: http://caml.inria.fr/bin/caml-bugs  FAQ: http://caml.inria.fr/FAQ/
To unsubscribe, mail caml-list-request@inria.fr  Archives: http://caml.inria.fr


^ permalink raw reply	[flat|nested] 12+ messages in thread
* Re: [Caml-list] A G'Caml question" + additional info
@ 2001-07-13 13:12 Krishnaswami, Neel
  2001-07-13 13:35 ` Markus Mottl
  0 siblings, 1 reply; 12+ messages in thread
From: Krishnaswami, Neel @ 2001-07-13 13:12 UTC (permalink / raw)
  To: caml-list

Markus Mottl [mailto:markus@mail4.ai.univie.ac.at] wrote:
> 
> Having tried RedBlackSet as presented in Okasaki's book a while ago,
> I was rather disappointed. It didn't perform faster (rather slower)
> than the Set-module (balanced binary trees) on some quick 
> examples that I had tried. But maybe my simple tests were not
> representative.

He has some timing data comparing splay trees, balanced binary 
trees, Patricia tries, and red-black trees in his paper "Fast 
Mergeable Integer Maps." To summarize, red-black trees were the 
fastest on lookup, and second-fastest on insertion. But they don't
perform very well on the merge operation. (These are all fairly
tuned implementations, though.)

I've been curious about implementing randomized treaps and seeing
how well they do, since they seem simpler than any other balanced 
binary tree implementation.

> > > Note that the non-polymorphic version also has advantages for 
> > > users: e.g. they don't have to pass around comparison functions 
> > > all the time.
> > 
> > ??? I don't understand this. In both the object version I posted 
> > and the functorial version that Brian Rogoff posted, a hacker
> > only needs to mention the comparison function when creating the
> > type, and then never again when making or using trees.
> 
> In the functorial version you naturally have to use a functor 
> application. I meant a polymorphic implementation without functors, 
> since I think you had complained somewhere about having to apply 
> functors. This was probably not obvious from my text.

Applying a functor doesn't bother me. What I find annoying is the
need to functorize my own code if I want to write functions that 
work independently of the element type. It doesn't take very many
of these before my source contains more functor declarations than
actual code. 

A sufficiently powerful include facility for G'Caml can make this
problem go away, since you could define a generic and have each 
functor instantiation add its specialized methods automatically
to the generic. 

> > In fact, my first experiment along these lines was to use a record
> > with a tree and a comparison function in it. But even there, one
> > could use currying to mention the function comparison only once.
> > (I rejected it because it permitted trees with different but type-
> > compatible comparison functions to intermix.)
> 
> But you have to manually curry every Set-function you want to use at
> least once. The functor application creates the closures for the whole
> Set-module at once.

Oh, I see what you mean. That's true but since I'd only implement the
Set once I don't much care. I tend to worry more about cruft associated
with code that uses the library.

--
Neel Krishnaswami
neelk@cswcasa.com
-------------------
Bug reports: http://caml.inria.fr/bin/caml-bugs  FAQ: http://caml.inria.fr/FAQ/
To unsubscribe, mail caml-list-request@inria.fr  Archives: http://caml.inria.fr


^ permalink raw reply	[flat|nested] 12+ messages in thread
* Re: [Caml-list] A G'Caml question" + additional info
@ 2001-07-12 21:30 Krishnaswami, Neel
  2001-07-13  9:34 ` Markus Mottl
  0 siblings, 1 reply; 12+ messages in thread
From: Krishnaswami, Neel @ 2001-07-12 21:30 UTC (permalink / raw)
  To: caml-list

Markus Mottl [mailto:markus@mail4.ai.univie.ac.at] wrote:
> On Wed, 11 Jul 2001, Krishnaswami, Neel wrote:
> > For instance, I recently wrote yet another set 
> > implementation, because the functorial interface to the Set module 
> > in the standard library wouldn't let me use it in a fully polymorphic
> > fashion.
> 
> This is a shortcoming of the standard library that there are no
> polymorphic implementations of "Set" and similar. It's very easy to
> extract a polymorphic (module-) version from the existing code. 

Are there any plans to add them? I /really/ need them, and while
their lack has led to me learning an awful lot about red-black
trees, Patricia tries and treaps, I can't help but feel that I've
been busy reinventing the wheel. :)

If desired, I can offer a red-black tree implementation that 
implements the whole Map and Set interfaces. (I wonder how many 
other people have been inspired by that Okasaki paper?) 

> Note that the non-polymorphic version also has advantages for 
> users: e.g. they don't have to pass around comparison functions 
> all the time.

??? I don't understand this. In both the object version I posted 
and the functorial version that Brian Rogoff posted, a hacker
only needs to mention the comparison function when creating the
type, and then never again when making or using trees.

In fact, my first experiment along these lines was to use a record 
with a tree and a comparison function in it. But even there, one 
could use currying to mention the function comparison only once. 
(I rejected it because it permitted trees with different but type-
compatible comparison functions to intermix.)

--
Neel Krishnaswami
neelk@cswcasa.com
-------------------
Bug reports: http://caml.inria.fr/bin/caml-bugs  FAQ: http://caml.inria.fr/FAQ/
To unsubscribe, mail caml-list-request@inria.fr  Archives: http://caml.inria.fr


^ permalink raw reply	[flat|nested] 12+ messages in thread
* Re: [Caml-list] A G'Caml question" + additional info
@ 2001-07-11 22:23 Krishnaswami, Neel
  2001-07-11 22:47 ` Brian Rogoff
                   ` (2 more replies)
  0 siblings, 3 replies; 12+ messages in thread
From: Krishnaswami, Neel @ 2001-07-11 22:23 UTC (permalink / raw)
  To: caml-list

Markus Mottl [mailto:markus@mail4.ai.univie.ac.at] writes:
> On Wed, 11 Jul 2001, Bruce Hoult wrote:
> > But the language itself seems to be starting to rival C++ for sheer
> > complexity. When you want to do something you seem to have a choice
> > of using this feature, or *this* one, or *this* newly developed one.
> 
> Having choices is not necessarily bad, being forced to using many
> alternatives is. I think that OCaml has succeeded quite well so far in
> keeping different features apart as one can see in the standard library,
> which can be used with the core language + modules alone. I hope this
> will stay so!

Permit me to disagree. I find nearly all of OCaml's features highly
useful and orthogonal, and I am only working on medium size projects. 

For instance, I recently wrote yet another set implementation, because 
the functorial interface to the Set module in the standard library 
wouldn't let me use it in a fully polymorphic fashion. If the Set 
library had been written using OCaml's object system, then I would 
not have had to redo my own. From this experience I conclude that the 
right thing is to use the features that offer the nicest degree of
modularity and reusability.

I can offer a demonstration if you are interested, but to illustrate 
I'd need to show both approaches in about 75 lines of code, which may 
be too much for a public email. 

--
Neel Krishnaswami
neelk@cswcasa.com
-------------------
Bug reports: http://caml.inria.fr/bin/caml-bugs  FAQ: http://caml.inria.fr/FAQ/
To unsubscribe, mail caml-list-request@inria.fr  Archives: http://caml.inria.fr


^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2001-07-14 15:00 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2001-07-11 23:10 [Caml-list] A G'Caml question" + additional info Krishnaswami, Neel
2001-07-12  0:08 ` Brian Rogoff
  -- strict thread matches above, loose matches on Subject: below --
2001-07-13 13:12 Krishnaswami, Neel
2001-07-13 13:35 ` Markus Mottl
2001-07-12 21:30 Krishnaswami, Neel
2001-07-13  9:34 ` Markus Mottl
2001-07-11 22:23 Krishnaswami, Neel
2001-07-11 22:47 ` Brian Rogoff
2001-07-12  9:37 ` Markus Mottl
2001-07-14  2:04 ` John Max Skaller
2001-07-14  3:00   ` Alexander V. Voinov
2001-07-14 15:00     ` John Max Skaller

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).