> > To solve this problem I just made them all instances of a class with a
> > gameId function. Still, not ideal.
>> That gives you a getter function but you would then need an extra setter
> function.
But there is no need to have two names for each label when you
only want to talk about two ways of using any given label (untested
code here, but I've used something similar in practice, and similar
patterns are in use in various libraries, I think):
-- what we expect from record field labels
data Label t r = Label { get :: r -> t, put :: t -> r -> r }
-- some record, with internal field labels
data R a b = R { field_x :: a, field_y :: b }
emptyR = R{}
-- and its externally visible field labels
x = Label { get = field_x, put = \t r->r{field_x=t} }
y = Label { get = field_y, put = \t r->r{field_y=t} }
-- example
r = (x `put` True) $ (y `put` "Hi") $ emptyR
r1 = (x `put` False) r
main = print (get y r,get x r,get x r1)
-- some might prefer something like (:=) for put and (:?) for get..
-- (x := False) r
-- x :? r1
-- this uses extraneous internal field names, which I'd like
-- to hide (losing direct pattern matching), but no overloading;
-- so you're free to overload the field labels for selection from
-- different record types (or perhaps for recursive selection from
-- nested records?);
-- claus