
Hello,
I just read through Adam's proposal and here is my take:
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,
- for me, anonymous records are fairly low priority
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
On Fri, Jan 23, 2015 at 2:25 AM, Adam Gundry
On 23/01/15 10:17, Simon Marlow wrote:
On 23/01/2015 04:12, Johan Tibell wrote:
On Wed, Jan 21, 2015 at 5:48 PM, Simon Marlow
mailto:marlowsd@gmail.com> wrote: On 21/01/2015 16:01, Johan Tibell wrote:
My thoughts mostly mirror those of Adam and Edward.
1) I want something that is backwards compatible.
Backwards compatible in what sense? Extension flags provide backwards compatibility, because you just don't turn on the extension until you want to use it. That's how all the other extensions work; most of them change syntax in some way or other that breaks existing code.
In this case in the sense of avoiding splitting code into a new-Haskell vs old-Haskell. This means that existing records should work well (and ideally also get the improved name resolution when used in call sites that have the pragma enabled) in the new record system.
I understand that position, but it does impose some pretty big constraints, which may mean the design has to make some compromises. It's probably not worth discussing this tradeoff until there's actually a concrete proposal so that we can quantify how much old code would fail to compile and the cost of any compromises.
In this spirit, I've started to prepare a concrete proposal for a revised OverloadedRecordFields design, based on recent feedback:
https://ghc.haskell.org/trac/ghc/wiki/Records/OverloadedRecordFields/Redesig...
This would not necessarily include anonymous records at first, but they do fit nicely as a potential later extension, and it would work well with a slightly amended version of the record library in the meantime. I'd be very interested to hear what you think of this.
Also, if someone would be prepared to flesh out a proposal based on the anonymous records idea, that might be a useful point of comparison.
Adam
-- Adam Gundry, Haskell Consultant Well-Typed LLP, http://www.well-typed.com/ _______________________________________________ ghc-devs mailing list ghc-devs@haskell.org http://www.haskell.org/mailman/listinfo/ghc-devs