2016-12-07 45 views
7

Podobne stanowisko: How to disambiguate selector function?Dlaczego DuplicateRecordFields nie może mieć wnioskowania o typie?

https://ghc.haskell.org/trac/ghc/wiki/Records/OverloadedRecordFields/DuplicateRecordFields

Jednak nie wywnioskować typ argumentu, aby określić typ danych, lub w dowolny sposób odroczenia wyboru solver więzów.

To naprawdę denerwujące, że ta funkcja nie jest zaimplementowana. Próbowałem wyszukać wiele źródeł, ale nie mogłem znaleźć powodu, dla którego zdecydowałyby się nie wnioskować o typach.

Czy ktoś ma dobry powód? Czy to z powodu ograniczenia obecnego systemu typów?

+0

Czy można to w ogóle zrobić w przyszłym wydaniu GHC? – Larry

+0

Prawdopodobnie nie mogli znaleźć sposobu, aby to zadziałało. – immibis

Odpowiedz

9

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).