[Haskell-cafe] Another idea for record field selection and better
namespace management
Brian Hulley
brianh at metamilk.com
Fri Jan 27 05:22:33 EST 2006
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.
More information about the Haskell-Cafe
mailing list