Matematyczny (kategoryczny) opis klas typów

14

Język funkcjonalny można postrzegać jako kategorię, w której jego obiektami są typy, a między nimi funkcjonują morfizmy.

Jak pasują klasy w tym modelu?

Zakładam, że powinniśmy brać pod uwagę tylko te implementacje, które spełniają ograniczenie większości klas typów, ale które nie są wyrażone w języku Haskell. Na przykład powinniśmy brać pod uwagę tylko te wdrożenia, Functordla których fmap id ≡ idi fmap f . fmap g ≡ fmap (f . g).

Czy istnieją jakieś inne teoretyczne podstawy dla klas typów (na przykład oparte na typowych obliczeniach lambda)?

Petr Pudlák
źródło
1
Możesz chcieć wyrazić się dokładniej na temat tego, czego chcesz model. Jeśli chcesz czegoś, co może rygorystycznie opisać założenia otwartego świata, zachowanie rozdzielczości instancji, interakcje różnych rozszerzeń GHC itd., Jest to bardziej skomplikowane niż wersja idealizowana. Podobnie zauważ, że dna są często ignorowane podczas omawiania Hask.
CA McCann,
4
Klasy typów można traktować jako podpisy (w sensie algebry uniwersalnej). Zbiór wszystkich podmiotów posiadających ten sam podpis (elementy tej samej klasy typu) jest różnorodny .
Dave Clarke,
1
@DaveClarke: Nie jest dla mnie od razu oczywiste, jak w ten sposób opisywać klasy na wyższych rodzajach, ale nie znam się na uniwersalnej algebrze i być może nie rozumiem korespondencji, o której myślisz ...
CA McCann,
1
@camccann: Nie jestem pewien, jak daleko posuwa się korespondencja. Z pewnością wydawało się to dobrym punktem wyjścia.
Dave Clarke,
2
@camccann: Po prostu zmień kategorię podstawową, nad którą definiujesz swoją algebrę: podstawowe klasy typów, takie jak num, są sygnaturami nad kategorią typów haskell (lub obiektów kategorii Hsk), klasy typów nad konstruktorami typów są algebrami nad kategorią funktorów od Hask do Hask. Zauważ, że algebra uniwersalna jest całkowicie objęta pojęciem algebry w teorii kategorii. Ponadto: Dave: powinieneś zamienić swój komentarz w odpowiedź.
cody

Odpowiedzi:

18

Jak pasują klasy w tym modelu?

Krótka odpowiedź brzmi: nie.

Ilekroć wprowadzasz w języku przymus, klasy typów lub inne mechanizmy polimorfizmu ad hoc, głównym problemem projektowym, z którym się stykasz, jest spójność .

Zasadniczo musisz upewnić się, że rozdzielczość klasy jest deterministyczna, aby dobrze napisany program miał jedną interpretację. Na przykład, jeśli możesz podać wiele instancji dla tego samego typu w tym samym zakresie, możesz potencjalnie napisać niejednoznaczne programy, takie jak to:

class Blah a where
   blah : a -> String 

instance Blah T where
   blah _ = "Hello"

instance Blah T where
   blah _ = "Goodbye"

v :: T = ...

main :: IO ()
main = print (blah v)  -- does this print "Hello" or "Goodbye"?

W zależności od wyboru przykład kompilator sprawia, blah vmógłby dorównać albo "Hello"albo "Goodbye". Dlatego znaczenie programu nie byłoby całkowicie zdeterminowane przez składnię programu, ale raczej mogło na niego wpływać arbitralne wybory dokonywane przez kompilator.

Rozwiązaniem tego problemu Haskell jest wymaganie, aby każdy typ miał co najwyżej jedną instancję dla każdej klasy. Aby to zapewnić, zezwala na deklaracje instancji tylko na najwyższym poziomie, a ponadto sprawia, że ​​wszystkie deklaracje są globalnie widoczne. W ten sposób kompilator może zawsze zasygnalizować błąd, jeśli zostanie złożona niejednoznaczna instancja.

Jednak uczynienie deklaracji widocznymi na całym świecie przełamuje złożoność semantyki. Aby odzyskać, należy podać semantykę opracowania dla języka programowania - to znaczy, jak pokazać, jak tłumaczyć programy Haskell na lepiej zachowujący się, bardziej kompozycyjny język.

To faktycznie pozwala ci również na kompilację klas - nazywa się to zwykle „tłumaczeniem dowodów” lub „transformacją słownikową” w kręgach Haskella i jest jednym z pierwszych etapów większości kompilatorów Haskell.

Klasy typów są również dobrym przykładem tego, w jaki sposób projektowanie języka programowania różni się od czystej teorii typów. Klasy typów są naprawdę niesamowitą funkcją językową, ale są dość źle wychowane z teoretycznego punktu widzenia. (Właśnie dlatego Agda w ogóle nie ma klas i dlatego Coq włącza je do infrastruktury heurystycznej wnioskowania).

Neel Krishnaswami
źródło
jaki jest drugi kandydat, który ma semantykę denotacyjną iyswim?
Ohad Kammar,
1
Niestety nie mam pojęcia.
Neel Krishnaswami,
Czy to zasługuje na dodatkowe pytanie?
Ohad Kammar
@NeelKrishnaswami: Czy masz pojęcie, jak pasują do tego moduły ML? A co z modułami Agdy (które ktoś mi wspomniał, są „pierwszej klasy”)?
Lii
1
@Lii: Moduły ML i rekordy Agdy zachowują się znacznie lepiej, ale jest to zbyt skomplikowane, aby wyjaśnić je w komentarzu - zadaj pytanie na ich temat, a ja (lub ktoś inny) wyjaśnię.
Neel Krishnaswami,