Hi -

To avoid the problems with so many names being put into a module's namespace, data declarations could implicitly define sub-modules and class/instance declarations as follows:

module M where
     data Foo = FooCon {x : Int}

would declare (as seen from inside M)

    Foo, Foo.FooCon, Foo.x

and would further declare x and FooCon as instances of a global value type-class and constructor type class as follows (where //varid denotes the global typeclass corresponding to (a record field called) varid, and //conid denotes the global typeclass corresponding to the constructor conid)

    class //x a b where
         x : a -> b

    instance //x Foo Int where
        x Foo.FooCon{x=p} = p

    class //FooCon a b where
         FooCon : a -> b

    instance //FooCon Int Foo where
        FooCon = Foo.FooCon

The class declarations (generated by the compiler) are global, and there is no danger of conflicts with user class declarations because of the // prefix. The instance declarations (also generated by the compiler) would be inserted into the module itself.

This would give at least three advantages:

1) The same names could be used for fields in more than one data declaration and these would be resolved using the well known type class mechanism

2) Some exciting new programming paradigms become instantly available due to the extension of allowing constructor type classes, namely we could then get the effect of extensible data types eg

       data Col1 a = One a
       data Col2 a = One a | Two a

       useOne :: ( //One col a) => col -> a
       useOne (One x) = x

This is a lot more powerful than just OOP, because we could have different views of a data type, selecting out those components which are relevant to particular operations:

data Element = TerminalPunct | TerminalValue | NonTerminal | Push | Pop
       data Action = Push | Pop
       data Insertion = TerminalValue | NonTerminal | Push

without having to artificially construct various injections...

3) If x is a record field, then because a typeclass and instance has been automatically generated, (x p) already uses the type of p to determine which overloaded x to use, so all that remains is to introduce a sugar to get a form of function application syntax that binds stronger than prefix application. I suggest p^x === (x p)
It is still possible to be completely explicit, by writing P.x p or p^P.x

I think this solves all the problems that I had with the value space idea, and is also a fairly conservative extension to Haskell as it stands at the moment, except I wonder if it is possible to implement type classes for constructors?

Regards, Brian.



_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe

Reply via email to