Będziesz zainteresowany OverloadedRecordFields
, który jest nadal wdrażany.
Obecna implementacja została celowo okaleczona, aby nie wprowadzać zbyt wiele nowych rzeczy naraz. Wnioskowanie typów projekcji rekordu okazuje się otwierać nieprzyjemną puszkę robaków (do której wyżej wspomniane adresy rozszerzeń).
Rozważmy następujący interakcji GHCi
ghci> data Record1 = Record1 { field :: Int }
ghci> data Record2 = Record2 { field :: Bool }
ghci> :t field
Co należy rodzaj field
być teraz? W jakiś sposób potrzebujemy sposobu na uchwycenie pojęcia "jakiegokolwiek rekordu z polem o nazwie field
". W tym celu OverloadedRecordFields
wprowadza nowy wbudowany w klasie typu
Nowy moduł GHC.Records
definiuje następujące:
class HasField (x :: k) r a | x r -> a where
getField :: r -> a
HasField x r a
ograniczenie stanowi fakt, że x
jest dziedziną typu a
przynależności do rekordowego typu: r
. Metoda getField
udostępnia funkcję selektora rekordów getField
.
Następnie, z powyższego przykładu, jest tak, jakby następujące przykłady zostały magicznie wygenerowane przez GHC (w rzeczywistości to nie jest tak naprawdę, co się stanie, ale jest to dobre pierwsze przybliżenie).
instance HasField "field" Record1 Int where
getField (Record1 f) = f
instance HasField "field" Record2 Bool where
getField (Record2 f) = f
Jeśli są Państwo zainteresowani, proponuję przeczytać propozycję. Inną cechą, o której nie wspomniałem, jest klasa IsLabel
. Gdy wszystko to zostanie zaimplementowane (i kilka więcej dla aktualizacji rekordów), czekam na możliwość get my lenses for free (mogę więc przestać deklarować nazwy pól zaczynając od podkreślenia i włączając TemplateHaskell
dla makeLenses
).
Czy można to w ogóle zrobić w przyszłym wydaniu GHC? – Larry
Prawdopodobnie nie mogli znaleźć sposobu, aby to zadziałało. – immibis