|
|
# Overloaded record fields: a modest proposal
|
|
|
# `OverloadedRecordFields`: design overview
|
|
|
|
|
|
|
|
|
This is an attempt to redesign and clarify the design of the [OverloadedRecordFields](records/overloaded-record-fields) extension, in order to develop a plan for implementation. It has benefited from the extensive discussion surrounding [Nikita Volkov's record library](records/volkov). The following design choices are not set in stone, but are intended as a concrete proposal for further discussion. For reference, here is the [previous design](records/overloaded-record-fields/design).
|
|
|
|
|
|
[Implementation notes here](records/overloaded-record-fields/implementation).
|
|
|
|
|
|
|
|
|
See also the [ high-level summary of the current plan on the Well-Typed blog](http://www.well-typed.com/blog/2015/03/overloadedrecordfields-revived/).
|
|
|
|
... | ... | @@ -31,34 +29,34 @@ Bare field names in expressions refer to the selector function only if unambiguo |
|
|
|
|
|
Once we have overloaded labels, we need [a little typeclass magic](records/overloaded-record-fields/magic-classes) to allow overloaded labels to refer to record fields.
|
|
|
|
|
|
## Anonymous records
|
|
|
## Summary
|
|
|
|
|
|
|
|
|
While we might choose to add anonymous records later, they are not central to the design. In particular, this means that
|
|
|
We propose three essentially orthogonal additions to GHC:
|
|
|
|
|
|
- all existing features of Haskell datatypes, such as multiple constructors, strictness and unpacking, are supported unchanged;
|
|
|
1. an extension `DuplicateRecordFields` to permit the same field name to be used multiple times in the same module;
|
|
|
1. an extension `OverloadedLabels` to enable the `#x` syntax, interpreted with the `IsLabel` typeclass;
|
|
|
1. typeclasses with special-purpose constraint solving behaviour to enable polymorphism over record fields.
|
|
|
|
|
|
- abstraction and representation hiding work just as in normal Haskell: if a field selector is not exported, client code cannot observe it;
|
|
|
|
|
|
- application code can use `DuplicateRecordFields` even with libraries that do not;
|
|
|
The `OverloadedRecordFields` extension is then defined as the combination of `OverloadedLabels` and `DuplicateRecordFields`.
|
|
|
|
|
|
- no new declaration syntax is added.
|
|
|
|
|
|
## Summary
|
|
|
These are all useful independently, but complement each other:
|
|
|
|
|
|
- `DuplicateRecordFields` is perfectly sensible without `OverloadedLabels`: it allows duplicate field names provided they are not used ambiguously.
|
|
|
- `OverloadedLabels` uses the special typeclasses through the instance for `IsLabel x (r -> a)`, but is also useful when used at other types (e.g. we could give an instance `IsLabel x (Proxy x)` to allow implicit values to represent Symbol proxies).
|
|
|
- Without either of the extensions, the special typeclasses allow users to write code that works for all datatypes with particular fields (albeit without a nice built-in syntax).
|
|
|
|
|
|
We propose three essentially orthogonal additions to GHC:
|
|
|
### Anonymous records
|
|
|
|
|
|
1. `HasField` and `FieldUpdate` typeclasses, with special-purpose constraint solving behaviour (just like `Coercible`, we do not require a special extension to enable this, as its effect is limited to code that imports the relevant module);
|
|
|
1. an extension `OverloadedLabels` to enable the `#x` syntax, interpreted with the `IsLabel` typeclass;
|
|
|
1. an extension `DuplicateRecordFields` to permit the same field name to be used multiple times in the same module.
|
|
|
|
|
|
While we might choose to add anonymous records later, they are not central to the design. In particular, this means that
|
|
|
|
|
|
The `OverloadedRecordFields` extension is then defined as the combination of `OverloadedLabels` and `DuplicateRecordFields`.
|
|
|
- all existing features of Haskell datatypes, such as multiple constructors, strictness and unpacking, are supported unchanged;
|
|
|
|
|
|
- abstraction and representation hiding work just as in normal Haskell: if a field selector is not exported, client code cannot observe it;
|
|
|
|
|
|
These are all useful independently, but complement each other:
|
|
|
- application code can use `DuplicateRecordFields` even with libraries that do not;
|
|
|
|
|
|
- Without either of the extensions, the special typeclasses allow users to write code that works for all datatypes with particular fields (albeit without a nice built-in syntax).
|
|
|
- `OverloadedLabels` uses the special typeclasses through the instance for `IsLabel x (r -> a)`, but is also useful when used at other types (e.g. we could give an instance `IsLabel x (Proxy x)` to allow implicit values to represent Symbol proxies).
|
|
|
- `DuplicateRecordFields` is perfectly sensible without `OverloadedLabels`: it allows duplicate field names provided they are not used ambiguously. |
|
|
- no new declaration syntax is added. |