Good idea, there’s definitely a more concise way to lay it out.
The baseline proposal is to extend the DataKinds
type-level machinery, which currently includes Symbol
s, Char
s and Natural
s, with a specialized dictionary, called Fields
.
data Field a = Symbol := a
data Fields a
Fields
is an ordered dictionary from unique Symbol
s to types. It is housed in a separate module, GHC.TypeFields
, which also provides at least the following set of type families:
type family Empty :: Fields a
-- Fails on duplicate insertion.
-- Should only allow a subset of characters in `Symbol`s to support
-- nested access.
type family Insert (k :: Symbol) (v :: a) (xs :: Fields a) :: Fields a
type family Lookup (k :: Symbol) (v :: a) (xs :: Fields a) :: Maybe a
type family Size (xs :: Fields a) :: Nat
-- Fails when no such symbol exists.
type family Index (k :: Symbol) (xs :: Field a) :: Nat
For construction and display of Fields
an additional bit of type-level syntax is necessary, which can mirror standard type-level lists . For future compatibility it could be gated behind an extension.
'{} -- On construction same as `Empty`
'{a := b, c := d} -- On construction same as `Insert a b (Insert c d Empty)`
Users would then be able to create their own datatypes outside of base
that use said dictionary to enforce certain type-level expectations.
“records” in the topic name comes from the fact that using an immutable array this way fully overlaps with Haskell98 record syntax feature-wise. Nesting is described to show that dot-notation and the like can be added on top on demand, which is superior to the current approach of creating entire language extensions to the record syntax. Anything involving mutation (including FFI) is too “yet another thing this approach does right”, since it requires no runtime conversions.
And yes, this is pretty much a blind retread of the Row Polymorphism proposal. From my perspective it just doesn’t look like something that needs changes to the type resolution (unless of course writing built-in type families is a whole journey I’m unaware of).