caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* [Caml-list] dynamic runtime cast in Ocaml
@ 2002-11-06 11:53 Basile STARYNKEVITCH
  2002-11-06 12:54 ` Xavier Leroy
  0 siblings, 1 reply; 9+ messages in thread
From: Basile STARYNKEVITCH @ 2002-11-06 11:53 UTC (permalink / raw)
  To: caml-list

Dear Ocaml developers

I am sometimes lacking the dynamic cast (with a runtime test) in
Ocaml. Assuming that I have the usual point and colored_point classes
(as in the 3.06 Manual), I want to deal with point array-s and test if
the 3rd point is in fact a colored point.

Is there some type-theoritical issues here? I thought a few minutes
(assuming a single-inheritance world) and found none, but I am not a
type theorist and I am (sadly) not working at INRIA. Perhaps
parameterized classes and constraints are an issue... But we ordinary
people need some explanations about it..

Is there some implementation issues here? There could be some with
multiple-inheritance, but I think that dynamic cast could be
restricted to a single-inheritance sub-world, and the classical
ObjVlisp model offer a quick runtime test for this. BTW, I believe
that the existing runtime has most of the features required for such a
test.

Is there some syntax issues here? I suggest using the pattern matching
with a object keyword, so

(* test if a point is in fact a colored one *)
let point_is_colored (pt: point) = match pt with
   object colored_point -> true
  | _ -> false

(* get the color of a point, if the point is not colored, fail *)
let color_of_point = function 
   (object colored_point) as p -> p#color
 | _ -> failwith "no color in point"

Actually I really think that the essence of object-orientation is
runtime dynamic cast (or class disambiguation or the instanceof Java
operator, etc....). I never happen to use Ocaml object system without
badly needing such a dynamic cast (of course it can be painfully
simulated, etc...).

Perhaps the question has been asked a billion times, then it might go
into a FAQ.

regards.
-- 

Basile STARYNKEVITCH         http://starynkevitch.net/Basile/ 
email: basile<at>starynkevitch<dot>net 
alias: basile<at>tunes<dot>org 
8, rue de la Faïencerie, 92340 Bourg La Reine, France
-------------------
To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners


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

* Re: [Caml-list] dynamic runtime cast in Ocaml
  2002-11-06 11:53 [Caml-list] dynamic runtime cast in Ocaml Basile STARYNKEVITCH
@ 2002-11-06 12:54 ` Xavier Leroy
  2002-11-07  2:01   ` Michael Vanier
  2002-11-07  3:28   ` Walid Taha
  0 siblings, 2 replies; 9+ messages in thread
From: Xavier Leroy @ 2002-11-06 12:54 UTC (permalink / raw)
  To: Basile STARYNKEVITCH; +Cc: caml-list

> I am sometimes lacking the dynamic cast (with a runtime test) in
> Ocaml. Assuming that I have the usual point and colored_point classes
> (as in the 3.06 Manual), I want to deal with point array-s and test if
> the 3rd point is in fact a colored point.
> Is there some type-theoritical issues here?

There was a long thread on this topic on this list not long ago.
Several approaches were discussed: using datatypes (Point of point |
CPoint of cpoint), extensible datatypes (via the type "exn" of
exceptions), etc.  See also Coca-ML:
http://www.pps.jussieu.fr/~emmanuel/Public/Dev/coca-ml/index-en.html

This said, my opinion on downcasts is that they are a low-level,
dangerous feature that is best replaced by advanced, statically-typed
constructs like OCaml provides.  (Some day, I'll have a bumper sticker
custom-made that reads "Caml programmers do it statically".)

In my (admittedly limited) experience with Java, 95% of downcasts in
Java code fall in one of the following scenarios:
- when using container classes (program puts a Foo in a Hashtable,
  reads it back as Object, needs downcast to Foo);
- when using binary methods (equal(), compare())
- to encode sum types (a Foo is a Bar or a Gee).

The OCaml type system is able to type-check all three scenarios
statically, using parameterized classes, "mytype" specialization,
and datatypes / variants (respectively).

The remaining 5% of downcasts were kludges where the programmer
managed to ruin a perfectly good class hierarchy by sprinkling type
tests everywhere, rather than subclassing and redefining virtual
methods adequately in classic OO fashion.

To be fair, I may have missed some legitimate uses of downcasts in
complicated situations.  But I believe these legitimate uses are
uncommon enough that it is best to find another way to express the
desired behavior, rather than extend OCaml with downcasts.

That you can do self-modifying code in assembler, Duff's device in C,
or downcasts in Java doesn't mean that you want to do it in OCaml as
well :-)

- Xavier Leroy
-------------------
To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners


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

* Re: [Caml-list] dynamic runtime cast in Ocaml
  2002-11-06 12:54 ` Xavier Leroy
@ 2002-11-07  2:01   ` Michael Vanier
  2002-11-07  8:11     ` Jacques Garrigue
  2002-11-07  3:28   ` Walid Taha
  1 sibling, 1 reply; 9+ messages in thread
From: Michael Vanier @ 2002-11-07  2:01 UTC (permalink / raw)
  To: caml-list


> Date: Wed, 6 Nov 2002 13:54:28 +0100
> From: Xavier Leroy <xavier.leroy@inria.fr>
> 
> > I am sometimes lacking the dynamic cast (with a runtime test) in
> > Ocaml. Assuming that I have the usual point and colored_point classes
> > (as in the 3.06 Manual), I want to deal with point array-s and test if
> > the 3rd point is in fact a colored point.
> > Is there some type-theoritical issues here?
> 
> There was a long thread on this topic on this list not long ago.
> Several approaches were discussed: using datatypes (Point of point |
> CPoint of cpoint), extensible datatypes (via the type "exn" of
> exceptions), etc.  See also Coca-ML:
> http://www.pps.jussieu.fr/~emmanuel/Public/Dev/coca-ml/index-en.html
> 

I started that thread, and I concluded at the end of it that all approaches
to simulating downcasting in ocaml were, at best, hacks.  From there it was
a short step to concluding that ocaml was simply not the best choice for my
application.  This is not to disparage ocaml, which is still my favorite
computer language, but sometimes you need something more dynamic.  Dynamic
is not a dirty word ;-)

I understand some of the objections to downcasting, but what I'm really
curious about is this: if the ocaml team really *wanted* to allow downcasts
(raising an exception on failure just like dividing by zero does), would it
be technically feasible?  By feasible I mean doable without nasty Obj.magic
hacks (no offense to coca-ml, which is very clever).

Mike
-------------------
To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners


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

* Re: [Caml-list] dynamic runtime cast in Ocaml
  2002-11-06 12:54 ` Xavier Leroy
  2002-11-07  2:01   ` Michael Vanier
@ 2002-11-07  3:28   ` Walid Taha
  2002-11-07  7:22     ` Jacques Garrigue
  1 sibling, 1 reply; 9+ messages in thread
From: Walid Taha @ 2002-11-07  3:28 UTC (permalink / raw)
  Cc: caml-list


Were nested quantifiers (either existentials or universals) considered in
the context of OCaml?  If not, are there plans to add them?  Thanks.

Walid.

On Wed, 6 Nov 2002, Xavier Leroy wrote:

|> I am sometimes lacking the dynamic cast (with a runtime test) in
|> Ocaml. Assuming that I have the usual point and colored_point classes
|> (as in the 3.06 Manual), I want to deal with point array-s and test if
|> the 3rd point is in fact a colored point.
|> Is there some type-theoritical issues here?
|
|There was a long thread on this topic on this list not long ago.
|Several approaches were discussed: using datatypes (Point of point |
|CPoint of cpoint), extensible datatypes (via the type "exn" of
|exceptions), etc.  See also Coca-ML:
|http://www.pps.jussieu.fr/~emmanuel/Public/Dev/coca-ml/index-en.html
|
|This said, my opinion on downcasts is that they are a low-level,
|dangerous feature that is best replaced by advanced, statically-typed
|constructs like OCaml provides.  (Some day, I'll have a bumper sticker
|custom-made that reads "Caml programmers do it statically".)
|
|In my (admittedly limited) experience with Java, 95% of downcasts in
|Java code fall in one of the following scenarios:
|- when using container classes (program puts a Foo in a Hashtable,
|  reads it back as Object, needs downcast to Foo);
|- when using binary methods (equal(), compare())
|- to encode sum types (a Foo is a Bar or a Gee).
|
|The OCaml type system is able to type-check all three scenarios
|statically, using parameterized classes, "mytype" specialization,
|and datatypes / variants (respectively).
|
|The remaining 5% of downcasts were kludges where the programmer
|managed to ruin a perfectly good class hierarchy by sprinkling type
|tests everywhere, rather than subclassing and redefining virtual
|methods adequately in classic OO fashion.
|
|To be fair, I may have missed some legitimate uses of downcasts in
|complicated situations.  But I believe these legitimate uses are
|uncommon enough that it is best to find another way to express the
|desired behavior, rather than extend OCaml with downcasts.
|
|That you can do self-modifying code in assembler, Duff's device in C,
|or downcasts in Java doesn't mean that you want to do it in OCaml as
|well :-)
|
|- Xavier Leroy
|-------------------
|To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
|Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
|Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
|

-------------------
To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners


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

* Re: [Caml-list] dynamic runtime cast in Ocaml
  2002-11-07  3:28   ` Walid Taha
@ 2002-11-07  7:22     ` Jacques Garrigue
  2002-11-07 14:49       ` Walid Taha
  2002-11-08 15:26       ` Alain Frisch
  0 siblings, 2 replies; 9+ messages in thread
From: Jacques Garrigue @ 2002-11-07  7:22 UTC (permalink / raw)
  To: taha; +Cc: caml-list

From: Walid Taha <taha@cs.rice.edu>

> Were nested quantifiers (either existentials or universals) considered in
> the context of OCaml?  If not, are there plans to add them?  Thanks.

I'm not sure of what you are asking about, and whether this is
relevant to the question of runtime casts.

If this is a question of type systems, then yes there are nested
universal quantifiers in ocaml, which you can use either through
object types (polymorphic methods), record types (polymorphic fields)
or the module system (not first-class quantification, but this was not
explicit in your question).
For existential quantification, you only get it more or less with
modules. Note that modules defined by "let module" are a bit weak in
this context, as the types they define cannot escape their scope.

Does this answer your question, or were you talking about something
else?

By the way, for the expressivity addict (Curry-style), there is now a
branch in CVS with support for a specific form of dependent types. You
can get it by
  cvs update -r multimatch `cat testlabl/dirs_multimatch`
(when it is not broken).
I plan to provide it as a patch after the next release.

This allows you to do things like:
# let convert x y =
    multimatch y with
      `Int -> x
    | `Float -> float x
    | `String -> string_of_int x;;
val convert :
  int ->
  [< `Float & 'a = float | `Int & 'a = int | `String & 'a = string] -> 'a =
  <fun>
# convert 3 `String;;
- : string = "3"
# convert 2 `Float;;
- : float = 2.
and this without any overloading...

---------------------------------------------------------------------------
Jacques Garrigue      Kyoto University     garrigue at kurims.kyoto-u.ac.jp
		<A HREF=http://wwwfun.kurims.kyoto-u.ac.jp/~garrigue/>JG</A>
-------------------
To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners


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

* Re: [Caml-list] dynamic runtime cast in Ocaml
  2002-11-07  2:01   ` Michael Vanier
@ 2002-11-07  8:11     ` Jacques Garrigue
  0 siblings, 0 replies; 9+ messages in thread
From: Jacques Garrigue @ 2002-11-07  8:11 UTC (permalink / raw)
  To: mvanier; +Cc: caml-list

From: Michael Vanier <mvanier@cs.caltech.edu>

> I understand some of the objections to downcasting, but what I'm really
> curious about is this: if the ocaml team really *wanted* to allow downcasts
> (raising an exception on failure just like dividing by zero does), would it
> be technically feasible?  By feasible I mean doable without nasty Obj.magic
> hacks (no offense to coca-ml, which is very clever).

Sure, it would be feasible.
And a bit more efficient than coca-ml, since we could put the class
identifier in a field rather than access it through a method.
But it would mean maintaining more runtime data for a feature of
disputed use.  From this point of view coca-ml is a possible approach:
it seems efficient enough, and you only use it when you really need
downcasting.

Note that coca-ml chooses to use Obj.magic, but there other ways to do
downcasting which do not require any magic. The weak hash-table
approach (see Weak_memo in Remy Vanicat's hweak library), or the
exception approach are examples of ways to do that.

And maybe someday we will see the light, and add a -with-rtti option
to Objective Caml. But do not hold your breath, as there is a strong
resistance to such an asymetric feature, which would work only on
non-parametric classes.

And this all the more as parametric classes are actually yet another
way to solve the problem:

class ['a] a (x : int) = object (self)
  val mutable x = x
  method x = x
  method me : 'a = `Ta (self :> _ a)
end

class ['a] b x = object (self)
  inherit ['a] a x
  method set_x y = x <- y
  method me : 'a = `Tb (self :> _ b)
end

# let some_b = new b 1;;
val some_b : (_[> `Ta of '_a a | `Tb of '_a b] as 'a) b = <obj>
# let hidden_b = (some_b :> _ a);;
val hidden_b : (_[> `Ta of '_a a | `Tb of '_a b] as 'a) a = <obj>
# match hidden_b#me with `Tb b -> b | _ -> assert false;;
- : (_[> `Ta of '_b a | `Tb of 'a] as 'b) b as 'a = <obj>

Ahem, types are ugly, but it works...

Jacques Garrigue
-------------------
To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners


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

* Re: [Caml-list] dynamic runtime cast in Ocaml
  2002-11-07  7:22     ` Jacques Garrigue
@ 2002-11-07 14:49       ` Walid Taha
  2002-11-08 15:26       ` Alain Frisch
  1 sibling, 0 replies; 9+ messages in thread
From: Walid Taha @ 2002-11-07 14:49 UTC (permalink / raw)
  To: Jacques Garrigue; +Cc: caml-list, Emir Pasalic


Hi Jacques,

Thank you for your quick responce.

On Thu, 7 Nov 2002, Jacques Garrigue wrote:

|From: Walid Taha <taha@cs.rice.edu>
|
|> Were nested quantifiers (either existentials or universals) considered in
|> the context of OCaml?  If not, are there plans to add them?  Thanks.
|
|I'm not sure of what you are asking about, and whether this is
|relevant to the question of runtime casts.

Sorry if it wasn't clear, but you've answered along the right lines.
Need to dynamic casting (outside specifics of the oo setting) sometimes
can be replaced by abstract datatypes (existentials) or dependent types
(which you mention below).

|If this is a question of type systems, then yes there are nested
|universal quantifiers in ocaml, which you can use either through
|object types (polymorphic methods), record types (polymorphic fields)
|or the module system (not first-class quantification, but this was not
|explicit in your question).
|For existential quantification, you only get it more or less with
|modules. Note that modules defined by "let module" are a bit weak in
|this context, as the types they define cannot escape their scope.
|
|Does this answer your question, or were you talking about something
|else?

Certainly.  Do you know if there are any plans to add nested quantifiers
explicitly?

|By the way, for the expressivity addict (Curry-style), there is now a
|branch in CVS with support for a specific form of dependent types. You
|can get it by
|  cvs update -r multimatch `cat testlabl/dirs_multimatch`
|(when it is not broken).
|I plan to provide it as a patch after the next release.

This sounds very interesting!  I'll check it.  Thanks!

Walid.

-------------------
To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners


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

* Re: [Caml-list] dynamic runtime cast in Ocaml
  2002-11-07  7:22     ` Jacques Garrigue
  2002-11-07 14:49       ` Walid Taha
@ 2002-11-08 15:26       ` Alain Frisch
  2002-11-11  9:26         ` Jacques Garrigue
  1 sibling, 1 reply; 9+ messages in thread
From: Alain Frisch @ 2002-11-08 15:26 UTC (permalink / raw)
  To: Jacques Garrigue; +Cc: Caml list

On Thu, 7 Nov 2002, Jacques Garrigue wrote:

> By the way, for the expressivity addict (Curry-style), there is now a
> branch in CVS with support for a specific form of dependent types.

Nice !  Do you have specific cases of application in mind ?
It's amazing to see how Caml succeed in escaping ML jail (rows, HO
polymorphism, etc...).

> I plan to provide it as a patch after the next release.

Any long-term plan for inclusion in OCaml ?

I guess that backtracking unification could benefit to OCaml in other
places (e.g.:undoing the effect of typing an ill-typed expression in the
toplevel).


> and this without any overloading...

Well, you could also say that this is a lightweight solution for
overloading ...


Let's play a little bit ...

# fun x -> multimatch x with (a, `A x) -> (a,x) | (a, `B y) -> a + y;;
This expression has type int but is here used with type int * 'a

Mmm, need to rewrite it this way:

# fun x -> match x with (a, z) -> multimatch z with `A -> (a,x) | `B y -> a + y;;
- : (int * [< `A & 'b = int * 'a | `B of int & 'b = int] as 'a) -> 'b = <fun>


Do you have any paper/doc describing multimatch typing ?


-- Alain

-------------------
To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners


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

* Re: [Caml-list] dynamic runtime cast in Ocaml
  2002-11-08 15:26       ` Alain Frisch
@ 2002-11-11  9:26         ` Jacques Garrigue
  0 siblings, 0 replies; 9+ messages in thread
From: Jacques Garrigue @ 2002-11-11  9:26 UTC (permalink / raw)
  To: frisch; +Cc: caml-list

From: Alain Frisch <frisch@clipper.ens.fr>
> > By the way, for the expressivity addict (Curry-style), there is now a
> > multimatch branch in CVS with support for a specific form of
> > dependent types. 
> 
> Nice !  Do you have specific cases of application in mind ?
> It's amazing to see how Caml succeed in escaping ML jail (rows, HO
> polymorphism, etc...).

I don't know. Actually I was quite dubious about the usefulness of
such a feature until a member of the Coq team told me that he
sometimes wished he could write programs that way. I suppose you need
some exposure to higher-order type systems before you can imagine
applications.
By the way, there was a nice example of encoding set types in variants
in TIP'02 in Dagstuhl, and this encoding would work (partially) with
this extension.

> Any long-term plan for inclusion in OCaml ?

None. This feature is fun, but it's still unclear whether it is really
useful. Not that i'm not convinced that dependent types are useful,
but dependent types are much more than this simple hack.

Another problem is that while type inference works nicely,
interface inclusion is hard to check (Francois Pottier told me it was
NP-complete). I'm still looking for a reasonable algorithm:
exponential in the number of constructors is a bit too much.

> I guess that backtracking unification could benefit to OCaml in other
> places (e.g.:undoing the effect of typing an ill-typed expression in the
> toplevel).

Always looking in the corners, you are.
This is unrelated to the rest of the patch, and I actually plan to move
backtracking to the main trunk in the future.

> Do you have any paper/doc describing multimatch typing ?

All the theory (and why it was so easy) is in my FOOL9 paper.
  http://wwwfun.kurims.kyoto-u.ac.jp/~garrigue/papers/

For the implementation, it's just two new keywords, multifun and
multimatch, that trigger different typing rules.  Also there is clever
typing for as-patterns, which can help you get more readable types:

# let f x = multimatch x with `A -> 1
            | `B -> multimatch x with `A -> 'a' | `B -> true;;
val f : [< `A & 'a = int & 'b = char | `B & 'a = 'b & 'b = bool] -> 'a
# let f' = multifun `A|`B as x -> f x;;
val f' : [< `A & 'a = int | `B & 'a = bool] -> 'a

---------------------------------------------------------------------------
Jacques Garrigue      Kyoto University     garrigue at kurims.kyoto-u.ac.jp
		<A HREF=http://wwwfun.kurims.kyoto-u.ac.jp/~garrigue/>JG</A>
-------------------
To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners


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

end of thread, other threads:[~2002-11-12  9:09 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-11-06 11:53 [Caml-list] dynamic runtime cast in Ocaml Basile STARYNKEVITCH
2002-11-06 12:54 ` Xavier Leroy
2002-11-07  2:01   ` Michael Vanier
2002-11-07  8:11     ` Jacques Garrigue
2002-11-07  3:28   ` Walid Taha
2002-11-07  7:22     ` Jacques Garrigue
2002-11-07 14:49       ` Walid Taha
2002-11-08 15:26       ` Alain Frisch
2002-11-11  9:26         ` Jacques Garrigue

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).