
Here is a simple concrete proposal: Nonextensible records with polymorphic selectors. ================================================= 1. Introduce a built-in class Label, whose members are strings at the type level. We need a notation for them; I will use double single quotes, so ''string'' is automatically an instance of Label, and you can't define other instances. 2. Define a class (in a library somewhere) class Label n => Contains r n where type field r n :: * select :: r -> n -> field r n update :: r -> n -> field r n -> r 3. Declarations with field labels such as data C = F {l1 :: t1, l2 :: t2} | G {l2 :: t2} are syntactic sugar for data C = F t1 t2 | G t2 instance Contains C ''l1'' where field C ''l1'' = t1 select (F x y) _ = x update (F x y) _ x' = F x' y instance Contains C ''l2'' where field C ''l2'' = t2 select (F x y) _ = y select (G y) _ = y update (F x y) _ y' = F x y' update (G y) _ y' = G y' 4. Selector functions only need to be defined once, however many types they are used in l1 :: Contains r ''l1'' => r -> field r ''l1'' l1 = select r (undef ::''l1'') l2 :: Contains r ''l2'' => r -> field r ''l2'' l2 = select r (undef ::''l2'') 5. Constructors are exactly as before 6. Updates such as r {l1 = x} are syntactic sugar for update r (undef::''l1'') x ===================================================== This has the advantage that the extension to Haskell is fairly small, and it's compatible with existing user code, but if we later decide we want extensible records, we need only add a type function to order Label lexicographically. Barney.