* Why can't I call a function over a subclass? @ 2007-10-05 7:48 Luca de Alfaro 2007-10-05 8:01 ` [Caml-list] " Florian Hars ` (2 more replies) 0 siblings, 3 replies; 22+ messages in thread From: Luca de Alfaro @ 2007-10-05 7:48 UTC (permalink / raw) To: Inria Ocaml Mailing List [-- Attachment #1: Type: text/plain, Size: 1155 bytes --] Consider the following sample code, that refuses to type check in Ocaml: ---start--- class r (x_init: int) = object method get_x : int = x_init end let f (r1: r) (r2: r) : bool = (r1#get_x = r2#get_x) class r' (x_init: int) = object inherit r x_init method get_xx : int = 2 * x_init end let q (r1: r') (r2: r') = f r1 r2 ---end--- r' is a subclass of r. The compiler complains: File "class1.ml", line 12, characters 28-30: This expression has type r' but is here used with type r The second object type has no method get_xx Now, I know r does not have method get_xx, but why on Earth should this matter? I can see that there can be an error if I feed to f something that has FEWER methods, but why should it be an error to feed to f something with MORE methods?? The absurdity continues: if I instead declare f as: let f (r1: <get_x: int; ..>) (r2: <get_x: int; ..>) : bool = (r1#get_x = r2#get_x) then the code type-checks. Why is this fine but f: r -> r -> bool causes a type error? The situation does not make sense to me. Can someone shed some light on what is going on? (This with Ocaml 3.10.0 in case it matters) Best, Luca [-- Attachment #2: Type: text/html, Size: 1413 bytes --] ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [Caml-list] Why can't I call a function over a subclass? 2007-10-05 7:48 Why can't I call a function over a subclass? Luca de Alfaro @ 2007-10-05 8:01 ` Florian Hars 2007-10-05 8:08 ` Luca de Alfaro 2007-10-05 10:30 ` David Teller 2007-10-05 8:07 ` [Caml-list] " Pietro Abate 2007-10-05 10:55 ` Andrej Bauer 2 siblings, 2 replies; 22+ messages in thread From: Florian Hars @ 2007-10-05 8:01 UTC (permalink / raw) To: Luca de Alfaro; +Cc: Inria Ocaml Mailing List Luca de Alfaro schrieb: > The absurdity continues: This is not absurd, this is the documented correct behaviuor. If *you* decide that f must only accept arguments of *exactly* type r, the typechecker enforces your decision, as it does if you decide that f may also accept subtypes of r (as long as your decisions are consistent within he type system). Yours, Florian. ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [Caml-list] Why can't I call a function over a subclass? 2007-10-05 8:01 ` [Caml-list] " Florian Hars @ 2007-10-05 8:08 ` Luca de Alfaro 2007-10-05 8:08 ` Fwd: " Luca de Alfaro 2007-10-05 11:08 ` Vincent Aravantinos 2007-10-05 10:30 ` David Teller 1 sibling, 2 replies; 22+ messages in thread From: Luca de Alfaro @ 2007-10-05 8:08 UTC (permalink / raw) To: Inria Ocaml Mailing List [-- Attachment #1: Type: text/plain, Size: 838 bytes --] I don't understand this. I thought the whole idea of oo programming was that you could use a subclass in place of a superclass... I also thought that the strict typing of Ocaml was there to avoid runtime errors, but if so, why does it complain in this situation, when no runtime error can possibly happen? It seems to me that the idea of oo programming is broken for no good reason... Luca On 10/5/07, Florian Hars <hars@bik-gmbh.de> wrote: > > Luca de Alfaro schrieb: > > The absurdity continues: > > This is not absurd, this is the documented correct behaviuor. > If *you* decide that f must only accept arguments of *exactly* > type r, the typechecker enforces your decision, as it does if > you decide that f may also accept subtypes of r (as long as your > decisions are consistent within he type system). > > Yours, Florian. > [-- Attachment #2: Type: text/html, Size: 1155 bytes --] ^ permalink raw reply [flat|nested] 22+ messages in thread
* Fwd: [Caml-list] Why can't I call a function over a subclass? 2007-10-05 8:08 ` Luca de Alfaro @ 2007-10-05 8:08 ` Luca de Alfaro 2007-10-05 11:08 ` Vincent Aravantinos 1 sibling, 0 replies; 22+ messages in thread From: Luca de Alfaro @ 2007-10-05 8:08 UTC (permalink / raw) To: caml-list [-- Attachment #1: Type: text/plain, Size: 1190 bytes --] I meant to say: it seems to be that Ocaml breaks the principles of oo programming for no good reason, in this case. luca ---------- Forwarded message ---------- From: Luca de Alfaro <luca@dealfaro.org> Date: Oct 5, 2007 1:08 AM Subject: Re: [Caml-list] Why can't I call a function over a subclass? To: Inria Ocaml Mailing List <caml-list@inria.fr> I don't understand this. I thought the whole idea of oo programming was that you could use a subclass in place of a superclass... I also thought that the strict typing of Ocaml was there to avoid runtime errors, but if so, why does it complain in this situation, when no runtime error can possibly happen? It seems to me that the idea of oo programming is broken for no good reason... Luca On 10/5/07, Florian Hars < hars@bik-gmbh.de> wrote: > > Luca de Alfaro schrieb: > > The absurdity continues: > > This is not absurd, this is the documented correct behaviuor. > If *you* decide that f must only accept arguments of *exactly* > type r, the typechecker enforces your decision, as it does if > you decide that f may also accept subtypes of r (as long as your > decisions are consistent within he type system). > > Yours, Florian. > [-- Attachment #2: Type: text/html, Size: 1856 bytes --] ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [Caml-list] Why can't I call a function over a subclass? 2007-10-05 8:08 ` Luca de Alfaro 2007-10-05 8:08 ` Fwd: " Luca de Alfaro @ 2007-10-05 11:08 ` Vincent Aravantinos 2007-10-05 11:47 ` Christophe Raffalli 1 sibling, 1 reply; 22+ messages in thread From: Vincent Aravantinos @ 2007-10-05 11:08 UTC (permalink / raw) To: Luca de Alfaro; +Cc: Inria Ocaml Mailing List Le 5 oct. 07 à 10:08, Luca de Alfaro a écrit : > I don't understand this. I thought the whole idea of oo > programming was that you could use a subclass in place of a > superclass... > > I also thought that the strict typing of Ocaml was there to avoid > runtime errors, but if so, why does it complain in this situation, > when no runtime error can possibly happen? > > It seems to me that the idea of oo programming is broken for no > good reason... - This is absurd in an oo context. Here, the main paradigm is not oo. It is simply strongly typed. So if you write that a function expects a particular type, this function should be applied with this particular type and nothing else. *You* wrote this so you claimed for it. You want more generality ? Then let the type checker do its job as Pietro said. *The default behaviour is not to write any type info.* If you stay with this you get the standard oo behaviour. Annotations are there to give more info to the compiler in case it does infer what you have in mind. - Strict typing of Ocaml is not to avoid runtime errors. It simply stays that if two types expected to be the same differ, we suppose *the program does not match what the programmer has in mind*. As a little side-effect, this can avoid runtime errors :) If you keep this idea of "what the programmer has in mind", in this particular case you said to the compiler with your type annotation that what you had in mind was that the function only takes a r. What you said to the compiler was not what you had in mind. And I insist again: the default behaviour (don't anotate) gives you what you would expect. Cheers, Vincent ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [Caml-list] Why can't I call a function over a subclass? 2007-10-05 11:08 ` Vincent Aravantinos @ 2007-10-05 11:47 ` Christophe Raffalli 0 siblings, 0 replies; 22+ messages in thread From: Christophe Raffalli @ 2007-10-05 11:47 UTC (permalink / raw) To: Vincent Aravantinos; +Cc: Luca de Alfaro, Inria Ocaml Mailing List [-- Attachment #1: Type: text/plain, Size: 803 bytes --] The problem is that OCaml type-checker is unification based instead of subtyping-constraint based and therefore require (useless) type cast in some place (with variant and objects) ... This is why you get unnatural behaviour of the type-checker with oo and variant in OCaml ... -- Christophe Raffalli Universite de Savoie Batiment Le Chablais, bureau 21 73376 Le Bourget-du-Lac Cedex tel: (33) 4 79 75 81 03 fax: (33) 4 79 75 87 42 mail: Christophe.Raffalli@univ-savoie.fr www: http://www.lama.univ-savoie.fr/~RAFFALLI --------------------------------------------- IMPORTANT: this mail is signed using PGP/MIME At least Enigmail/Mozilla, mutt or evolution can check this signature. The public key is stored on www.keyserver.net --------------------------------------------- [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 252 bytes --] ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [Caml-list] Why can't I call a function over a subclass? 2007-10-05 8:01 ` [Caml-list] " Florian Hars 2007-10-05 8:08 ` Luca de Alfaro @ 2007-10-05 10:30 ` David Teller 2007-10-05 10:53 ` Zheng Li 1 sibling, 1 reply; 22+ messages in thread From: David Teller @ 2007-10-05 10:30 UTC (permalink / raw) To: Florian Hars; +Cc: Luca de Alfaro, Inria Ocaml Mailing List I agree with Luca that it's disconcerting. When r is a class, I would expect let f (x:r) (y:r) =... to have a type such as x :> r -> y :> r -> ... Cheers, David On Fri, 2007-10-05 at 10:01 +0200, Florian Hars wrote: > Luca de Alfaro schrieb: > > The absurdity continues: > > This is not absurd, this is the documented correct behaviuor. > If *you* decide that f must only accept arguments of *exactly* > type r, the typechecker enforces your decision, as it does if > you decide that f may also accept subtypes of r (as long as your > decisions are consistent within he type system). > > Yours, Florian. > > _______________________________________________ > Caml-list mailing list. Subscription management: > http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list > Archives: http://caml.inria.fr > Beginner's list: http://groups.yahoo.com/group/ocaml_beginners > Bug reports: http://caml.inria.fr/bin/caml-bugs ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: Why can't I call a function over a subclass? 2007-10-05 10:30 ` David Teller @ 2007-10-05 10:53 ` Zheng Li 2007-10-05 14:02 ` [Caml-list] " David Teller 0 siblings, 1 reply; 22+ messages in thread From: Zheng Li @ 2007-10-05 10:53 UTC (permalink / raw) To: caml-list David Teller <David.Teller@ens-lyon.org> writes: > I agree with Luca that it's disconcerting. > When r is a class, I would expect > let f (x:r) (y:r) =... This expression says f accept arguments of type [r], what you mean to say is: f accept any arguments belong to [r]'s subtypes family. Then say it with # let f (x:#r) (y:#r) = x#get_x = y#get_x val f : #r -> #r -> bool = <fun> -- Zheng Li http://www.pps.jussieu.fr/~li ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [Caml-list] Re: Why can't I call a function over a subclass? 2007-10-05 10:53 ` Zheng Li @ 2007-10-05 14:02 ` David Teller 2007-10-05 14:59 ` Luca de Alfaro 0 siblings, 1 reply; 22+ messages in thread From: David Teller @ 2007-10-05 14:02 UTC (permalink / raw) To: Zheng Li; +Cc: caml-list Sure. I'm just saying that this default behaviour is disconcerting. In addition to which, while it does appear in the documentation, it's rather well hidden inside section 3.11 "Polymorphic methods" -- even though this is not a method. Cheers, David On Fri, 2007-10-05 at 12:53 +0200, Zheng Li wrote: > David Teller <David.Teller@ens-lyon.org> writes: > > I agree with Luca that it's disconcerting. > > When r is a class, I would expect > > > let f (x:r) (y:r) =... > This expression says f accept arguments of type [r], what you mean to say is: f > accept any arguments belong to [r]'s subtypes family. Then say it with > > # let f (x:#r) (y:#r) = x#get_x = y#get_x > val f : #r -> #r -> bool = <fun> > ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [Caml-list] Re: Why can't I call a function over a subclass? 2007-10-05 14:02 ` [Caml-list] " David Teller @ 2007-10-05 14:59 ` Luca de Alfaro 2007-10-05 15:12 ` Luca de Alfaro 0 siblings, 1 reply; 22+ messages in thread From: Luca de Alfaro @ 2007-10-05 14:59 UTC (permalink / raw) To: David Teller; +Cc: Zheng Li, caml-list [-- Attachment #1: Type: text/plain, Size: 2309 bytes --] The problem is also that the example I posted is a minimal instance of the problem, but my real problem is much harder to solve (or so I believe, let me know if you have suggestions!). My real problem is that I have a class r, that internally, in many places, uses objects of a class p. Then I subclass r into r', and in r', I need to replace objects of type p with objects of type p', a subclass of p. Inside r I have a method do_work that does something like, in its body: ... let x = new Pclass.p in ... Now, if I cut-and-paste the code of do_work from r to r', and change the above line in: let x = new Pclass.p' in then everything works. If instead I replace the code in r with: method make_p = new Pclass.p ... let x = make_p in ... so that in r', I just need to override make_p with: method make_p = new Pclass.p' then the code does not type check --- and I don't know why, and in any case it is not logical to me. What would be the solution in this case? The classes p, p' are used in many places in r, r', but the error only occurs when I do the above change. Any help would be appreciated --- at least, so that I understand better how not to break my code... Luca On 10/5/07, David Teller <David.Teller@ens-lyon.org> wrote: > > Sure. I'm just saying that this default behaviour is disconcerting. > > In addition to which, while it does appear in the documentation, it's > rather well hidden inside section 3.11 "Polymorphic methods" -- even > though this is not a method. > > Cheers, > David > > On Fri, 2007-10-05 at 12:53 +0200, Zheng Li wrote: > > David Teller <David.Teller@ens-lyon.org> writes: > > > I agree with Luca that it's disconcerting. > > > When r is a class, I would expect > > > > > let f (x:r) (y:r) =... > > This expression says f accept arguments of type [r], what you mean to > say is: f > > accept any arguments belong to [r]'s subtypes family. Then say it with > > > > # let f (x:#r) (y:#r) = x#get_x = y#get_x > > val f : #r -> #r -> bool = <fun> > > > > _______________________________________________ > Caml-list mailing list. Subscription management: > http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list > Archives: http://caml.inria.fr > Beginner's list: http://groups.yahoo.com/group/ocaml_beginners > Bug reports: http://caml.inria.fr/bin/caml-bugs > [-- Attachment #2: Type: text/html, Size: 3241 bytes --] ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [Caml-list] Re: Why can't I call a function over a subclass? 2007-10-05 14:59 ` Luca de Alfaro @ 2007-10-05 15:12 ` Luca de Alfaro [not found] ` <20071005152130.M41697@cs.unm.edu> 0 siblings, 1 reply; 22+ messages in thread From: Luca de Alfaro @ 2007-10-05 15:12 UTC (permalink / raw) To: David Teller; +Cc: Zheng Li, caml-list [-- Attachment #1: Type: text/plain, Size: 2696 bytes --] I am sorry - I am wrong. I get an error in both cases listed below. So the behavior is disconcerting to me, and no clear elegant solution exists, but at least the behavior is consistent. Luca On 10/5/07, Luca de Alfaro <luca@dealfaro.org> wrote: > > The problem is also that the example I posted is a minimal instance of the > problem, but my real problem is much harder to solve (or so I believe, let > me know if you have suggestions!). > My real problem is that I have a class r, that internally, in many places, > uses objects of a class p. > Then I subclass r into r', and in r', I need to replace objects of type p > with objects of type p', a subclass of p. > Inside r I have a method do_work that does something like, in its body: > > ... > let x = new Pclass.p in > ... > > Now, if I cut-and-paste the code of do_work from r to r', and change the > above line in: > let x = new Pclass.p' in > then everything works. > If instead I replace the code in r with: > > method make_p = new Pclass.p > > ... > let x = make_p in > ... > > so that in r', I just need to override make_p with: > > method make_p = new Pclass.p' > > then the code does not type check --- and I don't know why, and in any > case it is not logical to me. > What would be the solution in this case? The classes p, p' are used in > many places in r, r', but the error only occurs when I do the above change. > Any help would be appreciated --- at least, so that I understand better > how not to break my code... > > Luca > > > On 10/5/07, David Teller <David.Teller@ens-lyon.org> wrote: > > > > Sure. I'm just saying that this default behaviour is disconcerting. > > > > In addition to which, while it does appear in the documentation, it's > > rather well hidden inside section 3.11 "Polymorphic methods" -- even > > though this is not a method. > > > > Cheers, > > David > > > > On Fri, 2007-10-05 at 12:53 +0200, Zheng Li wrote: > > > David Teller <David.Teller@ens-lyon.org> writes: > > > > I agree with Luca that it's disconcerting. > > > > When r is a class, I would expect > > > > > > > let f (x:r) (y:r) =... > > > This expression says f accept arguments of type [r], what you mean to > > say is: f > > > accept any arguments belong to [r]'s subtypes family. Then say it with > > > > > > # let f (x:#r) (y:#r) = x#get_x = y#get_x > > > val f : #r -> #r -> bool = <fun> > > > > > > > _______________________________________________ > > Caml-list mailing list. Subscription management: > > http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list > > Archives: http://caml.inria.fr > > Beginner's list: http://groups.yahoo.com/group/ocaml_beginners > > Bug reports: http://caml.inria.fr/bin/caml-bugs > > > > [-- Attachment #2: Type: text/html, Size: 4296 bytes --] ^ permalink raw reply [flat|nested] 22+ messages in thread
[parent not found: <20071005152130.M41697@cs.unm.edu>]
* Re: [Caml-list] Re: Why can't I call a function over a subclass? [not found] ` <20071005152130.M41697@cs.unm.edu> @ 2007-10-05 15:49 ` Luca de Alfaro 2007-10-05 16:34 ` Edgar Friendly ` (2 more replies) 0 siblings, 3 replies; 22+ messages in thread From: Luca de Alfaro @ 2007-10-05 15:49 UTC (permalink / raw) To: William D. Neumann, Inria Ocaml Mailing List [-- Attachment #1: Type: text/plain, Size: 1476 bytes --] Yes, here is some code. Any help would be very much appreciated. The following fails to type check: class p (x: int) = object method plus1 : int = x + 1 end class p2 (x: int) = object inherit p x method plus2 : int = x + 2 end class r = object (self) val mutable l = [] method make_el x = new p x method add (x: int) : unit = l <- (self#make_el x) :: l method length : int = List.length l method total : int = List.fold_left (fun t el -> t + el#plus1) 0 l end class r2 = object inherit r method make_el x = new p2 x method total2 : int = List.fold_left (fun t el -> t + el#plus2) 0 l end What I am trying to do is to replace, in l, elements of type p with elements of type p2, so that my class r2 can offer more methods (or use them internally). However, the compiler complains that p2 and p are not compatible, because p does not have method plus2 (in spite of the fact that no runtime error can occur). I am not a deep expert of Ocaml type system for classes, as you might have guessed by now, so if someone were able to suggest a set of type casts/notations/... that would make the above go through, I would be very grateful. In my real (large) code, I use the elements of the list l in many places inside the code of r (and by inheritance, r2). Do you have any code that we can look at to see what the problem is? Can > you perhaps construct a small yet complete example that demonstartes the > issue? > > -- > > William D. Neumann > > [-- Attachment #2: Type: text/html, Size: 1896 bytes --] ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [Caml-list] Re: Why can't I call a function over a subclass? 2007-10-05 15:49 ` Luca de Alfaro @ 2007-10-05 16:34 ` Edgar Friendly 2007-10-05 17:39 ` Luca de Alfaro 2007-10-05 19:48 ` Why can't I call a function over a subclass? Zheng Li 2007-10-09 4:18 ` Jacques Garrigue 2 siblings, 1 reply; 22+ messages in thread From: Edgar Friendly @ 2007-10-05 16:34 UTC (permalink / raw) To: Luca de Alfaro; +Cc: William D. Neumann, Inria Ocaml Mailing List Luca de Alfaro wrote: > Yes, here is some code. Any help would be very much appreciated. > The following fails to type check: > > class p (x: int) = object > method plus1 : int = x + 1 > end > > class p2 (x: int) = object > inherit p x > method plus2 : int = x + 2 > end > > class r = object (self) > val mutable l = [] > method make_el x = new p x > method add (x: int) : unit = l <- (self#make_el x) :: l > method length : int = List.length l > method total : int = List.fold_left (fun t el -> t + el#plus1) 0 l > end > > class r2 = object > inherit r > method make_el x = new p2 x > method total2 : int = List.fold_left (fun t el -> t + el#plus2) 0 l > end > if I manually perform the inherit operation by pasting the code from r1 into r2, I get: class r2 = object (self) val mutable l = [] method make_el x = new p2 x method add (x: int) : unit = l <- (self#make_el x) :: l method length : int = List.length l method total2 : int = List.fold_left (fun t el -> t + el#plus2) 0 l end which compiles just fine, and probably works as intended. If I include the original method make_el above the new one like this: method make_el x = new p x method make_el x = new p2 x Ignoring the warning about overriding methods within the same class, we come to the root of the type problem: make_el must have a type. After inference completes on the first line, make_el's type is determined to be p. The second make_el's type must match, but it doesn't. I don't see a solution for your problem that doesn't involve this kind of manual expansion and removal of duplicate methods, but I'm fairly sure this is the real problem for you. E. ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [Caml-list] Re: Why can't I call a function over a subclass? 2007-10-05 16:34 ` Edgar Friendly @ 2007-10-05 17:39 ` Luca de Alfaro 2007-10-05 17:49 ` Martin Jambon 0 siblings, 1 reply; 22+ messages in thread From: Luca de Alfaro @ 2007-10-05 17:39 UTC (permalink / raw) To: Edgar Friendly; +Cc: William D. Neumann, Inria Ocaml Mailing List [-- Attachment #1: Type: text/plain, Size: 2485 bytes --] I thank you all for the help... in the end, I solved the practical problem by collapsing p and p2 into the same class -- not so nice, but it works, and it is simpler than other solutions. But the larger issue is: when a type is used for an input parameters, as the type p in: f : int -> p -> bool why does the compiler have to complain that p has too many methods? Would it not be possible to make the type checker smarter, and ensure that when p is an input type, it is ok to have more methods? And for output types as well, it would seem? In other words, what is that fundamentally breaks if one were to change the ocaml type checker in this way? Luca On 10/5/07, Edgar Friendly <thelema314@gmail.com> wrote: > > Luca de Alfaro wrote: > > Yes, here is some code. Any help would be very much appreciated. > > The following fails to type check: > > > > class p (x: int) = object > > method plus1 : int = x + 1 > > end > > > > class p2 (x: int) = object > > inherit p x > > method plus2 : int = x + 2 > > end > > > > class r = object (self) > > val mutable l = [] > > method make_el x = new p x > > method add (x: int) : unit = l <- (self#make_el x) :: l > > method length : int = List.length l > > method total : int = List.fold_left (fun t el -> t + el#plus1) 0 l > > end > > > > class r2 = object > > inherit r > > method make_el x = new p2 x > > method total2 : int = List.fold_left (fun t el -> t + el#plus2) 0 l > > end > > > if I manually perform the inherit operation by pasting the code from r1 > into r2, I get: > > class r2 = object (self) > val mutable l = [] > method make_el x = new p2 x > method add (x: int) : unit = l <- (self#make_el x) :: l > method length : int = List.length l > method total2 : int = List.fold_left (fun t el -> t + el#plus2) 0 l > end > > which compiles just fine, and probably works as intended. If I include > the original method make_el above the new one like this: > method make_el x = new p x > method make_el x = new p2 x > Ignoring the warning about overriding methods within the same class, we > come to the root of the type problem: make_el must have a type. After > inference completes on the first line, make_el's type is determined to > be p. The second make_el's type must match, but it doesn't. I don't > see a solution for your problem that doesn't involve this kind of manual > expansion and removal of duplicate methods, but I'm fairly sure this is > the real problem for you. > > E. > [-- Attachment #2: Type: text/html, Size: 3209 bytes --] ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [Caml-list] Re: Why can't I call a function over a subclass? 2007-10-05 17:39 ` Luca de Alfaro @ 2007-10-05 17:49 ` Martin Jambon [not found] ` <28fa90930710052153k2128bb63m5132455868eb2008@mail.gmail.com> 0 siblings, 1 reply; 22+ messages in thread From: Martin Jambon @ 2007-10-05 17:49 UTC (permalink / raw) To: Luca de Alfaro Cc: Edgar Friendly, Inria Ocaml Mailing List, William D. Neumann On Fri, 5 Oct 2007, Luca de Alfaro wrote: > But the larger issue is: when a type is used for an input parameters, as the > type p in: > f : int -> p -> bool > why does the compiler have to complain that p has too many methods? That's your point of view. The compiler complains about different types, but it doesn't know which one is intended: does one object have too many methods or does the other object miss some methods? With some experience, you will learn that artificially annotating types of objects or polymorphic variants leads to much clearer and earlier error messages. So I would say that using ":>" is a rather mild annoyance, except that you have to learn what it means. Martin > Would it not be possible to make the type checker smarter, and ensure that > when p is an input type, it is ok to have more methods? > And for output types as well, it would seem? > In other words, what is that fundamentally breaks if one were to change the > ocaml type checker in this way? > > Luca > > On 10/5/07, Edgar Friendly <thelema314@gmail.com> wrote: >> >> Luca de Alfaro wrote: >>> Yes, here is some code. Any help would be very much appreciated. >>> The following fails to type check: >>> >>> class p (x: int) = object >>> method plus1 : int = x + 1 >>> end >>> >>> class p2 (x: int) = object >>> inherit p x >>> method plus2 : int = x + 2 >>> end >>> >>> class r = object (self) >>> val mutable l = [] >>> method make_el x = new p x >>> method add (x: int) : unit = l <- (self#make_el x) :: l >>> method length : int = List.length l >>> method total : int = List.fold_left (fun t el -> t + el#plus1) 0 l >>> end >>> >>> class r2 = object >>> inherit r >>> method make_el x = new p2 x >>> method total2 : int = List.fold_left (fun t el -> t + el#plus2) 0 l >>> end >>> >> if I manually perform the inherit operation by pasting the code from r1 >> into r2, I get: >> >> class r2 = object (self) >> val mutable l = [] >> method make_el x = new p2 x >> method add (x: int) : unit = l <- (self#make_el x) :: l >> method length : int = List.length l >> method total2 : int = List.fold_left (fun t el -> t + el#plus2) 0 l >> end >> >> which compiles just fine, and probably works as intended. If I include >> the original method make_el above the new one like this: >> method make_el x = new p x >> method make_el x = new p2 x >> Ignoring the warning about overriding methods within the same class, we >> come to the root of the type problem: make_el must have a type. After >> inference completes on the first line, make_el's type is determined to >> be p. The second make_el's type must match, but it doesn't. I don't >> see a solution for your problem that doesn't involve this kind of manual >> expansion and removal of duplicate methods, but I'm fairly sure this is >> the real problem for you. >> >> E. >> > -- http://martin.jambon.free.fr ^ permalink raw reply [flat|nested] 22+ messages in thread
[parent not found: <28fa90930710052153k2128bb63m5132455868eb2008@mail.gmail.com>]
* Re: [Caml-list] Re: Why can't I call a function over a subclass? [not found] ` <28fa90930710052153k2128bb63m5132455868eb2008@mail.gmail.com> @ 2007-10-07 22:19 ` Martin Jambon 2007-10-07 22:57 ` Classes and polymorphism (Re: [Caml-list] Re: Why can't I call a function over a subclass?) Martin Jambon 1 sibling, 0 replies; 22+ messages in thread From: Martin Jambon @ 2007-10-07 22:19 UTC (permalink / raw) To: Luca de Alfaro; +Cc: caml-list Luca, I think what you meant is: ---------- class r (x_init: int) = object method get_x : int = x_init end let f (r1: r) (r2: r) : bool = (r1#get_x = r2#get_x) class r' (x_init: int) = object inherit r x_init method get_xx : int = 2 * x_init end let q (r1: r') (r2: r') = f (r1 :> r) (r2 :> r) -------------- You could also write: let f r1 r2 : bool = ((r1 :> r)#get_x = (r2 :> r)#get_x) let q (r1: r') (r2: r') = f r1 r2 I think the second form is nicer, since f is now polymorphic, and accepts any object type which is compatible with r, such as r'. Martin On Fri, 5 Oct 2007, Luca de Alfaro wrote: > I am not so used to ":>"... looking at the example I posted, would you be > able to tell me how to make it type-check by adding ":>"? This would be > very much appreciated... > > Luca > > On 10/5/07, Martin Jambon <martin.jambon@ens-lyon.org> wrote: >> >> On Fri, 5 Oct 2007, Luca de Alfaro wrote: >> >>> But the larger issue is: when a type is used for an input parameters, as >> the >>> type p in: >>> f : int -> p -> bool >>> why does the compiler have to complain that p has too many methods? >> >> That's your point of view. The compiler complains about different types, >> but it doesn't know which one is intended: does one object have >> too many methods or does the other object miss some methods? >> >> With some experience, you will learn that artificially annotating types >> of objects or polymorphic variants leads to much clearer and earlier error >> messages. >> >> So I would say that using ":>" is a rather mild annoyance, except that you >> have to learn what it means. >> >> >> Martin >> >> >>> Would it not be possible to make the type checker smarter, and ensure >> that >>> when p is an input type, it is ok to have more methods? >>> And for output types as well, it would seem? >>> In other words, what is that fundamentally breaks if one were to change >> the >>> ocaml type checker in this way? >>> >>> Luca >>> >>> On 10/5/07, Edgar Friendly <thelema314@gmail.com> wrote: >>>> >>>> Luca de Alfaro wrote: >>>>> Yes, here is some code. Any help would be very much appreciated. >>>>> The following fails to type check: >>>>> >>>>> class p (x: int) = object >>>>> method plus1 : int = x + 1 >>>>> end >>>>> >>>>> class p2 (x: int) = object >>>>> inherit p x >>>>> method plus2 : int = x + 2 >>>>> end >>>>> >>>>> class r = object (self) >>>>> val mutable l = [] >>>>> method make_el x = new p x >>>>> method add (x: int) : unit = l <- (self#make_el x) :: l >>>>> method length : int = List.length l >>>>> method total : int = List.fold_left (fun t el -> t + el#plus1) 0 l >>>>> end >>>>> >>>>> class r2 = object >>>>> inherit r >>>>> method make_el x = new p2 x >>>>> method total2 : int = List.fold_left (fun t el -> t + el#plus2) 0 l >>>>> end >>>>> >>>> if I manually perform the inherit operation by pasting the code from r1 >>>> into r2, I get: >>>> >>>> class r2 = object (self) >>>> val mutable l = [] >>>> method make_el x = new p2 x >>>> method add (x: int) : unit = l <- (self#make_el x) :: l >>>> method length : int = List.length l >>>> method total2 : int = List.fold_left (fun t el -> t + el#plus2) 0 l >>>> end >>>> >>>> which compiles just fine, and probably works as intended. If I include >>>> the original method make_el above the new one like this: >>>> method make_el x = new p x >>>> method make_el x = new p2 x >>>> Ignoring the warning about overriding methods within the same class, we >>>> come to the root of the type problem: make_el must have a type. After >>>> inference completes on the first line, make_el's type is determined to >>>> be p. The second make_el's type must match, but it doesn't. I don't >>>> see a solution for your problem that doesn't involve this kind of >> manual >>>> expansion and removal of duplicate methods, but I'm fairly sure this is >>>> the real problem for you. >>>> >>>> E. >>>> >>> >> >> -- >> http://martin.jambon.free.fr >> > -- http://martin.jambon.free.fr ^ permalink raw reply [flat|nested] 22+ messages in thread
* Classes and polymorphism (Re: [Caml-list] Re: Why can't I call a function over a subclass?) [not found] ` <28fa90930710052153k2128bb63m5132455868eb2008@mail.gmail.com> 2007-10-07 22:19 ` Martin Jambon @ 2007-10-07 22:57 ` Martin Jambon 1 sibling, 0 replies; 22+ messages in thread From: Martin Jambon @ 2007-10-07 22:57 UTC (permalink / raw) To: Luca de Alfaro; +Cc: caml-list On Fri, 5 Oct 2007, Luca de Alfaro wrote: > I am not so used to ":>"... looking at the example I posted, would you be > able to tell me how to make it type-check by adding ":>"? This would be > very much appreciated... Ah, sorry, I missed your second problem, which was: (next time please change the subject line and cc the list) class p (x: int) = object method plus1 : int = x + 1 end class p2 (x: int) = object inherit p x method plus2 : int = x + 2 end class r = object (self) val mutable l = [] method make_el x = new p x method add (x: int) : unit = l <- (self#make_el x) :: l method length : int = List.length l method total : int = List.fold_left (fun t el -> t + el#plus1) 0 l end class r2 = object inherit r method make_el x = new p2 x method total2 : int = List.fold_left (fun t el -> t + el#plus2) 0 l end What you're trying to do usually ends up being a nightmare: l would have to be polymorphic. Keeping classes polymorphic is not something practical. If you inherit an object value such as l, basically it will have one fixed type, and that's all. I find the following guidelines convenient: Define class types independently from class implementations when you know that you will have several classes of the same type. Only use monomorphic methods and values. You may inherit a class from another, and you don't need polymorphic classes for this. You never have to use inheritance. You don't have to use classes, immediate objects are often sufficient (object ... end). You can inherit and override methods, which is convenient when only a small subset of methods differ between two classes. That's when your classes are like an evolutionary tree of species. Don't bother when you have only 2 or 3 classes. Martin -- http://martin.jambon.free.fr ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: Why can't I call a function over a subclass? 2007-10-05 15:49 ` Luca de Alfaro 2007-10-05 16:34 ` Edgar Friendly @ 2007-10-05 19:48 ` Zheng Li 2007-10-06 1:49 ` [Caml-list] " Jake Donham 2007-10-09 4:18 ` Jacques Garrigue 2 siblings, 1 reply; 22+ messages in thread From: Zheng Li @ 2007-10-05 19:48 UTC (permalink / raw) To: caml-list "Luca de Alfaro" <luca@dealfaro.org> writes: > class p (x: int) = object > method plus1 : int = x + 1 > end > > class p2 (x: int) = object > inherit p x > method plus2 : int = x + 2 > end > > class r = object (self) > val mutable l = [] > method make_el x = new p x > method add (x: int) : unit = l <- (self#make_el x) :: l > method length : int = List.length l > method total : int = List.fold_left (fun t el -> t + el#plus1) 0 l > end > > class r2 = object > inherit r > method make_el x = new p2 x > method total2 : int = List.fold_left (fun t el -> t + el#plus2) 0 l > end I tried it in another way, maybe not the way you expect, but just for your reference. <code> class virtual r = object val mutable l = [] val virtual make_el: int -> #p method add x = l <- make_el x ::l method length = List.length l method total = List.fold_left (fun t el -> t + el#plus1) 0 l end class r1 = object inherit r val make_el = new p end class r2 = object inherit r val make_el = new p2 method total2 = List.fold_left (fun t el -> t + el#plus2) 0 l end </code> Note that before you finally provide the virtual classes with a concrete make_el, you're free to inherit and extend them *arbitrarily*. E.g. <code> class virtual r3 = object inherit r method total3 = List.fold_left (fun t el -> t + el#plus3) 0 l end class virtual r4 = object inherit r3 (* r3 is extensible *) method total4 = List.fold_left (fun t el -> t + el#plus4) 0 l end </code> HTH. -- Zheng Li http://www.pps.jussieu.fr/~li ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [Caml-list] Re: Why can't I call a function over a subclass? 2007-10-05 19:48 ` Why can't I call a function over a subclass? Zheng Li @ 2007-10-06 1:49 ` Jake Donham 0 siblings, 0 replies; 22+ messages in thread From: Jake Donham @ 2007-10-06 1:49 UTC (permalink / raw) To: caml-list Hi Luca, Others have given good replies already but you may find this article helpful: http://skydeck.com/blog/programming/ocaml-for-the-recovering-java-programmer-part-1-objects-and-subtyping/ What it comes down to is that in OCaml subsumption (i.e. the whole idea of object oriented programming) is accomplished using polymorphism, not implicit coercion. Jake ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [Caml-list] Re: Why can't I call a function over a subclass? 2007-10-05 15:49 ` Luca de Alfaro 2007-10-05 16:34 ` Edgar Friendly 2007-10-05 19:48 ` Why can't I call a function over a subclass? Zheng Li @ 2007-10-09 4:18 ` Jacques Garrigue 2 siblings, 0 replies; 22+ messages in thread From: Jacques Garrigue @ 2007-10-09 4:18 UTC (permalink / raw) To: luca; +Cc: caml-list From: "Luca de Alfaro" <luca@dealfaro.org> > Yes, here is some code. Any help would be very much appreciated. > The following fails to type check: > > class p (x: int) = object > method plus1 : int = x + 1 > end > > class p2 (x: int) = object > inherit p x > method plus2 : int = x + 2 > end > > class r = object (self) > val mutable l = [] > method make_el x = new p x > method add (x: int) : unit = l <- (self#make_el x) :: l > method length : int = List.length l > method total : int = List.fold_left (fun t el -> t + el#plus1) 0 l > end > > class r2 = object > inherit r > method make_el x = new p2 x > method total2 : int = List.fold_left (fun t el -> t + el#plus2) 0 l > end Zheng Li already provided an answer to your problem. However Zheng's answer, while doing exactly what you were trying to do, use virtual value fields, which are a new feature in 3.10. A more standard way to do this would be to use a private virtual method, as make_el is the same across all instances of a specific class. class virtual r = object (self) val mutable l = [] method private virtual make_el : int -> #p method add x = l <- self#make_el x ::l method length = List.length l method total = List.fold_left (fun t el -> t + el#plus1) 0 l end class r1 = object inherit r method make_el = new p end class r2 = object inherit r method make_el = new p2 method total2 = List.fold_left (fun t el -> t + el#plus2) 0 l end Practically, these two solutions are equivalent. Jacques Garrigue ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [Caml-list] Why can't I call a function over a subclass? 2007-10-05 7:48 Why can't I call a function over a subclass? Luca de Alfaro 2007-10-05 8:01 ` [Caml-list] " Florian Hars @ 2007-10-05 8:07 ` Pietro Abate 2007-10-05 10:55 ` Andrej Bauer 2 siblings, 0 replies; 22+ messages in thread From: Pietro Abate @ 2007-10-05 8:07 UTC (permalink / raw) To: caml-list, Inria Ocaml Mailing List On Fri, Oct 05, 2007 at 12:48:54AM -0700, Luca de Alfaro wrote: > r' is a subclass of r. The compiler complains: > > File "class1.ml", line 12, characters 28-30: > This expression has type r' but is here used with type r > The second object type has no method get_xx I see two solutions: Either you explicitly coerce the type of r' to r so to match its (explicit) signature: let q (r1: r') (r2: r') = f (r1 :> r) (r2 :> r) or you remove the type constraints from f and you let ocaml do the rest. let f r1 r2 = (r1#get_x = r2#get_x) let q (r1: r') (r2: r') = f r1 r2 why do you want to specify the type of f ? The minimal information needed is that it's an object with a method get_x and this can be inferred by the type checker. Then all objects with a method get_x will work even if not explicitly a subclass (iirc). Usually I don't specify type constraints if not absolutely necessary and I use a signature to wrap the module in the end. :) pp -- ++ ++ "All great truths begin as blasphemies." -George Bernard Shaw ++ Please avoid sending me Word or PowerPoint attachments. See http://www.gnu.org/philosophy/no-word-attachments.html ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [Caml-list] Why can't I call a function over a subclass? 2007-10-05 7:48 Why can't I call a function over a subclass? Luca de Alfaro 2007-10-05 8:01 ` [Caml-list] " Florian Hars 2007-10-05 8:07 ` [Caml-list] " Pietro Abate @ 2007-10-05 10:55 ` Andrej Bauer 2 siblings, 0 replies; 22+ messages in thread From: Andrej Bauer @ 2007-10-05 10:55 UTC (permalink / raw) To: Luca de Alfaro; +Cc: Inria Ocaml Mailing List Ocaml will compute types for you. If you want, you can also specify the types and it will repsect that. You specified the types of r1 and r2: > let f (r1: r) (r2: r) : bool = (r1#get_x = r2#get_x) Even though r' is a subclass of r, a value of type r' is _not_ of type r (if your brain thinks in Java you might find this surprising--in which case we can talk about it): # let a = new r' 5 ;; val a : r' = <obj> # (a : r);; Characters 1-2: (a : r);; ^ This expression has type r' but is here used with type r Only the first object type has a method get_xx If you let Ocaml compute types on its own, your example will work as expected: let f r1 r2 = (r1#get_x = r2#get_x) Now the function of f is computed to be val f : < get_x : 'a; .. > -> < get_x : 'a; .. > -> bool So just let the machine worry about they types. Andrej ^ permalink raw reply [flat|nested] 22+ messages in thread
end of thread, other threads:[~2007-10-09 4:19 UTC | newest] Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2007-10-05 7:48 Why can't I call a function over a subclass? Luca de Alfaro 2007-10-05 8:01 ` [Caml-list] " Florian Hars 2007-10-05 8:08 ` Luca de Alfaro 2007-10-05 8:08 ` Fwd: " Luca de Alfaro 2007-10-05 11:08 ` Vincent Aravantinos 2007-10-05 11:47 ` Christophe Raffalli 2007-10-05 10:30 ` David Teller 2007-10-05 10:53 ` Zheng Li 2007-10-05 14:02 ` [Caml-list] " David Teller 2007-10-05 14:59 ` Luca de Alfaro 2007-10-05 15:12 ` Luca de Alfaro [not found] ` <20071005152130.M41697@cs.unm.edu> 2007-10-05 15:49 ` Luca de Alfaro 2007-10-05 16:34 ` Edgar Friendly 2007-10-05 17:39 ` Luca de Alfaro 2007-10-05 17:49 ` Martin Jambon [not found] ` <28fa90930710052153k2128bb63m5132455868eb2008@mail.gmail.com> 2007-10-07 22:19 ` Martin Jambon 2007-10-07 22:57 ` Classes and polymorphism (Re: [Caml-list] Re: Why can't I call a function over a subclass?) Martin Jambon 2007-10-05 19:48 ` Why can't I call a function over a subclass? Zheng Li 2007-10-06 1:49 ` [Caml-list] " Jake Donham 2007-10-09 4:18 ` Jacques Garrigue 2007-10-05 8:07 ` [Caml-list] " Pietro Abate 2007-10-05 10:55 ` Andrej Bauer
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox