... | ... | @@ -3,10 +3,10 @@ |
|
|
|
|
|
Here be dragons. This page describes implementation details and progress on the implementation of [the overloaded record fields plan](records/overloaded-record-fields/plan). Development of the extension is taking place on forks of the [ ghc](https://github.com/adamgundry/ghc) and [ packages-base](https://github.com/adamgundry/packages-base) repositories (on branch 'overloaded-record-fields').
|
|
|
|
|
|
## Upcoming changes
|
|
|
## The basic idea
|
|
|
|
|
|
|
|
|
Typechecking a record datatype will still generates record selectors, but their names contain the name of their type. Additionally, a dictionary function (for the `Has` instance) is generated. Thus
|
|
|
Typechecking a record datatype still generates record selectors, but their names have a `$sel` prefix and end with the name of their type. Additionally, a dictionary function (for the `Has` instance) is generated. Thus
|
|
|
|
|
|
```wiki
|
|
|
data T = MkT { x :: Int }
|
... | ... | @@ -16,21 +16,43 @@ data T = MkT { x :: Int } |
|
|
generates
|
|
|
|
|
|
```wiki
|
|
|
$sel_x_T :: T -> Int -- record selector (used to be called `x`)
|
|
|
$sel_x_T :: T -> Int -- record selector (used to be called `x`)
|
|
|
$df_x_T :: Has T "x" Int -- dictionary function (coerced selector)
|
|
|
```
|
|
|
|
|
|
## The naming of cats
|
|
|
|
|
|
The `dcFields` field of `DataCon.DataCon` (constructor `MkData`) stores a list of `FastString` field names, rather than `Name`s.
|
|
|
|
|
|
The `AvailTC Name [Name] [OccName]` constructor of `AvailInfo` represents a type and its pieces that are in scope. Record fields are now stored in a separate list (the third argument). Every field should have a corresponding selector (in the second argument). Since we have the name of the type (the first argument), we can find the selector corresponding to a field. Similar changes are required to the `IEThingWith` constructor of `IE`, which represents a thing that can be imported or exported.
|
|
|
|
|
|
The `AvailTC` constructor of `Avail.AvailInfo` represents a type and its pieces that are in scope. Record fields are stored in a separate list (rather than bundled in with data constructors and class methods), which contains the `FastString` field name, and perhaps the names of the record selector and dictionary function.
|
|
|
|
|
|
The `Parent` type has an extra constructor `FldParent Name OccName` that stores the parent `Name` and the field `OccName`. The `GlobalRdrElt` (`GRE`) for a field stores the selector name directly, and uses the `FldParent` constructor to store the field. Thus a field `foo` of type `T` gives rise to two entries in the `GlobalRdrEnv`:
|
|
|
|
|
|
Similarly, the `RdrName.Parent` type has an extra constructor `FldParent` which stores the field name (and possibly the dfunid). Thus it is easy to tell whether a `RdrName.GlobalRdrElt` (`GRE`) is a field. In this case, the name of the `GRE` is the selector function.
|
|
|
```wiki
|
|
|
$sel_foo_T |-> GRE $sel_foo_T (ParentIs T) LocalDef
|
|
|
foo |-> GRE $sel_foo_T (FldParent T foo) LocalDef
|
|
|
```
|
|
|
|
|
|
|
|
|
Note that the `OccName` used when adding a GRE to the environment now depends on the parent field: for `FldParent` it is the field rather than the selector name.
|
|
|
|
|
|
|
|
|
The `dcFields` field of `DataCon` stores a list of
|
|
|
|
|
|
```wiki
|
|
|
type FieldLabel = (OccName, Name)
|
|
|
```
|
|
|
|
|
|
|
|
|
where the first component is the field and the second is the selector function.
|
|
|
|
|
|
|
|
|
Where an AST representation type (e.g. `HsRecField` or `ConDeclField`) contained an argument of type `Located id` for a field, it now stores a `Located RdrName` for the label and `Maybe id` for the selector. The parser supplies `Nothing` for the selector; it is filled in by the renamer (by `rnHsRecFields1` in `RnPat`, and `rnField` in `RnTypes`). Partial functions are provided to extract the `Located id`, but they will panic if called on not-yet-renamed syntax.
|
|
|
|
|
|
## Next steps
|
|
|
|
|
|
|
|
|
The `HsExpr.HsExpr` type has an extra constructor `HsOverloadedRecFld FastString`. When `-XOverloadedRecordFields` is enabled, and the renamer encounters `HsVar "x"` where `x` refers to multiple `GRE`s that are all record fields, it replaces it with `HsOverloadedRecFld "x"`. There needs to be a similar constructor for non-overloaded projections, so that we can pretty-print the field name but store the selector name.
|
|
|
The `HsExpr.HsExpr` type has an extra constructor `HsOverloadedRecFld OccName`. When `-XOverloadedRecordFields` is enabled, and the renamer encounters `HsVar "x"` where `x` refers to multiple `GRE`s that are all record fields, it replaces it with `HsOverloadedRecFld "x"`. There needs to be a similar constructor for non-overloaded projections, so that we can pretty-print the field name but store the selector name.
|
|
|
|
|
|
|
|
|
When the typechecker sees `HsOverloadedRecFld x` it emits a wanted constraint `Has alpha x beta` and returns type `alpha -> beta` where `alpha` and `beta` are fresh unification variables.
|
... | ... | |