* Why can't immediate objects be extended? @ 2008-07-12 14:12 Richard Jones 2008-07-12 14:26 ` [Caml-list] " Richard Jones ` (3 more replies) 0 siblings, 4 replies; 5+ messages in thread From: Richard Jones @ 2008-07-12 14:12 UTC (permalink / raw) To: caml-list I'm wondering if there's a reason why one cannot inherit from immediate objects? (See description at: http://caml.inria.fr/pub/docs/manual-ocaml/manual005.html#ss:immediate-objects) Is it just a syntax problem because the 'inherit' keyword currently needs to take a class type, or is there a deeper reason? This is the code I'd like to write (non-working, obviously): type 'a tree = Leaf of string | Node of 'a tree * 'a * 'a tree let none = object end let tree = Node (Leaf "1", none, Leaf "2") let rec string_of_tree = function | Leaf str -> str | Node (left, _, right) -> "(" ^ string_of_tree left ^ "," ^ string_of_tree right ^ ")" let rec annotate = function | (Leaf _ as t) -> t | (Node (left, parent_obj, right) as t) -> let obj = object inherit (typeof parent_obj) method str = string_of_tree t end in Node (annotate left, obj, annotate right) let tree = annotate tree The problematic function is 'annotate'. I believe I want annotate to have a type along these lines (again, this is not precisely OCaml code because I've used alpha to stand for '..'): val annotate : < 'a > tree -> < str : string; 'a > tree Rich. -- Richard Jones Red Hat ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [Caml-list] Why can't immediate objects be extended? 2008-07-12 14:12 Why can't immediate objects be extended? Richard Jones @ 2008-07-12 14:26 ` Richard Jones 2008-07-14 1:47 ` Peng Zang ` (2 subsequent siblings) 3 siblings, 0 replies; 5+ messages in thread From: Richard Jones @ 2008-07-12 14:26 UTC (permalink / raw) To: caml-list On Sat, Jul 12, 2008 at 03:12:00PM +0100, Richard Jones wrote: > let obj = object > inherit (typeof parent_obj) > method str = string_of_tree t > end in > Node (annotate left, obj, annotate right) Further exploration reveals I can write this, which is _almost_ what I want: let obj = object inherit object method parent = parent_obj end method str = string_of_tree t end in ... except the indirection through a parent method is not helpful for what I'm trying to achieve (an extensible static type that doesn't depend on the order in which the type is extended). The types produced by this are: val annotate : 'a tree -> < parent : 'a; str : string > tree = <fun> val tree : < parent : < >; str : string > tree = (* ... *) Rich. -- Richard Jones Red Hat ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [Caml-list] Why can't immediate objects be extended? 2008-07-12 14:12 Why can't immediate objects be extended? Richard Jones 2008-07-12 14:26 ` [Caml-list] " Richard Jones @ 2008-07-14 1:47 ` Peng Zang 2008-07-14 14:38 ` Keiko Nakata 2008-07-16 1:43 ` Jacques Garrigue 3 siblings, 0 replies; 5+ messages in thread From: Peng Zang @ 2008-07-14 1:47 UTC (permalink / raw) To: caml-list; +Cc: Richard Jones, caml-list -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On Saturday 12 July 2008 10:12:00 am Richard Jones wrote: > I'm wondering if there's a reason why one cannot inherit from > immediate objects? (See description at: > http://caml.inria.fr/pub/docs/manual-ocaml/manual005.html#ss:immediate-obje >cts) Is it just a syntax problem because the 'inherit' keyword currently > needs to take a class type, or is there a deeper reason? I have no idea, however, using some black magic we can accomplish exactly this: - ----------- snip of temp.ml ------------- (** ported from hash.c **) let caml_hash_variant name = let acc = ref 0 in let len = String.length name in for i = 0 to len - 1 do acc := (223 * !acc + Char.code (String.get name i)) land 0x7FFFFFFF; done; !acc ;; (** the return type is needs casting **) let addmethod obj methodname methodfun = let methodsuite = Obj.field obj 0 in let newms = let nummethods : int = Obj.magic (Obj.field methodsuite 0) in let size = Obj.size methodsuite in let arr = Array.create (size+2) 0 in arr.(0) <- nummethods + 1; for i = 1 to size - 1 do arr.(i) <- Obj.magic (Obj.field methodsuite i); done; arr.(size) <- methodfun; arr.(size+1) <- caml_hash_variant methodname; arr in let obj' = Obj.dup obj in Obj.set_field obj' 0 (Obj.magic newms); obj' ;; let addmethod = Obj.magic addmethod let addmethod : (< .. > as 'a) -> string -> ('a -> 'b) -> < .. > = addmethod;; let foo = object method foo = "foo" end;; let foobar : <foo:string; bar:string> = addmethod foo "bar" (fun _ -> "bar");; foo#foo;; foobar#foo;; foobar#bar;; - ----------- end snip ---------- Objective Caml version 3.09.3 # #use "temp.ml";; val caml_hash_variant : string -> int = <fun> val addmethod : Obj.t -> string -> int -> Obj.t = <fun> val addmethod : 'a = <poly> val addmethod : (< .. > as 'a) -> string -> ('a -> 'b) -> < .. > = <fun> val foo : < foo : string > = <obj> val foobar : < bar : string; foo : string > = <obj> - - : string = "foo" - - : string = "foo" - - : string = "bar" # Not pretty, but it works, Peng -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.7 (GNU/Linux) iD8DBQFIerBLfIRcEFL/JewRAnTpAJ9LdD09DsVvgJHemCf3ROzGqH+dQwCfRAoX 7sOvInXyvq8jDfF+ucZhzic= =V3Ki -----END PGP SIGNATURE----- ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [Caml-list] Why can't immediate objects be extended? 2008-07-12 14:12 Why can't immediate objects be extended? Richard Jones 2008-07-12 14:26 ` [Caml-list] " Richard Jones 2008-07-14 1:47 ` Peng Zang @ 2008-07-14 14:38 ` Keiko Nakata 2008-07-16 1:43 ` Jacques Garrigue 3 siblings, 0 replies; 5+ messages in thread From: Keiko Nakata @ 2008-07-14 14:38 UTC (permalink / raw) To: rich; +Cc: caml-list Hello. > I'm wondering if there's a reason why one cannot inherit from > immediate objects? (See description at: > http://caml.inria.fr/pub/docs/manual-ocaml/manual005.html#ss:immediate-objects) > Is it just a syntax problem because the 'inherit' keyword currently > needs to take a class type, or is there a deeper reason? I do not think it is a syntax problem. Here is my understanding: The type of a class and the type of an immediate object are essentially different. In other words, the self type of a class is open, thus extensible; the self type of an immediate object is closed, thus not extensible. As written at: http://caml.inria.fr/pub/docs/manual-ocaml/manual005.html#ss:immediate-objects) the difference gives you different advantages; I suspect this is one reason. Best regards, Keiko ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [Caml-list] Why can't immediate objects be extended? 2008-07-12 14:12 Why can't immediate objects be extended? Richard Jones ` (2 preceding siblings ...) 2008-07-14 14:38 ` Keiko Nakata @ 2008-07-16 1:43 ` Jacques Garrigue 3 siblings, 0 replies; 5+ messages in thread From: Jacques Garrigue @ 2008-07-16 1:43 UTC (permalink / raw) To: rich; +Cc: caml-list From: Richard Jones <rich@annexia.org> > I'm wondering if there's a reason why one cannot inherit from > immediate objects? (See description at: > http://caml.inria.fr/pub/docs/manual-ocaml/manual005.html#ss:immediate-objects) > Is it just a syntax problem because the 'inherit' keyword currently > needs to take a class type, or is there a deeper reason? > > This is the code I'd like to write (non-working, obviously): [..] > let rec annotate = function > | (Leaf _ as t) -> t > | (Node (left, parent_obj, right) as t) -> > let obj = object > inherit (typeof parent_obj) > method str = string_of_tree t > end in > Node (annotate left, obj, annotate right) [..] > The problematic function is 'annotate'. I believe I want annotate to > have a type along these lines (again, this is not precisely OCaml code > because I've used alpha to stand for '..'): > > val annotate : < 'a > tree -> < str : string; 'a > tree There are several problems here. What what you here is extensible records, with differential rows (i.e. you need some way to ensure that str is not in 'a); otherwise you would end up with a record with two str fiels, with possibly different type. Extensible records are not available in ocaml, and while objects allow structural typing of records, they do not allow extension. So the next question is why objects do not allow that. And here the answer is very clear: this form of inheritance is incompatible with subtyping. Namely, by subtyping you can hide a field. So you could start with a <data: int; str: float> tree, coerce it to <data: int> tree by subtyping, and then annotate it and obtain a <data: int; str: string> tree. If we were talking about records, there would be no problem, but those are objects, so the definition of data may actually be method data = truncate self#str If str now returns a string, this is broken. This question is studied in details in Abadi and Cardelli's "A theory of objects". So there is no way you can inherit from an immediate object. (The syntax "inherit object ... end" is not about immediate objects but immediate classes (inside another class), and is not really useful) Going back to your original problem, another approach would be to allow extension of objects _without overriding of methods_. The trouble here is that it would require major changes in the type system, to accomodate the differential rows mentioned above, for something not directly connected with objects. Now about workarounds. Since you problem is really a problem of records, the simplest approach might be to use... records! type ('str,'cmt) parent_data = {str: 'str; cmt: 'cmt} let none = {str = (); cmt = ()} let annotate_data d (str:string) = {d with str = str} (* ('a, 'b) parent_data -> string -> (string, 'b) parent_data *) Note here how the type is updated when you use the with construct. This should provide you with the behaviour you want. This may not be as polymorphic as you hoped (you need to know all the fields w\you will use in advance), but providing a fully polymorphic solution to the update problem requires a very complicated type system (look at Didier Remy's papers) Also, if you want lots of fields, this may be a good idea to use a constraint to name parameters. type +'a parent_data = {str: 'str; cmt: 'cmt} constraint 'a = <str:'str; cmt:'cmt> The explicit variance annotation is required here because it is not automatically inferred for constrained parameters. With this definition, the type of none becomes: < cmt : unit; str : unit > parent_data Hope this helps, Jacques Garrigue ^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2008-07-16 1:43 UTC | newest] Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2008-07-12 14:12 Why can't immediate objects be extended? Richard Jones 2008-07-12 14:26 ` [Caml-list] " Richard Jones 2008-07-14 1:47 ` Peng Zang 2008-07-14 14:38 ` Keiko Nakata 2008-07-16 1:43 ` Jacques Garrigue
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox