caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
From: brogoff <brogoff@speakeasy.net>
To: Richard Jones <rich@annexia.org>
Cc: caml-list@yquem.inria.fr
Subject: Re: [Caml-list] Polymorphic method question
Date: Mon, 10 Jul 2006 16:25:20 -0700 (PDT)	[thread overview]
Message-ID: <Pine.LNX.4.58.0607101619040.26509@shell2.speakeasy.net> (raw)
In-Reply-To: <20060710200508.GA18988@furbychan.cocan.org>

On Mon, 10 Jul 2006, Richard Jones wrote:

> On Mon, Jul 10, 2006 at 12:21:26PM -0700, brogoff wrote:
> > This type scheme cannot quantify 'a :
> > it escapes this scope.
>
> Check out this thread:
>
> http://caml.inria.fr/pub/ml-archives/caml-list/2005/02/a67b1a509263be01705305f36d64c39c.en.html
>
> Rich.

Hi Rich,

Thanks for the info, I guess I missed that one when it came out. Unfortunately,
the solution proposed, breaking the recursion by introducing some polymorphic
algebraic type to hold any kind of value in some class type to represent the
visitor, breaks the whole thing. There are just too many recursive
dependencies. Here's a more complete, but still small, example. The modules
are only there to show how the classes would go into files, they're not
essential.

PS: Before anyone tells me that algebraic data types are favored for this
over visitor classes, I'm well aware of all that, and in general agree
with those who prefer their ML sans OOP. However, I was trying to encode a
design pattern I read about somewhere (Felleisen?) which made good use of
polymorphic methods, only to find that it just doesn't translate into the OCaml
class system. The restriction on polymorphism in mutually recursive class
definitions makes the idea unworkable. Any possibility that restriction will be
lifted?

(* The following code won't work, but hopefully gives the idea *)

module Shape =
  struct
    class virtual ['a] shape_visitor =
      object
        method visit_square : square -> 'a
        method visit_rectangle : rectangle  -> 'a
        method visit_polygon :  polygon -> 'a
        method visit_translated : translated  -> 'a
        (* and potentially many more! *)
      end
    and virtual shape =
      object
        method virtual visit : 'a . 'a shape_visitor -> 'a
      end
    and square pt width =
      object (self)
        inherit shape
        method visit visitor = visitor#visit_square self

        method as_tuple : ((int * int) * (int * int)) =
          let (ll_x, ll_y) = pt in
          (pt, (ll_x + width, ll_y + width))

        method as_point_list : (int * int) list =
          failwith "Shape.square#as_point_list: unimplemented"
      end
    and rectangle ll ur =
      object (self)
        inherit shape
        method visit visitor = visitor#visit_rectangle self

        method as_tuple : ((int * int) * (int * int)) = (ll, ur)

        method as_point_list : (int * int) list =
          failwith "Shape.rectangle#as_point_list: unimplemented"
      end

    and polygon points =
      object (self)
        val points : (int * int) list = points
        inherit shape

        method visit visitor = visitor#visit_polygon self

        method as_point_list : (int * int) list =
          points
      end

    class translated pt s =
      object (self)
        inherit shape
        method visit visitor = visitor#visit_translated self

        method get_shape = s
        method get_translation = pt

        method as_point_list : (int * int) list =
          failwith "Shape.translated#as_point_list: unimplemented"
      end
  end (* module Shape *)

module Contains_point =
  struct
    (* Writing code that works over shapes *)
    class contains_point point =
      object
        inherit bool Shape.shape_visitor

        method make_contains_point p =
          new contains_point p

        method visit_square : Shape.square node -> bool =
          fun s ->
            let ((ll_x, ll_y), (ur_x, ur_y)) = s#as_tuple in
            let (x, y) = point in
            ll_x <= x && x <= ur_x && ll_y <= y && y <= ur_y

        method visit_rectangle : Shape.rectangle node  -> bool =
          fun r ->
            let ((ll_x, ll_y), (ur_x, ur_y)) = r#as_tuple in
            let (x, y) = point in
            ll_x <= x && x <= ur_x && ll_y <= y && y <= ur_y

        method visit_polygon : Shape.polygon node  -> bool =
          fun p ->
            failwith "Contains_point.contains_point#visit_polygon: unimplemented"

        method visit_translated : Shape.translated node  -> bool =
          fun t ->
            failwith "Contains_point.contains_point#visit_translated: unimplemented"
  end;;



-- 
-- Brian



  reply	other threads:[~2006-07-10 23:25 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-07-10 19:21 brogoff
2006-07-10 20:05 ` [Caml-list] " Richard Jones
2006-07-10 23:25   ` brogoff [this message]
2006-07-11  2:24     ` skaller
2006-07-11  4:56       ` brogoff
2006-07-11  2:09 ` Jacques Garrigue
2006-07-11  5:22   ` brogoff
2006-07-11  7:32     ` Jacques Garrigue
2006-07-11 18:20       ` brogoff
2006-07-12  0:37         ` Jacques Garrigue
2006-07-12 19:26           ` brogoff
  -- strict thread matches above, loose matches on Subject: below --
2002-08-21 21:49 [Caml-list] polymorphic " nadji
2002-08-21 22:57 ` Jacques Garrigue

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=Pine.LNX.4.58.0607101619040.26509@shell2.speakeasy.net \
    --to=brogoff@speakeasy.net \
    --cc=caml-list@yquem.inria.fr \
    --cc=rich@annexia.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).