Ashley Yakeley: >I think existential types are arranged so that Haskell never needs to >store type information in them at run-time. So you'll never be able to do >dynamic OOP with them. > >One possible extension to Haskell for dynamic OOP, which I never tire of >suggesting, is the extensible datatype, for instance: > > module P > data BaseType = B1 | B2 | _ > > module Q > data DerivedType = D1 | D2 > data BaseType |= BD DerivedType
That rubs me the wrong way in that it invents new notions, eg, "| _" and "|=" when I get the feeling extant notions can be reused. Eg, why not try to replace the equality with an implication (both equality and implication being notions we already need to know), eg, >data BaseType <= B1 | B2 >data BaseType <= D1 | D2 Of course, that is just an untested idea. My reason for posting is to bring attention to how something similar is done in the language merd, whose designer posts here under the name pixel, and which is actually implemented I think. Having just found this, I do not understand it, but it sure has the look, tone and feel of a good design. merd has a notation a !< b which means that values of type "a" can be used when expecting a value of type "b" --ie, it is a subtype. (note the similarity to "<=".) Haskell's data declaration makes a sum-of-products type, eg, data Maybe a=Nothing|Just a In contrast, merd has sum types written a|b and product types written (a,b) and data constructors which are capitalized, eg, True, Just. So this next is the definition of Maybe in merd: (Maybe,x) = Nothing | (Just,x) (I've simplified and renamed constructors a little.) I believe that factoring Haskell's datatypes into constituent parts, which merd does, is essential to a good subtyping design. Haskell's datatypes are too specialized for particular patterns of uses. In addition, merd has a type called a struct, written a |&| b. For reasons I do not understand, instead of defining, eg, point = (double,double) or point = (Point,double,double) pixel prefers to define point = (X,double) |&| (Y,double) That last way is the standard way of declaring a record type, says pixel. The fact that none of the types introduced so far can be built from the other 3 types is made clear by the rules for subtypes, some of which are (a0, ..., an) !< (b0, ..., bn) <=> ai !< bi (forall i) a !< a | b a |&| b !< a i !< a and i !< b <=> i !< a |&| b i !< a or i !< b <=> i !< a | b i !> a and i !> b <=> i !> a | b i !> a or i !> b <=> i !> a |&| b i !< a | b|&|c <=> i !< a|b |&| a|c i !> a |&| b|c <=> i !> a|&|b | a|&|c i !> i | a => i !> a i !< i | a => i !> a i !< i |&| a => i !< a i !> i |&| a => true i !> i|&|a | b => i !> b i !< i|a |&| b => i !> a and i !< b Oh, yeah, there is a function type of course --which obeys a|c->b !< a->b !< a->b|d A->B !> x->x <=> (exists x. A !< x and B !> x) The words "covariant" and "contravariant" are mentioned, whatever they are. More at http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/~checkout~/merd/ merd/subtyping.me?content-type=text/plain and http://merd.sourceforge.net/types.png _______________________________________________ Haskell mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell