
Sorry about sending the previous message unfinished, and with the final line downright wrong. (Unfamiliar new desktop, grumble, fulminate...) Continuing: With asymmetric merging, this function f x = x { l <- (3::Int) } would have type r -> (l::Int | r) regardless of whether r already had an l field. The one explicitly added by f would take precedence. Changing the tentative syntax a little, we could unify the record creation and record updating syntax. r1 = ( foo = (), bar = 'q' ) r2 = ( bar = "", baz = const ) g x = ( foo = id, qux = True | r1 | r2 | x ) -- g ( qux = LT, quux = EQ ) -- = ( foo = id, qux = True, bar = 'q', baz = const, quux = EQ ) As long as the higher-precedence side of the asymmetric merge (e.g. the part to the left of any '|' in the above example) has a fixed set of field labels, the types don't get too hairy. - Tom