* Instance variables can't be polymorphic? @ 2009-04-05 23:16 Zheng Li 2009-04-06 3:40 ` [Caml-list] " Jacques Garrigue 0 siblings, 1 reply; 4+ messages in thread From: Zheng Li @ 2009-04-05 23:16 UTC (permalink / raw) To: OCaml Hi, Here is an example: ---- # class c = object val iter = List.iter end;; class c : object val iter : ('a -> unit) -> 'a list -> unit end ---- Since iter is a instance variable, the type parameter 'a won't be required to parameterize the type of the class, perfect! But it's still not polymorphic. ---- # let o = object inherit c method do_sth = iter print_int []; iter print_string [] end;; Characters 69-81: method do_sth = iter print_int []; iter print_string [] ^^^^^^^^^^^^ Error: This expression has type string -> unit but is here used with type int -> unit ---- Is that reasonable? The inference of class c is done before the declaration of object o, and the type signature says it's polymorphic (not a weak one '_a). Trying to declare the polymorphism explicitly as -- val iter : 'a. ('a -> unit) -> 'a list -> unit = List.iter -- won't work. This syntax is only allowed for methods. Given that I really want to use polymorphic functions this way: as instance variable and accessible through inheritance, is there any workaround or suggestions ? Thanks -- Zheng ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [Caml-list] Instance variables can't be polymorphic? 2009-04-05 23:16 Instance variables can't be polymorphic? Zheng Li @ 2009-04-06 3:40 ` Jacques Garrigue 2009-04-06 8:35 ` Instance variables can't be polymorphic? {a few more annoyances on "val" syntax} Zheng Li 0 siblings, 1 reply; 4+ messages in thread From: Jacques Garrigue @ 2009-04-06 3:40 UTC (permalink / raw) To: zheng_li; +Cc: caml-list From: Zheng Li <zheng_li@users.sourceforge.net> > Here is an example: > > ---- > # class c = object > val iter = List.iter > end;; > class c : object val iter : ('a -> unit) -> 'a list -> unit end > ---- > > Since iter is a instance variable, the type parameter 'a won't be > required to parameterize the type of the class, perfect! > > But it's still not polymorphic. > > ---- > # let o = object > inherit c > method do_sth = iter print_int []; iter print_string [] > end;; > Characters 69-81: > method do_sth = iter print_int []; iter print_string [] > ^^^^^^^^^^^^ > Error: This expression has type string -> unit but is here used with type > int -> unit > ---- > > Is that reasonable? The inference of class c is done before the > declaration of object o, and the type signature says it's polymorphic > (not a weak one '_a). Actually it's polymorphic, but only at the level of inheritance. You could define two objects inheriting from c, one using print_int, and the other print_string, and this would work. Due to functional update (i.e. {< iter = ... >}), object-level polymorphism would have to be explicit, but as you pointed next, no syntax is provided for explicitly polymorphic fields. > Trying to declare the polymorphism explicitly as > > -- > val iter : 'a. ('a -> unit) -> 'a list -> unit = List.iter > -- > > won't work. This syntax is only allowed for methods. Yes. It would be too difficult to add such a functionality, but what kind of application do you have in mind? > Given that I really want to use polymorphic functions this way: as > instance variable and accessible through inheritance, is there any > workaround or suggestions ? The simplest way I see currently is to use a let defined field (i.e., before the object keyword, but then you can't access it after inheritance), or to use a private method. What is your problem with a private method? It should be more flexible. Of course you can also define a record to wrap your polymorphic value. Jacques Garrigue ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: Instance variables can't be polymorphic? {a few more annoyances on "val" syntax} 2009-04-06 3:40 ` [Caml-list] " Jacques Garrigue @ 2009-04-06 8:35 ` Zheng Li 2009-04-06 9:55 ` [Caml-list] " Goswin von Brederlow 0 siblings, 1 reply; 4+ messages in thread From: Zheng Li @ 2009-04-06 8:35 UTC (permalink / raw) To: Jacques Garrigue; +Cc: caml-list Hello Jacques, On 4/6/2009 5:40 AM, Jacques Garrigue wrote: > > Actually it's polymorphic, but only at the level of inheritance. > You could define two objects inheriting from c, one using print_int, > and the other print_string, and this would work. > > Due to functional update (i.e. {< iter = ...>}), object-level > polymorphism would have to be explicit, but as you pointed next, no > syntax is provided for explicitly polymorphic fields. Thanks for your clear explanation! >> Trying to declare the polymorphism explicitly as >> >> -- >> val iter : 'a. ('a -> unit) -> 'a list -> unit = List.iter >> -- >> >> won't work. This syntax is only allowed for methods. > > Yes. It would be too difficult to add such a functionality, but what > kind of application do you have in mind? One of my project relies heavily on OO. We choose OO not in the traditional OO sense, but for the benefits of - structural subtyping - privileges control The OO part is merely an "interface". The core is functional, and all the objects will be dropped right after the declaration/initialization phrase. Here, selective access restriction of some data by declaring them as instance variable is just one way to control privilege, so that only objects of current class and its subclasses can access them. It's not 100% safe since such objects can still expose the data again through public methods, however this will only happen when they really intend and take effort to make the mistake(?) > The simplest way I see currently is to use a let defined field (i.e., > before the object keyword, but then you can't access it after > inheritance), or to use a private method. What is your problem with a > private method? It should be more flexible. > Of course you can also define a record to wrap your polymorphic value. Yes, private method is also the closest solution I could though of. "let" is not acceptable since the definition must be accessible through inheritance. I preferred instance variable (if it could work in the same way) than private method since - it's more lightweight in syntax - it's more lightweight in execution cost - with instance variable, I can totally drop all objects right after the initialization; with private method, some part of the definition will still point back to objects since they contain self#xxx inside. But anyway, assorting to private methods is still acceptable considering various aspects. I will probably take this approach. [OT]: Here are a few more annoyances on the syntax of instance variable I've encountered. I recorded it here for comments: Why it can't just copy the common "let" syntax in OCaml? Even though it's possible to just lift the awkward "val" definitions out of objects and using "let" instead, I'm really uncomfortable when being forced to do that. Besides, the lifted variables won't be accessible through inheritance any more, so they are not strictly equivalent or interchangeable in semantics. Currently, the "val" syntax - doesn't support pattern matching assignment. Instead of -- let a,b,c,d = tuple4 -- one write -- val a = match tuple4 with a,_,_,_ -> a val b = match tuple4 with _,b,_,_ -> b val c = match tuple4 with _,_,c,_ -> c val d = match tuple4 with _,_,_,d -> d -- This is still the easy case, image if your pattern matching will also trigger some side-effect. - doesn't support sharing state. -- let up,down = let r = ref 0 in (fun () -> incr r; !r), (fun () -> decr r; !r) -- can't be expressed directly as instance variables - doesn't support shortcut syntax of function definition like -- val f x y z = x + y + z -- instead one must write -- val f = fun x y z -> x + y + z -- - doesn't support recursion. Instead of -- val rec fact n = if n <= 1 then 1 else n * fact (n-1) -- one must write -- val fact = let rec fact_rec n = if n <= 1 then 1 else n * fact_rec (n-1) in fact_rec -- - all parallel assignments, no assignment orders, hence can't refer to previous assignment -- val x = 3 val y = x + 11 -- is wrong, even if it makes perfect sense in many situations. To access "x", one is simply forced to declare "y" as method! Any comments? -- Zheng ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [Caml-list] Re: Instance variables can't be polymorphic? {a few more annoyances on "val" syntax} 2009-04-06 8:35 ` Instance variables can't be polymorphic? {a few more annoyances on "val" syntax} Zheng Li @ 2009-04-06 9:55 ` Goswin von Brederlow 0 siblings, 0 replies; 4+ messages in thread From: Goswin von Brederlow @ 2009-04-06 9:55 UTC (permalink / raw) To: Zheng Li; +Cc: Jacques Garrigue, caml-list Zheng Li <zheng_li@users.sourceforge.net> writes: > [OT]: Here are a few more annoyances on the syntax of instance > variable I've encountered. I recorded it here for comments: > > Why it can't just copy the common "let" syntax in OCaml? Even though > it's possible to just lift the awkward "val" definitions out of > objects and using "let" instead, I'm really uncomfortable when being > forced to do that. Besides, the lifted variables won't be accessible > through inheritance any more, so they are not strictly equivalent or > interchangeable in semantics. > > Currently, the "val" syntax > > - doesn't support pattern matching assignment. Instead of > -- > let a,b,c,d = tuple4 > -- > one write > -- > val a = match tuple4 with a,_,_,_ -> a > val b = match tuple4 with _,b,_,_ -> b > val c = match tuple4 with _,_,c,_ -> c > val d = match tuple4 with _,_,_,d -> d > -- > This is still the easy case, image if your pattern matching will > also trigger some side-effect. class foo = let (a,b,c,d) = tuple4 in object val a = a val b = b val c = c val d = d end > - doesn't support sharing state. > -- > let up,down = > let r = ref 0 in > (fun () -> incr r; !r), > (fun () -> decr r; !r) > -- > can't be expressed directly as instance variables Same thing. Use let to create the shared state and then assign in the object. Although that really ought to be written as class foo : object (* to hide count if you really want that *) method private up : unit method private down : unit end = object val count = ref 0 method private up = incr count method private down = decr count end > - doesn't support shortcut syntax of function definition like > -- > val f x y z = x + y + z > -- > instead one must write > -- > val f = fun x y z -> x + y + z > -- same > - doesn't support recursion. Instead of > -- > val rec fact n = > if n <= 1 then 1 else n * fact (n-1) > -- > one must write > -- > val fact = > let rec fact_rec n = > if n <= 1 then 1 else n * fact_rec (n-1) in > fact_rec > -- same > - all parallel assignments, no assignment orders, hence can't refer to > previous assignment > > -- > val x = 3 > val y = x + 11 > -- > > is wrong, even if it makes perfect sense in many situations. To access > "x", one is simply forced to declare "y" as method! same again. > Any comments? Yes, ocaml objects can drive one nuts. :) You seem to want to use classes with static functions (functions that do not have/use self). Why not use records? Is that just because you can not coerce record to a "subtype"? Sometimes one can use modules and functors instead of objects. MfG Goswin ^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2009-04-06 9:55 UTC | newest] Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2009-04-05 23:16 Instance variables can't be polymorphic? Zheng Li 2009-04-06 3:40 ` [Caml-list] " Jacques Garrigue 2009-04-06 8:35 ` Instance variables can't be polymorphic? {a few more annoyances on "val" syntax} Zheng Li 2009-04-06 9:55 ` [Caml-list] " Goswin von Brederlow
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox