From: Jacques Garrigue <garrigue@math.nagoya-u.ac.jp>
To: brogoff@speakeasy.net
Cc: caml-list@yquem.inria.fr
Subject: Re: [Caml-list] Polymorphic method question
Date: Tue, 11 Jul 2006 16:32:07 +0900 (JST) [thread overview]
Message-ID: <20060711.163207.72458365.garrigue@math.nagoya-u.ac.jp> (raw)
In-Reply-To: <Pine.LNX.4.58.0607102157080.26509@shell2.speakeasy.net>
From: brogoff <brogoff@speakeasy.net>
> > The only way to solve this problem would be to remove parameter
> > constraint inference from classes. It would certainly break some
> > programs, so this seems difficult.
>
> That's too bad, as it seems the class based OO version of the extensible
> visitor is fairly straightforward in OCaml except for this counterintuitive
> gotcha. What would have to be done to fix the broken programs? It may be
> worth considering.
You just would have to write constraints explicitly when they are
needed.
This could be a pain for classes. See the tutorial on the
subject-observer pattern in the reference manual for a non-trivial use
of inference.
But maybe we could rather have a way to tell the system that, for some
specific class, type parameters are not constrained. Hacky though.
> > By the way, if you're ready to define your types first, then you
> > can do this properly.
>
> In the more realistic example I sent along after, you'll see that this
> solution is not really pleasing. You'd need to create a parallel type
> hierarchy to match your class hierarchy, which is too verbose. All this
> because we must have inference, which is supposed to make things less
> verbose. Ironic, isn't it? ;-)
I'm not so sure about verbosity. Type syntax is pretty compact :-)
> I have seen the new private rows stuff, which is very nice, but all of these
> solutions IMO are way too complex to be considered satisfactory. I'll see if
> the Java 1.5 approach actually works (I used some Pizza code to do the OCaml
> implementation) because that was quite straightforward. I'd prefer approaches
> that I can explain with a little hand waving. I think type theorists often
> forget that there are a few programmers still who don't have PhDs in type
> theory and will look at such solutions and conclude that OCaml is not for
> them ;-).
I'm sure you need some tricks to make it work in Java 1.5 too.
I don't have the code in mind.
I agree that the solution I posted is not too simple, but I don't
think this is PhD level. Actually it's not much worse than the visitor
pattern. What is hard is understanding why you have to do all this
extra work, not using the pattern itself.
Note that, if you are ready to use a slightly less functional
approach, where the result is extracted from the visitor afterwards,
then typing is no problem.
This code is based on http://cristal.inria.fr/~remy/work/expr/
It is strictly equivalent to Odersky&Zenger's Scala version.
(Actually this kind of code is one reason we reverted to sharing of
instance variables in 3.10)
Jacques Garrigue
module Shape =
struct
class virtual shape_visitor =
object
method virtual visit_square : square -> unit
method virtual visit_rectangle : rectangle -> unit
method virtual visit_polygon : polygon -> unit
method virtual visit_translated : translated -> unit
(* and potentially many more! *)
end
and virtual shape =
object
method virtual visit : shape_visitor -> unit
end
and square pt width =
object (self)
inherit shape
method visit visitor = visitor#visit_square (self :> square)
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 :> rectangle)
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 :> polygon)
method as_point_list : (int * int) list =
points
end
and translated (pt : int * int) (s : shape) =
object (self)
inherit shape
method visit visitor = visitor#visit_translated (self :> translated)
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 Shape.shape_visitor
val mutable result = false
method result = result
method visit_square : Shape.square -> unit =
fun s ->
let ((ll_x, ll_y), (ur_x, ur_y)) = s#as_tuple in
let (x, y) = point in
result <- ll_x <= x && x <= ur_x && ll_y <= y && y <= ur_y
method visit_rectangle : Shape.rectangle -> unit =
fun r ->
let ((ll_x, ll_y), (ur_x, ur_y)) = r#as_tuple in
let (x, y) = point in
result <- ll_x <= x && x <= ur_x && ll_y <= y && y <= ur_y
method visit_polygon : Shape.polygon -> unit =
fun p ->
failwith "Contains_point.contains_point#visit_polygon: unimplemented"
method visit_translated : Shape.translated -> unit =
fun t ->
let (x, y) = point in
let (dx, dy) = t#get_translation in
let visitor = new contains_point (x-dx, y-dy) in
t#get_shape#visit (visitor :> Shape.shape_visitor);
result <- visitor#result
end
let contains_point p (s : #Shape.shape) =
let visitor = new contains_point p in
s#visit (visitor :> Shape.shape_visitor);
visitor#result
end;;
next prev parent reply other threads:[~2006-07-11 7:32 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
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 [this message]
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=20060711.163207.72458365.garrigue@math.nagoya-u.ac.jp \
--to=garrigue@math.nagoya-u.ac.jp \
--cc=brogoff@speakeasy.net \
--cc=caml-list@yquem.inria.fr \
/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