* [Caml-list] Re: OCAML Downcasting? [not found] ` <ci9ggm$i6p$1@wolfberry.srv.cs.cmu.edu> @ 2004-09-21 8:03 ` Jacques GARRIGUE 2004-09-21 8:43 ` Damien Pous 2004-09-21 19:27 ` Michael Vanier 0 siblings, 2 replies; 29+ messages in thread From: Jacques GARRIGUE @ 2004-09-21 8:03 UTC (permalink / raw) To: caml-list Reposted from comp.lang.ml: Matthias Kretschmer <mccratch@gmx.net> writes: > Roy Patrick Tan schrieb: > > > I'm trying to learn about ocaml's object-oriented features. It seems > > like you can coerce an object of one type to a supertype, but not from > > a supertype to a subtype. But what if I need to recover the original > > type? > > I am a bit curious why it is that unsafe that it is completely > forbidden. Of course type-checks can't be done at elaboration time and > have to be postponed to the evaluation time, but most other OO-languages > just implement this and if it is impossible, they raise an exception or > abort the program. At least something like Oberon's WITH-statement would > sometimes be very handy. There are two important differences between ocaml and other OO-languages that have downcasting. - inheritance is not subtyping. The subtyping relation being structural, a full fledge typecast would not only require to keep type information at runtime, but to embark a large part of the compiler to check subtyping. This might also be incredibly slow. As a result, downcast is only reasonable when we have both inheritance and subtyping. You're suddenly losing a large part of the language. Worse, even if you have a module interface class b : object inherit a .... end in ocaml this does _not_ mean that b inherits from a, just that it has at least a's methods and fields. So the semantics of downcast would not allow abstraction. - classes may have type parameters. Assume a situation like class ['a] a = object ... end Then we cannot downcast any runtime object to "a", because we don't know what is its type parameter. Again, downcast would not mix well with other features of the language. So, while this is somehow unfortunate, there is no downcast in ocaml. There are various ways to simulate it, but at first this is a bit confusing for people used to languages with reflection. > On the other hand, one can overcome this by using sum-types: e.g. You > know about button widgets and label widgets. Of course there can be > other widgets, so we have 3 different types to distinguish: > - buttons > - labels > - others > => > type mywidget = Button of button_widget > | Label of label_widget > | Other of widget This is indeed the standard way to do it, as it mixes best with a functional programming language. > In some circumstances this is nice, because you can simply use pattern > matching to extract the type you want. On the other hand, when defining > this type you have to know excactly what types you want to handle. So it > might get very ugly and clumsy. Phrased this way, this sounds like you have no way to modify the above type when you need to add a new subtype. The straightforward thing to do is to use your editor and add a new case to the above list. Then the compiler will tell you all the places you need to modify to take this new case into consideration -- something most OO compilers wouldn't bother to tell you: they would force you to have a default case, which may be relevant or not, and you would only discover this at runtime. For the more special cases where you can't modify the original code, there are still various ways to simulate downcast, from keeping objects in hashtables to advanced uses of parametric polymorphism. Just for fun, here is an example of the second approach: class virtual ['a] widget = object method virtual raw : 'a end class ['a] button = object (self) inherit ['a] widget method raw = `Button self method press = prerr_endline "pressed" end class ['a] label = object (self) inherit ['a] widget method raw = `Label self val mutable text = "" method set_text s = text <- s end let l = [(new button :> _ widget); (new label :> _ widget)] let f = function `Button b -> b#press | `Label l -> l#set_text "Hello" let test () = List.iter (fun o -> f o#raw) l Such a programming pattern lets you use downcasting in a refined way, without any language support. It even avoids the first limitation I described above (label need not really inherit from widget). But the fact you must keep 'a polymorphic makes it advanced. 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] 29+ messages in thread
* [Caml-list] Re: OCAML Downcasting? 2004-09-21 8:03 ` [Caml-list] Re: OCAML Downcasting? Jacques GARRIGUE @ 2004-09-21 8:43 ` Damien Pous 2004-09-21 9:15 ` Jacques GARRIGUE 2004-09-21 19:27 ` Michael Vanier 1 sibling, 1 reply; 29+ messages in thread From: Damien Pous @ 2004-09-21 8:43 UTC (permalink / raw) To: caml-list Hello, Jacques GARRIGUE <garrigue@kurims.kyoto-u.ac.jp> wrote: > Just for fun, here is an example of the second approach: > > class virtual ['a] widget = object > method virtual raw : 'a > end > class ['a] button = object (self) > inherit ['a] widget > method raw = `Button self > method press = prerr_endline "pressed" > end How to write a signature for this code ? even "ocamlc -i" fails ! << #ocamlc -i error.ml class virtual ['a] widget : object method virtual raw : 'a end class ['a] button : object ('b) constraint 'a = [> `Button of 'b ] method press : unit method raw : 'a end >> then << #ocamlc -c error.ml The implementation error.ml does not match the interface error.cmi: Class declarations do not match: class ['a] button : object ('b) constraint 'a = [> `Button of 'b ] method press : unit method raw : 'a end does not match class ['a] button : object constraint 'a = [> `Button of 'a button ] method press : unit method raw : 'a end One type parameter has type [> `Button of < press : unit; raw : 'a; .. > as 'b ] as 'a but is expected to have type [> `Button of 'c button ] as 'c Type 'b is not compatible with type 'c button = < press : unit; raw : 'c > >> thanks, Damien ------------------- 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] 29+ messages in thread
* Re: [Caml-list] Re: OCAML Downcasting? 2004-09-21 8:43 ` Damien Pous @ 2004-09-21 9:15 ` Jacques GARRIGUE 2004-09-21 9:29 ` skaller 2004-09-21 9:34 ` Stefano Zacchiroli 0 siblings, 2 replies; 29+ messages in thread From: Jacques GARRIGUE @ 2004-09-21 9:15 UTC (permalink / raw) To: Damien.Pous; +Cc: caml-list From: Damien Pous <Damien.Pous@ens-lyon.fr> > Jacques GARRIGUE <garrigue@kurims.kyoto-u.ac.jp> wrote: > > Just for fun, here is an example of the second approach: > > > > class virtual ['a] widget = object > > method virtual raw : 'a > > end > > class ['a] button = object (self) > > inherit ['a] widget > > method raw = `Button self > > method press = prerr_endline "pressed" > > end > > How to write a signature for this code ? > > even "ocamlc -i" fails ! You're right. I shall never post before verifying my code seriously. The real code is: class virtual ['a] widget = object method virtual raw : 'a end class ['a] button = object (self) inherit ['a] widget method raw = `Button (self :> 'a button) method press = prerr_endline "pressed" end class ['a] label = object (self) inherit ['a] widget method raw = `Label (self :> 'a label) val mutable text = "" method set_text s = text <- s end let l = [(new button :> _ widget); (new label :> _ widget)] let f = function `Button b -> b#press | `Label l -> l#set_text "Hello" let test () = List.iter (fun o -> f o#raw) l Without the self-cast, you cannot extend any class. 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] 29+ messages in thread
* Re: [Caml-list] Re: OCAML Downcasting? 2004-09-21 9:15 ` Jacques GARRIGUE @ 2004-09-21 9:29 ` skaller 2004-09-21 9:49 ` Jacques GARRIGUE 2004-09-21 9:34 ` Stefano Zacchiroli 1 sibling, 1 reply; 29+ messages in thread From: skaller @ 2004-09-21 9:29 UTC (permalink / raw) To: Jacques GARRIGUE; +Cc: Damien.Pous, caml-list On Tue, 2004-09-21 at 19:15, Jacques GARRIGUE wrote: > class ['a] button = object (self) > inherit ['a] widget > method raw = `Button (self :> 'a button) > method press = prerr_endline "pressed" > end > Without the self-cast, you cannot extend any class. Is that an issue with classes or polymorphic variants? -- John Skaller, mailto:skaller@users.sf.net voice: 061-2-9660-0850, snail: PO BOX 401 Glebe NSW 2037 Australia Checkout the Felix programming language http://felix.sf.net ------------------- 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] 29+ messages in thread
* Re: [Caml-list] Re: OCAML Downcasting? 2004-09-21 9:29 ` skaller @ 2004-09-21 9:49 ` Jacques GARRIGUE 0 siblings, 0 replies; 29+ messages in thread From: Jacques GARRIGUE @ 2004-09-21 9:49 UTC (permalink / raw) To: skaller; +Cc: caml-list From: skaller <skaller@users.sourceforge.net> > On Tue, 2004-09-21 at 19:15, Jacques GARRIGUE wrote: > > > class ['a] button = object (self) > > inherit ['a] widget > > method raw = `Button (self :> 'a button) > > method press = prerr_endline "pressed" > > end > > > Without the self-cast, you cannot extend any class. > > Is that an issue with classes or polymorphic variants? With classes. If you omit the coercion, any class inheriting from button would have the type of the raw method specialized to itself, and as a result it would be incompatible with button. ... But strangely enough, some tests show that this is not the case. Even without the coercion, the type of `Button becomes fixed to 'a button. Looks like there is a bug in the interaction between classes and variants. So do not forget the coercion even if it works now without... 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] 29+ messages in thread
* Re: [Caml-list] Re: OCAML Downcasting? 2004-09-21 9:15 ` Jacques GARRIGUE 2004-09-21 9:29 ` skaller @ 2004-09-21 9:34 ` Stefano Zacchiroli 2004-09-21 9:56 ` Jacques GARRIGUE 1 sibling, 1 reply; 29+ messages in thread From: Stefano Zacchiroli @ 2004-09-21 9:34 UTC (permalink / raw) To: caml-list On Tue, Sep 21, 2004 at 06:15:31PM +0900, Jacques GARRIGUE wrote: > > even "ocamlc -i" fails ! > You're right. Anyway, shouldn't this be considered an "ocamlc -i" bug? I used to assume that: ocamlc -i a.ml > a.mli ocamlc -c a.mli ocamlc -c a.ml should work for every compilable a.ml. Was I wrong? -- Stefano Zacchiroli -*- Computer Science PhD student @ Uny Bologna, Italy zack@{cs.unibo.it,debian.org,bononia.it} -%- http://www.bononia.it/zack/ If there's any real truth it's that the entire multidimensional infinity of the Universe is almost certainly being run by a bunch of maniacs. -!- ------------------- 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] 29+ messages in thread
* Re: [Caml-list] Re: OCAML Downcasting? 2004-09-21 9:34 ` Stefano Zacchiroli @ 2004-09-21 9:56 ` Jacques GARRIGUE 0 siblings, 0 replies; 29+ messages in thread From: Jacques GARRIGUE @ 2004-09-21 9:56 UTC (permalink / raw) To: zack; +Cc: caml-list From: Stefano Zacchiroli <zack@bononia.it> > On Tue, Sep 21, 2004 at 06:15:31PM +0900, Jacques GARRIGUE wrote: > > > even "ocamlc -i" fails ! > > You're right. > > Anyway, shouldn't this be considered an "ocamlc -i" bug? > > I used to assume that: > > ocamlc -i a.ml > a.mli > ocamlc -c a.mli > ocamlc -c a.ml > > should work for every compilable a.ml. Was I wrong? This is intended to be so, eventhough this is not always easy to print a type both exactly and concisely... In the present case, there clearly seems to be a bug, independently of the error in the example. 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] 29+ messages in thread
* Re: [Caml-list] Re: OCAML Downcasting? 2004-09-21 8:03 ` [Caml-list] Re: OCAML Downcasting? Jacques GARRIGUE 2004-09-21 8:43 ` Damien Pous @ 2004-09-21 19:27 ` Michael Vanier 2004-09-21 21:38 ` Brian Hurt 2004-09-22 1:30 ` Jacques GARRIGUE 1 sibling, 2 replies; 29+ messages in thread From: Michael Vanier @ 2004-09-21 19:27 UTC (permalink / raw) To: garrigue; +Cc: caml-list > Date: Tue, 21 Sep 2004 17:03:39 +0900 (JST) > From: Jacques GARRIGUE <garrigue@kurims.kyoto-u.ac.jp> > > There are two important differences between ocaml and other > OO-languages that have downcasting. > > - inheritance is not subtyping. The subtyping relation being > structural, a full fledge typecast would not only require to keep > type information at runtime, but to embark a large part of the > compiler to check subtyping. This might also be incredibly slow. > > As a result, downcast is only reasonable when we have both > inheritance and subtyping. You're suddenly losing a large part of > the language. But java has interfaces (subtypes), and classes can implement interfaces (making them subtypes of the interface) without inheritance. Furthermore, the class identity can be retrieved from an instance of an interface by using the instanceof operator. > > Worse, even if you have a module interface > class b : > object > inherit a > .... > end > in ocaml this does _not_ mean that b inherits from a, just that it > has at least a's methods and fields. > So the semantics of downcast would not allow abstraction. I don't understand the point you're trying to make here, but it seems like a is effectively equivalent to an interface in java (at least from your description). > - classes may have type parameters. Assume a situation like > class ['a] a = object ... end > Then we cannot downcast any runtime object to "a", because we don't > know what is its type parameter. Again, downcast would not mix well > with other features of the language. Java now has generics (type parameters), and I assume that it has to get around this situation somehow. > > So, while this is somehow unfortunate, there is no downcast in ocaml. > I'm sure there are good reasons for this, but I don't find the arguments you've presented above persuasive. Not that I'm trying to hold java up as a shining example of the Right Thing; I'd much rather program in ocaml than java any day of the week. But the lack of downcasting has frustrated me in the past (it's my #1 gripe about ocaml, with the lack of support for native-code shared libraries at #2). 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] 29+ messages in thread
* Re: [Caml-list] Re: OCAML Downcasting? 2004-09-21 19:27 ` Michael Vanier @ 2004-09-21 21:38 ` Brian Hurt 2004-09-21 22:06 ` Michael Vanier ` (2 more replies) 2004-09-22 1:30 ` Jacques GARRIGUE 1 sibling, 3 replies; 29+ messages in thread From: Brian Hurt @ 2004-09-21 21:38 UTC (permalink / raw) To: Michael Vanier; +Cc: garrigue, caml-list On Tue, 21 Sep 2004, Michael Vanier wrote: > But java has interfaces (subtypes), and classes can implement interfaces > (making them subtypes of the interface) without inheritance. Furthermore, > the class identity can be retrieved from an instance of an interface by > using the instanceof operator. Java also has run time type identification, something Ocaml doesn't have. And generally doesn't need. Downcasting, however, requires RTTI- I hand you an object of class foo, you think it's really an object of class bar (which inherits from foo), and want to turn the foo into a bar- but how do you know it's *really* a bar? It might just be a foo, it might be a baz (a different class inheriting from foo). The general solution is to rethink the problem to avoid the downcast. Some general platitudes: first, avoid upcasts. Try using column types instead. Second, move the operations that need the downcast into the object itself- delegate (the object knows what sort of object it really is, even if you don't). Third, ditch objects. Java, C++, etc. strongly encourage you to think of everything as an object, try designing the code sans objects and see how it works. Fourth, hand implement RTTI- either by adding member functions to the base class to do the conversion (throwing an exception if the conversion is bad), or using a variant type. > > - classes may have type parameters. Assume a situation like > > class ['a] a = object ... end > > Then we cannot downcast any runtime object to "a", because we don't > > know what is its type parameter. Again, downcast would not mix well > > with other features of the language. > > Java now has generics (type parameters), and I assume that it has to get > around this situation somehow. If I understand it correctly, they basically lifted C++'s templates more or less verbatim. I don't have experience with Java Generics, but C++ templates create a whole new copy of the class for every type they handle. So that List<short>, List<int>, List<float>, List<foo_t>, etc. all use different instantiations. How C++ gets around it is that if you have a template<class t> class foo_t, bar_t doesn't so much inherit from foo_t, as bar_t<int> inherits from foo_t<int>, etc. > > > > > So, while this is somehow unfortunate, there is no downcast in ocaml. > > > > I'm sure there are good reasons for this, but I don't find the arguments > you've presented above persuasive. Not that I'm trying to hold java up as > a shining example of the Right Thing; I'd much rather program in ocaml than > java any day of the week. But the lack of downcasting has frustrated me in > the past (it's my #1 gripe about ocaml, with the lack of support for > native-code shared libraries at #2). Downcasting is a sign you're doing something wrong. If you knew the object was a bar_t, why didn't it have the type bar_t from the get-go? If you don't know it's a bar_t, how do you know it's safe to cast it to a bar_t? Without RTTI, that is. By the way, RTTI costs memory (at least one extra word per object, plus the overhead of the Class classes for all types). Plus- does RTTI apply to non-objects? Ocaml has a lot of types that are not classes. -- "Usenet is like a herd of performing elephants with diarrhea -- massive, difficult to redirect, awe-inspiring, entertaining, and a source of mind-boggling amounts of excrement when you least expect it." - Gene Spafford Brian ------------------- 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] 29+ messages in thread
* Re: [Caml-list] Re: OCAML Downcasting? 2004-09-21 21:38 ` Brian Hurt @ 2004-09-21 22:06 ` Michael Vanier 2004-09-21 22:32 ` Brian Hurt 2004-09-22 1:04 ` skaller 2004-09-21 22:20 ` Marcin 'Qrczak' Kowalczyk 2004-09-22 0:50 ` skaller 2 siblings, 2 replies; 29+ messages in thread From: Michael Vanier @ 2004-09-21 22:06 UTC (permalink / raw) To: bhurt; +Cc: caml-list > Date: Tue, 21 Sep 2004 16:38:25 -0500 (CDT) > From: Brian Hurt <bhurt@spnz.org> > Cc: garrigue@kurims.kyoto-u.ac.jp, <caml-list@inria.fr> > > On Tue, 21 Sep 2004, Michael Vanier wrote: > > > But java has interfaces (subtypes), and classes can implement interfaces > > (making them subtypes of the interface) without inheritance. Furthermore, > > the class identity can be retrieved from an instance of an interface by > > using the instanceof operator. > > Java also has run time type identification, something Ocaml doesn't have. > And generally doesn't need. Downcasting, however, requires RTTI- I hand > you an object of class foo, you think it's really an object of class bar > (which inherits from foo), and want to turn the foo into a bar- but how do > you know it's *really* a bar? It might just be a foo, it might be a baz > (a different class inheriting from foo). Yes, I was assuming RTTI, which is what the instanceof operator provides. > > Java now has generics (type parameters), and I assume that it has to get > > around this situation somehow. > > If I understand it correctly, they basically lifted C++'s templates more > or less verbatim. I don't have experience with Java Generics, but C++ > templates create a whole new copy of the class for every type they handle. > So that List<short>, List<int>, List<float>, List<foo_t>, etc. all use > different instantiations. How C++ gets around it is that if you have a > template<class t> class foo_t, bar_t doesn't so much inherit from foo_t, > as bar_t<int> inherits from foo_t<int>, etc. Um, no, they didn't. In fact, it's a completely different mechanism. The compiler erases the generic information so that the JVM sees only old-style java classes without parameterization and adds casts where needed. OK, this wasn't the greatest example in the world, because it relies massively on RTTI. > > > > > > So, while this is somehow unfortunate, there is no downcast in ocaml. > > > > > > > I'm sure there are good reasons for this, but I don't find the arguments > > you've presented above persuasive. Not that I'm trying to hold java up as > > a shining example of the Right Thing; I'd much rather program in ocaml than > > java any day of the week. But the lack of downcasting has frustrated me in > > the past (it's my #1 gripe about ocaml, with the lack of support for > > native-code shared libraries at #2). > > Downcasting is a sign you're doing something wrong. If you knew the > object was a bar_t, why didn't it have the type bar_t from the get-go? If > you don't know it's a bar_t, how do you know it's safe to cast it to a > bar_t? Without RTTI, that is. I don't agree. For instance, try implementing the equivalent of multimethods without some kind of downcast. Of course, if a language supported multimethods from the get-go it would be even nicer, but very few languages do. Now, if you're going to argue that wanting multimethods at all is a sign that you haven't thought through a problem carefully enough, we'll just have to agree to disagree. I'm always suspicious of arguments that start off with "you really don't want to do that", because I can't say with any certainty what I will want to do or need to do 100% of the time. 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] 29+ messages in thread
* Re: [Caml-list] Re: OCAML Downcasting? 2004-09-21 22:06 ` Michael Vanier @ 2004-09-21 22:32 ` Brian Hurt 2004-09-22 1:04 ` skaller 1 sibling, 0 replies; 29+ messages in thread From: Brian Hurt @ 2004-09-21 22:32 UTC (permalink / raw) To: Michael Vanier; +Cc: caml-list On Tue, 21 Sep 2004, Michael Vanier wrote: > Um, no, they didn't. In fact, it's a completely different mechanism. The > compiler erases the generic information so that the JVM sees only old-style > java classes without parameterization and adds casts where needed. OK, > this wasn't the greatest example in the world, because it relies massively > on RTTI. OK. I'm not up on what precisely Java is doing here. I note that they're also adding autoboxing/unboxing. > I don't agree. For instance, try implementing the equivalent of > multimethods without some kind of downcast. Of course, if a language > supported multimethods from the get-go it would be even nicer, but very few > languages do. Now, if you're going to argue that wanting multimethods at > all is a sign that you haven't thought through a problem carefully enough, > we'll just have to agree to disagree. I'm always suspicious of arguments > that start off with "you really don't want to do that", because I can't say > with any certainty what I will want to do or need to do 100% of the time. Multimethods should use variant (tagged) types, not objects and downcasting. For example, consider the case where I want to deal with a number, that could be an integer, a floating point number, or a complex (x + yi format) number. I'd implement it like: type number_t = | Int of int | Float of float | Complex of float * float ;; let add a b = match a, b with | Int(x), Int(y) -> Int(x + y) | Int(x), Float(y) | Float(y), Int(x) -> Float((float_of_int x) +. y) | Float(x), Float(y) -> Float(x +. y) | Int(x), Complex(yr, yi) | Complex(yr, yi), Float(x) -> Complex(((float_of_int x) +. yr), yi) | Float(x), Complex(yr, yi) | Complex(yr, yi), Float(x) -> Complex(x +. yr, yi) | Complex(xr, xi), Complex(yr, yi) -> Complex(xr +. yr, xi +. yi) ;; This is what I meant by not everything in Ocaml needs to be objects. Note that there is an advantage to how Ocaml does it- if you add a new tag to number_t, Ocaml will warn you in all the places you need to update to handle the new tag. -- "Usenet is like a herd of performing elephants with diarrhea -- massive, difficult to redirect, awe-inspiring, entertaining, and a source of mind-boggling amounts of excrement when you least expect it." - Gene Spafford Brian ------------------- 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] 29+ messages in thread
* Re: [Caml-list] Re: OCAML Downcasting? 2004-09-21 22:06 ` Michael Vanier 2004-09-21 22:32 ` Brian Hurt @ 2004-09-22 1:04 ` skaller 1 sibling, 0 replies; 29+ messages in thread From: skaller @ 2004-09-22 1:04 UTC (permalink / raw) To: caml-list On Wed, 2004-09-22 at 08:06, Michael Vanier wrote: > Um, no, they didn't. In fact, it's a completely different mechanism. The > compiler erases the generic information so that the JVM sees only old-style > java classes without parameterization and adds casts where needed. OK, > this wasn't the greatest example in the world, because it relies massively > on RTTI. Ocaml does this too. However, the polymorphism uses *static* type checking to erase the type information, and doesn't need to use RTTI. BTW: Ocaml *does* provide limited RTTI and dynamic dispatch on that RTTI. If you examine: type num = Int of int | Float of float match x with | Int x -> print_int x | Float x -> print_float x you can see that the match must use RTTI and it does. However it isn't a full description of the type, just an integral 'tag' allowing a switch to the correct case. Not enough information to check the type -- the static type system has checked already 'up to which variant' and the rest is done at runtime. Similarly, RTTI is used to do array bounds checks in Ocaml: arrays typing is weaker than in Pascal, which never needs array bound checks, or Modula, where advanced analysis can elide about 60% of such checks. -- John Skaller, mailto:skaller@users.sf.net voice: 061-2-9660-0850, snail: PO BOX 401 Glebe NSW 2037 Australia Checkout the Felix programming language http://felix.sf.net ------------------- 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] 29+ messages in thread
* Re: [Caml-list] Re: OCAML Downcasting? 2004-09-21 21:38 ` Brian Hurt 2004-09-21 22:06 ` Michael Vanier @ 2004-09-21 22:20 ` Marcin 'Qrczak' Kowalczyk 2004-09-22 2:26 ` skaller 2004-09-22 0:50 ` skaller 2 siblings, 1 reply; 29+ messages in thread From: Marcin 'Qrczak' Kowalczyk @ 2004-09-21 22:20 UTC (permalink / raw) To: Brian Hurt; +Cc: Michael Vanier, garrigue, caml-list Brian Hurt <bhurt@spnz.org> writes: > The general solution is to rethink the problem to avoid the downcast. It's not always possible or desirable. Example 1: exceptions. Fortunately OCaml provides an extensible exn type. It's probably impossible to emulate using other features: classes, polymorphic variants, modules etc., without Obj.magic. OTOH dynamically typed or OO languages typically don't need extra language features just to *represent* exceptions of extensible types. Example 2: embedding a dynamically typed sublanguage in OCaml, with extensible set of types of wrapped objects. For this I had to use Obj.magic with manual tagging of dynamic types. Attempts to avoid downcasts are often unmodular, they require to specify all possible variants in one place. >> Java now has generics (type parameters), and I assume that it has to get >> around this situation somehow. > > If I understand it correctly, they basically lifted C++'s templates more > or less verbatim. AFAIK the implementation technique is entirely different, similar to parametric polymorphism in OCaml. It influences the semantics. You can't select overloaded methods basing on a type substituted for a type variable for example (except by using reflection at runtime); you can do that in C++. There are no specializations of generics. There are no types depending on types (an equivalent of putting different typedefs in different specializations of a template). Java generics compared to C++ templates are like OCaml parametric polymorphism compared to OCaml modules. > Downcasting is a sign you're doing something wrong. I disagree. It may be, or not. Just that OCaml doesn't support something doesn't imply that it must be evil. > If you knew the object was a bar_t, why didn't it have the type > bar_t from the get-go? For the same reason as why can't exn be a regular algebraic type. > If you don't know it's a bar_t, how do you know it's safe to cast it > to a bar_t? Without RTTI, that is. Of course something is necessary to determine at runtime whether it's safe. I don't advocate unsafe constructs. > By the way, RTTI costs memory (at least one extra word per object, > plus the overhead of the Class classes for all types). You could move the object header there. It would only make no room for two bits for GC that OCaml uses, so it would be hard to adapt to OCaml as it is, but it's not a significant overhead in general. A dynamically typed language can have the overhead of one word per object, for most objects. Only the size of arrays and strings is stored after the header, but it would be a good idea anyway compared to the current design - it would remove the artificial limit of object sizes. > Plus- does RTTI apply to non-objects? Ocaml has a lot of types that > are not classes. A possible answer: conceptually yes, physically it can be avoided for unboxed ints or other unboxed variables whose type is known statically; constants like the empty list can be boxed and allocated statically, so they have almost the same overhead as currently (only the bit pattern is not known until link time). I don't claim that it would be easy to adapt to OCaml as it is. I claim that it's not a bad idea in general. -- __("< Marcin Kowalczyk \__/ qrczak@knm.org.pl ^^ http://qrnik.knm.org.pl/~qrczak/ ------------------- 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] 29+ messages in thread
* Re: [Caml-list] Re: OCAML Downcasting? 2004-09-21 22:20 ` Marcin 'Qrczak' Kowalczyk @ 2004-09-22 2:26 ` skaller 2004-09-22 6:31 ` Marcin 'Qrczak' Kowalczyk 0 siblings, 1 reply; 29+ messages in thread From: skaller @ 2004-09-22 2:26 UTC (permalink / raw) To: caml-list On Wed, 2004-09-22 at 08:20, Marcin 'Qrczak' Kowalczyk wrote: > Attempts to avoid downcasts are often unmodular, they require to > specify all possible variants in one place. It makes no difference. You have do specify them all anyhow, downcast or not. > > Downcasting is a sign you're doing something wrong. > > I disagree. It may be, or not. Just that OCaml doesn't support > something doesn't imply that it must be evil. The unstated assumption is that you want early error detection and efficiency which static typing promises. If you are willing to forgo these benefits -- and have slow unreliable programs -- then you can use downcasts, RTTI, or even code in Assmebler. My typesetting tool Interscript uses Python for dynamic message dispatch -- a certain class of errors lead to exceptions being thrown which are just ignored. This is intentional. The result is sometimes bad output, so you have to actually proofread the generated document to be sure you got what you expected. The reason is that (a) usually ignoring a request to use a LaTeX feature in HTML is reasonable, or vice versa. (b) termination of processing with a weird error makes finding the problem harder than generating bad output where you can actually examine the consequences visually. I.e. what I'm doing is even 'worse' than run time error diagnosis -- I'm checking, and then ignoring the fault :) > Of course something is necessary to determine at runtime whether it's > safe. I don't advocate unsafe constructs. In the static typing world, 'safe' means errors are always detected at compile time. Clearly this is impossible in general, so safe is a relative term. I consider Ocaml *unsafe* because array bounds aren't checked at compile time. Catching the error at run time is better than not catching it -- but it still means the program is unsafe. Generally, we'd like to make programs safer where possible. The problem with downcasting as a general technique is that it bypasses static safety where it is in fact desired and is available. -- John Skaller, mailto:skaller@users.sf.net voice: 061-2-9660-0850, snail: PO BOX 401 Glebe NSW 2037 Australia Checkout the Felix programming language http://felix.sf.net ------------------- 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] 29+ messages in thread
* Re: [Caml-list] Re: OCAML Downcasting? 2004-09-22 2:26 ` skaller @ 2004-09-22 6:31 ` Marcin 'Qrczak' Kowalczyk 2004-09-22 9:03 ` sejourne_kevin ` (5 more replies) 0 siblings, 6 replies; 29+ messages in thread From: Marcin 'Qrczak' Kowalczyk @ 2004-09-22 6:31 UTC (permalink / raw) To: skaller; +Cc: caml-list skaller <skaller@users.sourceforge.net> writes: >> Attempts to avoid downcasts are often unmodular, they require to >> specify all possible variants in one place. > > It makes no difference. You have do specify them all anyhow, > downcast or not. It makes a difference because specifying them at the type definition would introduce a dependency loop between modules. And it would be unmodular: it would require changing some base module whenever a far client module is added. Apply this reasoning to the exn type. Why don't you define all exn constructors in one place? > The unstated assumption is that you want early error detection > and efficiency which static typing promises. It's impossible in general. Only some errors are detectable statically in practice. > In the static typing world, 'safe' means errors are always > detected at compile time. No practical language is safe according to this definition, so this definition is useless. > Generally, we'd like to make programs safer where possible. This is the catch: "where possible". I would add: "where practical"; sometimes the cost outweights the benefits. For example static detection of possible division by 0 would be impractical. You would have to either embed a proof checker in the language in order to be able to convince the compiler that the number can't be 0, or not use exceptions at all and have all partial functions return a result in "option" type or similar, with manual propagation of errors. And guess what? No language I know checks division by 0 statically (except proof checkers, but they are not suitable for writing big programs - too much work). Because it would make programs less robust, not more. Because you would not use exceptions, and manual propagation of errors is more error-prone than using exceptions, and it causes more problems when the set of possible exceptions raised in a given part of code is changed. > The problem with downcasting as a general technique is that it > bypasses static safety where it is in fact desired and is available. It's not available because it can't express what downcasts provide: the ability to add "constructors" to a type in a modular way. According to your beliefs, you should advocate removing exceptions from OCaml. Because they make the type independent from the set of ways in which a program can fail, and thus remove the ability to statically check whether all possible errors are caught. You should always use explicit algebraic types to encode the outcome, no? -- __("< Marcin Kowalczyk \__/ qrczak@knm.org.pl ^^ http://qrnik.knm.org.pl/~qrczak/ ------------------- 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] 29+ messages in thread
* Re: [Caml-list] Re: OCAML Downcasting? 2004-09-22 6:31 ` Marcin 'Qrczak' Kowalczyk @ 2004-09-22 9:03 ` sejourne_kevin 2004-09-22 10:29 ` Richard Jones ` (4 subsequent siblings) 5 siblings, 0 replies; 29+ messages in thread From: sejourne_kevin @ 2004-09-22 9:03 UTC (permalink / raw) To: caml-list Marcin 'Qrczak' Kowalczyk wrote: > skaller <skaller@users.sourceforge.net> writes: > > >>>Attempts to avoid downcasts are often unmodular, they require to >>>specify all possible variants in one place. >> >>It makes no difference. You have do specify them all anyhow, >>downcast or not. > > > It makes a difference because specifying them at the type definition > would introduce a dependency loop between modules. And it would be > unmodular: it would require changing some base module whenever a far > client module is added. > > Apply this reasoning to the exn type. Why don't you define all exn > constructors in one place? I think there is no problems with exceptions. But if you have problems managing exceptions in large modules have you try something like this ? here an example: I define all my exceptions like this : let errors = ref [];; (*to define an error*) (*errors "the exception" , the new value*) errors := ("div by zero" ,0) :: (!errors);; And the functions catch errors in this way: let truc () = try ... with ... all Ocaml pre-defined exceptions | exn -> (* my exceptions in errors list ref *) let s = Printexc.to_string exn in ... Lex & Parse 's' in (fst errors) ref list , then handle error ... ;; If exceptions are complex I can use polymorphic variants for the "new value". ------------------- 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] 29+ messages in thread
* Re: [Caml-list] Re: OCAML Downcasting? 2004-09-22 6:31 ` Marcin 'Qrczak' Kowalczyk 2004-09-22 9:03 ` sejourne_kevin @ 2004-09-22 10:29 ` Richard Jones 2004-09-22 18:39 ` Brian Hurt 2004-09-22 10:50 ` skaller ` (3 subsequent siblings) 5 siblings, 1 reply; 29+ messages in thread From: Richard Jones @ 2004-09-22 10:29 UTC (permalink / raw) To: caml-list [-- Attachment #1: Type: text/plain, Size: 1654 bytes --] On Wed, Sep 22, 2004 at 08:31:38AM +0200, Marcin 'Qrczak' Kowalczyk wrote: > skaller <skaller@users.sourceforge.net> writes: > > >> Attempts to avoid downcasts are often unmodular, they require to > >> specify all possible variants in one place. > > > > It makes no difference. You have do specify them all anyhow, > > downcast or not. > > It makes a difference because specifying them at the type definition > would introduce a dependency loop between modules. And it would be > unmodular: it would require changing some base module whenever a far > client module is added. I've tended to stop using and thinking in OO terms since starting to use OCaml. In particular, when I need a data structure of some sort, I just use a data structure (tuple, struct, variant whatever). Before coming to OCaml, data structure implied "class" for me. The advantage to me is that now when I change the data structure the compiler catches all the places in the code which I need to change, so I go through and methodically change them. But the OCaml assumption here is that you program is one big monolithic entity, for which you have source (and are recompiling) all parts. This goes against the OO theory of "reuse" - particularly of reuse of binary classes, which I don't think I've ever actually used in practice anyway. Rich. -- Richard Jones. http://www.annexia.org/ http://www.j-london.com/ Merjis Ltd. http://www.merjis.com/ - improving website return on investment NET::FTPSERVER is a full-featured, secure, configurable, database-backed FTP server written in Perl: http://www.annexia.org/freeware/netftpserver/ [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 189 bytes --] ^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [Caml-list] Re: OCAML Downcasting? 2004-09-22 10:29 ` Richard Jones @ 2004-09-22 18:39 ` Brian Hurt 0 siblings, 0 replies; 29+ messages in thread From: Brian Hurt @ 2004-09-22 18:39 UTC (permalink / raw) To: Richard Jones; +Cc: caml-list On Wed, 22 Sep 2004, Richard Jones wrote: > But the OCaml assumption here is that you program is one big > monolithic entity, for which you have source (and are recompiling) all > parts. This goes against the OO theory of "reuse" - particularly of > reuse of binary classes, which I don't think I've ever actually used > in practice anyway. Note that OO resuse is not the only theory of reuse possible. Partial function application, higher order functions, modules and functors, universal types ('a), etc. also allow incredible code reuse, without touching objects. In OO program, the object or class is the building block of reuse- in functional programming, it's the function. If all you know is hammers, a cresent wrench is seen as a badly designed hammer. -- "Usenet is like a herd of performing elephants with diarrhea -- massive, difficult to redirect, awe-inspiring, entertaining, and a source of mind-boggling amounts of excrement when you least expect it." - Gene Spafford Brian ------------------- 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] 29+ messages in thread
* Re: [Caml-list] Re: OCAML Downcasting? 2004-09-22 6:31 ` Marcin 'Qrczak' Kowalczyk 2004-09-22 9:03 ` sejourne_kevin 2004-09-22 10:29 ` Richard Jones @ 2004-09-22 10:50 ` skaller 2004-09-22 12:03 ` Alain Frisch ` (2 subsequent siblings) 5 siblings, 0 replies; 29+ messages in thread From: skaller @ 2004-09-22 10:50 UTC (permalink / raw) To: Marcin 'Qrczak' Kowalczyk; +Cc: caml-list On Wed, 2004-09-22 at 16:31, Marcin 'Qrczak' Kowalczyk wrote: > sometimes the cost outweights the benefits. For example static > detection of possible division by 0 would be impractical. You could use a monad .. :) > And guess what? No language I know checks division by 0 statically Hehe --:> include "std"; print (1/0); endl; [skaller@pelican] ~>flxg aa EXCEPTION Division_by_zero That's a compile time error (Dang -- and its a bug too, the error should report the location .. :) But I assume you mean 'exhaustively'. -- John Skaller, mailto:skaller@users.sf.net voice: 061-2-9660-0850, snail: PO BOX 401 Glebe NSW 2037 Australia Checkout the Felix programming language http://felix.sf.net ------------------- 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] 29+ messages in thread
* Re: [Caml-list] Re: OCAML Downcasting? 2004-09-22 6:31 ` Marcin 'Qrczak' Kowalczyk ` (2 preceding siblings ...) 2004-09-22 10:50 ` skaller @ 2004-09-22 12:03 ` Alain Frisch 2004-09-22 12:50 ` Cláudio Valente 2004-09-22 18:42 ` Brian Hurt 5 siblings, 0 replies; 29+ messages in thread From: Alain Frisch @ 2004-09-22 12:03 UTC (permalink / raw) To: Marcin 'Qrczak' Kowalczyk; +Cc: skaller, caml-list On Wed, 22 Sep 2004, Marcin 'Qrczak' Kowalczyk wrote: > This is the catch: "where possible". I would add: "where practical"; > sometimes the cost outweights the benefits. For example static > detection of possible division by 0 would be impractical. You would > have to either embed a proof checker in the language in order to be > able to convince the compiler that the number can't be 0, or not use > exceptions at all and have all partial functions return a result in > "option" type or similar, with manual propagation of errors. You don't necessarily have to use a proof checker. What about using a type system, or a(nother kind of) static analysis ? E.g. detection of division by 0 can be done with interval arithmetic, and it might work well in practice. > And guess what? No language I know checks division by 0 statically > (except proof checkers, but they are not suitable for writing big > programs - too much work). CDuce version 0.2.1+1 # fun (x : Int) : Int = 1 div x;; Warning at chars 22-29: This operator may fail - : Int -> Int = <fun> # fun (x : 0--*) : Int = 1 div x;; Warning at chars 23-30: This operator may fail - : 0--* -> Int = <fun> # fun (x : 1--*) : Int = 1 div x;; - : 1--* -> Int = <fun> # fun (x : 1--*) : Int = 1 div (x + x);; - : 1--* -> Int = <fun> # fun (x : 1--*) : Int = 1 div (x - x + x);; Warning at chars 23-40: This operator may fail - : 1--* -> Int = <fun> (type 1--* means: "positive integers") To get rid of warning (or compile-time error) when the type system is not precise enough (the last example above), you can always do an explicit check: # fun (x : 1--*) : Int = match x - x + x with | y & (1--*) -> 1 div y | _ -> raise "Bla";; - : 1--* -> Int = <fun> -- 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] 29+ messages in thread
* Re: [Caml-list] Re: OCAML Downcasting? 2004-09-22 6:31 ` Marcin 'Qrczak' Kowalczyk ` (3 preceding siblings ...) 2004-09-22 12:03 ` Alain Frisch @ 2004-09-22 12:50 ` Cláudio Valente 2004-09-22 13:15 ` Marcin 'Qrczak' Kowalczyk 2004-09-22 18:42 ` Brian Hurt 5 siblings, 1 reply; 29+ messages in thread From: Cláudio Valente @ 2004-09-22 12:50 UTC (permalink / raw) To: Marcin 'Qrczak' Kowalczyk; +Cc: skaller, caml-list Em Quarta, 22 de Setembro de 2004 07:31, o Marcin 'Qrczak' Kowalczyk escreveu: > And guess what? No language I know checks division by 0 statically > (except proof checkers, but they are not suitable for writing big > programs - too much work) 12>0 cvalente@link Stats 54$ cat t.pl sub t{ print 1/0; } 13>0 cvalente@link Stats 54$ perl -c t.pl Illegal division by zero at t.pl line 2. perl -c stands for check syntax gcc also has this. It gives a warning gcc -c t.c t.c: In function `t': t.c:2: warning: division by zero and it does even more: 24>0 cvalente@link Stats 54$ cat t.cpp const int X = 1-1; int t(int i){ return i/X; } 25>0 cvalente@link Stats 54$ g++ -c t.cpp t.cpp: In function `int t(int)': t.cpp:3: warning: division by zero in `i / 0' These are not exhaustive tests, but they are good enough to catch many common errors. -- Cláudio Valente ------------------- 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] 29+ messages in thread
* Re: [Caml-list] Re: OCAML Downcasting? 2004-09-22 12:50 ` Cláudio Valente @ 2004-09-22 13:15 ` Marcin 'Qrczak' Kowalczyk 2004-09-22 15:50 ` skaller 0 siblings, 1 reply; 29+ messages in thread From: Marcin 'Qrczak' Kowalczyk @ 2004-09-22 13:15 UTC (permalink / raw) To: cvalente; +Cc: skaller, caml-list Cláudio Valente <cvalente@co.sapo.pt> writes: >> And guess what? No language I know checks division by 0 statically >> (except proof checkers, but they are not suitable for writing big >> programs - too much work) > These are not exhaustive tests, but they are good enough to catch > many common errors. I meant exhaustive tests, not heuristics for easy cases where the divisor is constant. -- __("< Marcin Kowalczyk \__/ qrczak@knm.org.pl ^^ http://qrnik.knm.org.pl/~qrczak/ ------------------- 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] 29+ messages in thread
* Re: [Caml-list] Re: OCAML Downcasting? 2004-09-22 13:15 ` Marcin 'Qrczak' Kowalczyk @ 2004-09-22 15:50 ` skaller 0 siblings, 0 replies; 29+ messages in thread From: skaller @ 2004-09-22 15:50 UTC (permalink / raw) To: Marcin 'Qrczak' Kowalczyk; +Cc: cvalente, caml-list On Wed, 2004-09-22 at 23:15, Marcin 'Qrczak' Kowalczyk wrote: > Cláudio Valente <cvalente@co.sapo.pt> writes: > I meant exhaustive tests, not heuristics for easy cases where the > divisor is constant. It is of course possible to it entirely statically right now in Ocaml by using an abstract type for a non-zero int. Not as good as CDuce's interval arithmetic because you have to handle the 0 in the int-> nonzero_int conversion, but still afterwards you can divide without an exception. Some functions, eg multiplication, preserve non-zeroness, so in many cases you can use static typing to avoid gratuitous checks for zero. As you may have noted in my Felix example -- exceptions are just too powerful: I forgot to catch the exception. I fixed my modulus function too .. but no doubt I have missed others. Perhaps static checking would make programming harder -- but nothing is harder than exhaustively testing a complex program. -- John Skaller, mailto:skaller@users.sf.net voice: 061-2-9660-0850, snail: PO BOX 401 Glebe NSW 2037 Australia Checkout the Felix programming language http://felix.sf.net ------------------- 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] 29+ messages in thread
* Re: [Caml-list] Re: OCAML Downcasting? 2004-09-22 6:31 ` Marcin 'Qrczak' Kowalczyk ` (4 preceding siblings ...) 2004-09-22 12:50 ` Cláudio Valente @ 2004-09-22 18:42 ` Brian Hurt 2004-09-22 18:44 ` Marcin 'Qrczak' Kowalczyk 5 siblings, 1 reply; 29+ messages in thread From: Brian Hurt @ 2004-09-22 18:42 UTC (permalink / raw) To: Marcin 'Qrczak' Kowalczyk; +Cc: caml-list On Wed, 22 Sep 2004, Marcin 'Qrczak' Kowalczyk wrote: > It makes a difference because specifying them at the type definition > would introduce a dependency loop between modules. And it would be > unmodular: it would require changing some base module whenever a far > client module is added. > > Apply this reasoning to the exn type. Why don't you define all exn > constructors in one place? Ignoring the fact that exceptions are built into the language, I'd read section 4.2 "Polymorphic Variants" of the Ocaml language manual for how to get around this. -- "Usenet is like a herd of performing elephants with diarrhea -- massive, difficult to redirect, awe-inspiring, entertaining, and a source of mind-boggling amounts of excrement when you least expect it." - Gene Spafford Brian ------------------- 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] 29+ messages in thread
* Re: [Caml-list] Re: OCAML Downcasting? 2004-09-22 18:42 ` Brian Hurt @ 2004-09-22 18:44 ` Marcin 'Qrczak' Kowalczyk 2004-09-22 19:18 ` Brian Hurt 0 siblings, 1 reply; 29+ messages in thread From: Marcin 'Qrczak' Kowalczyk @ 2004-09-22 18:44 UTC (permalink / raw) To: Brian Hurt; +Cc: caml-list Brian Hurt <bhurt@spnz.org> writes: >> Apply this reasoning to the exn type. Why don't you define all exn >> constructors in one place? > > Ignoring the fact that exceptions are built into the language, I'd read > section 4.2 "Polymorphic Variants" of the Ocaml language manual for how to > get around this. It helps only in some cases. In particular it's not expressive enough to replace exn. -- __("< Marcin Kowalczyk \__/ qrczak@knm.org.pl ^^ http://qrnik.knm.org.pl/~qrczak/ ------------------- 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] 29+ messages in thread
* Re: [Caml-list] Re: OCAML Downcasting? 2004-09-22 18:44 ` Marcin 'Qrczak' Kowalczyk @ 2004-09-22 19:18 ` Brian Hurt 0 siblings, 0 replies; 29+ messages in thread From: Brian Hurt @ 2004-09-22 19:18 UTC (permalink / raw) To: Marcin 'Qrczak' Kowalczyk; +Cc: caml-list On Wed, 22 Sep 2004, Marcin 'Qrczak' Kowalczyk wrote: > Brian Hurt <bhurt@spnz.org> writes: > > >> Apply this reasoning to the exn type. Why don't you define all exn > >> constructors in one place? > > > > Ignoring the fact that exceptions are built into the language, I'd read > > section 4.2 "Polymorphic Variants" of the Ocaml language manual for how to > > get around this. > > It helps only in some cases. In particular it's not expressive enough > to replace exn. No. That's why exceptions were built into the language. It does, however, allow you to 'retrofit' RTTI onto any type: let do_stuff = function | `Foo of foo -> (* our argument is only of type foo, only do stuff we can do with a foo. *) foo#do_foo_stuff() | `Bar of bar -> (* In addition to being a foo, our argument is also a bar. Do foo stuff and bar stuff. *) bar#do_foo_stuff (); bar#do_bar_stuff () ;; As for interpreting a RTTI language, I do a full on interpreter. I don't try to use Ocaml as an intermediate language. Every object gets a StringMap ( = Map.Make(String)) to allow me to look up the member function definition from the function name. I collect the arguments up into another StringMap (mapping from the name of the argument to the value), and pass that it to any function I call. Yes, you have to add the type information to every object, instead of having the compiler do it for you. There is a whole long list of features Ocaml has that Java lacks, or requires you to use broken kludges to work around. It sounds like- the better part of a decade later- they finally figured out that univeral types and being able to express types like 'int array list list' is a good thing. Partial function application still has to be kludged with "doit" objects- objects and interfaces with single member functions- the "doit" function. And so on, and so forth. The trick is, when programming in Java, to "think in Java", not in Ocaml (or C). Likewise, the trick is, when programming in Ocaml, to think in Ocaml. The question is not "how do I make this particular Java solution to the problem work?" The question is "how do I solve this problem in Ocaml?" -- "Usenet is like a herd of performing elephants with diarrhea -- massive, difficult to redirect, awe-inspiring, entertaining, and a source of mind-boggling amounts of excrement when you least expect it." - Gene Spafford Brian ------------------- 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] 29+ messages in thread
* Re: [Caml-list] Re: OCAML Downcasting? 2004-09-21 21:38 ` Brian Hurt 2004-09-21 22:06 ` Michael Vanier 2004-09-21 22:20 ` Marcin 'Qrczak' Kowalczyk @ 2004-09-22 0:50 ` skaller 2 siblings, 0 replies; 29+ messages in thread From: skaller @ 2004-09-22 0:50 UTC (permalink / raw) To: caml-list On Wed, 2004-09-22 at 07:38, Brian Hurt wrote: > Downcasting is a sign you're doing something wrong. If you knew the > object was a bar_t, why didn't it have the type bar_t from the get-go? I agree. However I'll add two explanations here. (1) C++ and Java classes use nominal typing which means they have a particular name. Two similar classes with a different name are different. This is important because the associated type is determined exclusively by the name. In Ocaml, the class name is irrelevant because they use structural typing. This means that what counts is the set of names of the methods and their types. So in Ocaml two similar classes with the different names have the *same* associated type. Of course you can name such types, but the names are just aliases. Structural typing is prone to errors where two types intended to be distinct become interchangeable "by accident" because they have the same method names and types "by accident" but in practice this hardly ever happens. OTOH structural typing is vastly superior to nominal typing when it comes to subtyping. Algorithms can be written requiring a particular type, and can be applied to any class that has that type as a supertype, just as in Java or C++. The difference is you don't have to invade the class definition and add the name of the supertype to the list of abstract bases/interfaces. Therefore, the most fundamental principle of Object Orientation -- Meyers Open/Closed principle -- is obeyed by Ocaml classes and NOT by C++ or Java. It is this principle which helps provide encapsulation. You could say Ocaml is more Object Oriented than either C++ or Java because it obeys the major principles better. (2) In Ocaml we have two kinds of unions: ordinary variants and polymorphic variants, aka sum types. In C++ and Java, we don't have these types natively. [C++ has a severely broken union] So what programmers do to emulate them is use inheritence. This is the primary reason both C++ and java require downcasts. So in summary: OO programmers are generally ignorant of the very fundamentals of programming theory. They're used to dealing with all sorts of weird problems representing simple data which arises directly out from broken type systems C++ and Java provide: a naturally algebraic representation can't be found, because they only provide products and not sums. So the programmer turns to abstraction, but then has to 'unabstract' the abstraction using downcasts. The worst thing about this is that inheritance is used to provide two fundamentally distinct type relations: abstraction/subtyping and unification. In Ocaml, there are two distinct mechanisms. No one would claim Ocaml is perfect, but it does get the basics right. Note I didn't mention the fact you also have first class function types: this has nothing to do with functional programming per se. Its just that languages like Ocaml were designed after doing basic mathematics, Java and C++ were not. -- John Skaller, mailto:skaller@users.sf.net voice: 061-2-9660-0850, snail: PO BOX 401 Glebe NSW 2037 Australia Checkout the Felix programming language http://felix.sf.net ------------------- 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] 29+ messages in thread
* Re: [Caml-list] Re: OCAML Downcasting? 2004-09-21 19:27 ` Michael Vanier 2004-09-21 21:38 ` Brian Hurt @ 2004-09-22 1:30 ` Jacques GARRIGUE 2004-09-22 2:59 ` skaller 1 sibling, 1 reply; 29+ messages in thread From: Jacques GARRIGUE @ 2004-09-22 1:30 UTC (permalink / raw) To: mvanier; +Cc: caml-list From: Michael Vanier <mvanier@cs.caltech.edu> > > From: Jacques GARRIGUE <garrigue@kurims.kyoto-u.ac.jp> > > > > There are two important differences between ocaml and other > > OO-languages that have downcasting. > > > > - inheritance is not subtyping. The subtyping relation being > > structural, a full fledge typecast would not only require to keep > > type information at runtime, but to embark a large part of the > > compiler to check subtyping. This might also be incredibly slow. > > > > As a result, downcast is only reasonable when we have both > > inheritance and subtyping. You're suddenly losing a large part of > > the language. > > But java has interfaces (subtypes), and classes can implement interfaces > (making them subtypes of the interface) without inheritance. Furthermore, > the class identity can be retrieved from an instance of an interface by > using the instanceof operator. Java interfaces are actually closer to inheritance than to subtyping. For a class to support an interface, you must declare it when you define the class, and you have no way to add a new interface afterwards. With ocaml class types, you can coerce an object to any type whose methods it implements, even if the object comes from a class actually defined before this class type. For this reason, I would rather compare java interfaces to purely virtual ocaml classes. Implementing a java inteface then amounts to inheriting from a class whose methods are all virtual. This is closer, because a java class includes extra code for all the interfaces it is supposed to implement. >From an implementation point of view, java interfaces are just a hack to work around the absence of multiple inheritance. And not very efficient at that: method calls through interfaces can be slower than ocaml method calls, which have to be completely dynamic. > > Worse, even if you have a module interface > > class b : > > object > > inherit a > > .... > > end > > in ocaml this does _not_ mean that b inherits from a, just that it > > has at least a's methods and fields. > > So the semantics of downcast would not allow abstraction. > > I don't understand the point you're trying to make here, but it seems like > a is effectively equivalent to an interface in java (at least from your > description). The point is that b may actually have no relation whatsoever to a. It just happens to implements all a's methods, and as result the above syntax can be used to make the declaration shorter. If downcasting were to depend on the inheritance relation (and in java it does, if you rightly consider all the "implements" as weaker versions of "inherits"), then there would be no way at runtime to see b as a subclass of a, eventhough the above declaration lets you think this is the case. > > - classes may have type parameters. Assume a situation like > > class ['a] a = object ... end > > Then we cannot downcast any runtime object to "a", because we don't > > know what is its type parameter. Again, downcast would not mix well > > with other features of the language. > > Java now has generics (type parameters), and I assume that it has to get > around this situation somehow. Well, I tried today with 1.5beta2, and it simply doesn't. Actually, generics only provide very limited type safety if you start using casts. Look at the following program: import java.util.*; class Testgen { public static void main(String[] argv) { ArrayList<Integer> l = new ArrayList<Integer>(); Object l1 = l; ArrayList<String> l2 = (ArrayList<String>)l1; l2.add("Hello"); Integer n = l.get(0); } } When you compile it, you get a warning about the cast (ArrayList<String>) not being checked. When you run it, you get a runtime type error on the last line: not even when you try to add a string to a list of integers, but when you extract an integer from a list of integers! I believe C# intends to do something better, but this is going to be rather heavy-weight, and their subtyping relation is much simpler than ocaml's. > > So, while this is somehow unfortunate, there is no downcast in ocaml. > > I'm sure there are good reasons for this, but I don't find the arguments > you've presented above persuasive. Not that I'm trying to hold java up as > a shining example of the Right Thing; I'd much rather program in ocaml than > java any day of the week. But the lack of downcasting has frustrated me in > the past (it's my #1 gripe about ocaml, with the lack of support for > native-code shared libraries at #2). There are various type-safe idioms to support downcasting. Maybe it would be a good idea to collect them somewhere. Yet I think that other people's comments are right: there are often better ways than downcasting. They may mean that you lose in modularity, but in my opinion you gain more in safety. 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] 29+ messages in thread
* Re: [Caml-list] Re: OCAML Downcasting? 2004-09-22 1:30 ` Jacques GARRIGUE @ 2004-09-22 2:59 ` skaller 0 siblings, 0 replies; 29+ messages in thread From: skaller @ 2004-09-22 2:59 UTC (permalink / raw) To: caml-list On Wed, 2004-09-22 at 11:30, Jacques GARRIGUE wrote: > From an implementation point of view, java interfaces are just a hack > to work around the absence of multiple inheritance. I don't think this is quite right. In C++ you can use 'mixin' abstract classes, however the basic rule is that you do all the mixing with the abstractions, providing subtyping, and then any mixing you do in providing an implementation is regarded as 'implementation inheritance' which you should represent using private bases. However this last rule isn't enforced. Java provides two ways to enhance enforcement: it separates the notion of the abstract class from the concrete implementation, and it provides 'final' classes. Thus, the idea isn't entirely a workaround for lack of multiple inheritance, but instead a refinement of more general and less secure C++ technology, which provides a bit more enforcement. I.e: the separation is deliberate and based on some concept of enforcement of constraints, rather a workaround for a deficiency. -- John Skaller, mailto:skaller@users.sf.net voice: 061-2-9660-0850, snail: PO BOX 401 Glebe NSW 2037 Australia Checkout the Felix programming language http://felix.sf.net ------------------- 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] 29+ messages in thread
end of thread, other threads:[~2004-09-22 19:08 UTC | newest] Thread overview: 29+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- [not found] <ci7tcf$qqf$1@wolfberry.srv.cs.cmu.edu> [not found] ` <ci9ggm$i6p$1@wolfberry.srv.cs.cmu.edu> 2004-09-21 8:03 ` [Caml-list] Re: OCAML Downcasting? Jacques GARRIGUE 2004-09-21 8:43 ` Damien Pous 2004-09-21 9:15 ` Jacques GARRIGUE 2004-09-21 9:29 ` skaller 2004-09-21 9:49 ` Jacques GARRIGUE 2004-09-21 9:34 ` Stefano Zacchiroli 2004-09-21 9:56 ` Jacques GARRIGUE 2004-09-21 19:27 ` Michael Vanier 2004-09-21 21:38 ` Brian Hurt 2004-09-21 22:06 ` Michael Vanier 2004-09-21 22:32 ` Brian Hurt 2004-09-22 1:04 ` skaller 2004-09-21 22:20 ` Marcin 'Qrczak' Kowalczyk 2004-09-22 2:26 ` skaller 2004-09-22 6:31 ` Marcin 'Qrczak' Kowalczyk 2004-09-22 9:03 ` sejourne_kevin 2004-09-22 10:29 ` Richard Jones 2004-09-22 18:39 ` Brian Hurt 2004-09-22 10:50 ` skaller 2004-09-22 12:03 ` Alain Frisch 2004-09-22 12:50 ` Cláudio Valente 2004-09-22 13:15 ` Marcin 'Qrczak' Kowalczyk 2004-09-22 15:50 ` skaller 2004-09-22 18:42 ` Brian Hurt 2004-09-22 18:44 ` Marcin 'Qrczak' Kowalczyk 2004-09-22 19:18 ` Brian Hurt 2004-09-22 0:50 ` skaller 2004-09-22 1:30 ` Jacques GARRIGUE 2004-09-22 2:59 ` skaller
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox