You will be interested in OverloadedRecordFields
which is still being implemented.
The current implementation is intentionally crippled, so as to not introduce too much new stuff all at once. Inferring the record projection types turns out to open a nasty can of worms (which the aforementioned extension addresses).
Consider the following GHCi interaction
ghci> data Record1 = Record1 { field :: Int }
ghci> data Record2 = Record2 { field :: Bool }
ghci> :t field
What should the type of field
be now? Somehow, we need a way to capture the notion of "any record with a field called field
". To this end, OverloadedRecordFields
introduces a new built-in type class
The new module GHC.Records
defines the following:
class HasField (x :: k) r a | x r -> a where
getField :: r -> a
A HasField x r a
constraint represents the fact that x
is a field of
type a
belonging to a record type r
. The getField
method gives the
record selector function.
Then, from our example above, it is as if the following instances were magically generated by GHC (in fact that is not actually what will happen, but it is a good first approximation).
instance HasField "field" Record1 Int where
getField (Record1 f) = f
instance HasField "field" Record2 Bool where
getField (Record2 f) = f
If you are interested, I recommend reading the proposal. The other feature I haven't mentioned is the IsLabel
class. Once all of this is implemented (and some more for updating records) I look forward to being able to get my lenses for free (so I can stop declaring field names starting with an underscore and enabling TemplateHaskell
for makeLenses
).
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…