1. I like the general idea---in particular:
- backwards compatibility is very important to me as I make extensive use of records in all my code,
2. I would propose that we simplify things further, and provide just one class for overloading:
class Field (name :: Symbol)
rec rec'
field field'
| name rec -> field
, name rec' -> field'
, name rec field' -> rec'
, name rec' field -> rec
where
field :: Functor f => Proxy name -> (field -> f field') ->
(rec -> f rec')
I don't think we need to go into "lenses" at all, the `field` method simply provides a functorial
update function similar to `mapM`. Of course, one could use the `lens` library to
get more functionality but this is entirely up to the programmer.
When the ORF extension is enabled, GHC should simply generate an instance of the class,
in a similar way to what the lens library does.
3. I like the idea of `#x` desugaring into `field (Proxy :: Proxy "x")`, but I don't like the concrete symbol choice:
- # is a valid operator and a bunch of libraries use it, so it won't be compatible with existing code.
- @x might be a better choice; then you could write things like:
view @x rec
set @x 3 rec
over @x (+2) rec
- another nice idea (due to Eric Mertens, aka glguy), which allows us to avoid additional special syntax is as follows:
- instead of using special syntax, reuse the module system
- designate a "magic" module name (e.g., GHC.Records)
- when the renamer sees a name imported from that module, it "resolves" the name by desugaring it into whatever we want
- For example, if `GHC.Records.x` desugars into `field (Proxy :: Proxy "x")`, we could write things like this:
import GHC.Records as R
view R.x rec
set R.x 3 rec
over R.x (+2) rec
-Iavor