Po prostu wpisany rachunek lambda - Simply typed lambda calculus

Prostu wpisane rachunek lambda ( ), to forma teorii typów , jest wpisany interpretacja z rachunku lambda tylko jeden konstruktor typu ( ), która buduje typy funkcyjne . Jest to kanoniczny i najprostszy przykład typowanego rachunku lambda. Rachunek lambda z prostym typowaniem został pierwotnie wprowadzony przez Alonzo Church w 1940 roku jako próba uniknięcia paradoksalnych zastosowań rachunku lambda bez typowania i wykazuje wiele pożądanych i interesujących właściwości.

Termin typ prosty jest również używany w odniesieniu do rozszerzeń prostego rachunku lambda, takich jak iloczyny , koprodukty lub liczby naturalne ( System T ) lub nawet pełna rekurencja (jak PCF ). W przeciwieństwie do tego, systemy, które wprowadzają typy polimorficzne (takie jak System F ) lub typy zależne (takie jak Logical Framework ) nie są uważane za po prostu typowane . Te pierwsze, poza pełną rekurencją, są nadal uważane za proste, ponieważ kościelne kodowanie takich struktur może być wykonane przy użyciu tylko i odpowiednich zmiennych typu, podczas gdy polimorfizm i zależność nie.

Składnia

W tym artykule używamy i zmieniamy typy. Nieformalnie typ funkcji odnosi się do typu funkcji, które po podaniu danych wejściowych typu , generują dane wyjściowe typu . Zgodnie z konwencją, współpracownicy po prawej: czytamy jako .

Definiowanie typów zaczynamy od ustalenia zestawu typów bazowych , . Są one czasami nazywane typami atomowymi lub stałymi typu . Po naprawieniu składnia typów to:

.

Na przykład , generuje nieskończony zestaw typów zaczynających się od

Ustalamy również zestaw stałych term dla typów podstawowych. Na przykład możemy założyć typ bazowy nat , a terminem stałe mogą być liczby naturalne. W oryginalnym przedstawieniu Church użył tylko dwóch typów podstawowych: dla „typu propozycji” i dla „typu jednostek”. Typ nie ma stałych terminowych, natomiast ma jedną stałą termiczną. Często bierze się pod uwagę rachunek różniczkowy z tylko jednym typem podstawowym, zwykle .

Składnia prostego rachunku lambda jest zasadniczo składnią samego rachunku lambda. Piszemy, aby zaznaczyć, że zmienna jest typu . Składnia terminu w BNF to wtedy:

gdzie jest terminem stałym.

Czyli referencja do zmiennej , abstrakcje , aplikacja i stała . Odwołanie do zmiennej jest powiązane, jeśli znajduje się wewnątrz powiązania abstrakcji . Termin jest zamknięty, jeśli nie ma niezwiązanych zmiennych.

Porównaj to ze składnią rachunku lambda bez typu:

Widzimy, że w typowanym rachunku lambda każda funkcja ( abstrakcja ) musi określać typ swojego argumentu.

Zasady pisania

Aby zdefiniować zestaw dobrze wpisanych terminów lambda danego typu, zdefiniujemy relację typowania między terminami i typami. Najpierw wprowadzamy konteksty typowania lub środowiska typograficzne , które są zbiorami założeń typowania. Wpisując założenie ma formę , to znaczy ma typ .

Związek typowania wskazuje, że to określenie typu kontekstu . W tym przypadku mówi się, że jest dobrze wpisany (mający typ ). Instancje relacji typowania nazywane są osądami typowania . Ważność sądu typograficznego jest pokazana przez dostarczenie wyprowadzenia typograficznego , skonstruowanego przy użyciu reguł typowania (gdzie przesłanki nad linią pozwalają nam wyprowadzić wniosek poniżej linii). Rachunek lambda o prostym typie używa następujących reguł:

(1) (2)
(3) (4)

W słowach,

  1. Jeśli ma type w kontekście, wiemy, że ma type .
  2. Stałe terminowe mają odpowiednie typy podstawowe.
  3. Jeżeli w pewnym kontekście z konieczności typ , ma typ , to w tym samym kontekście, bez , ma typ .
  4. Jeśli w pewnym kontekście ma typ i ma typ , to ma typ .

Przykłady terminów zamkniętych, tj. terminów typowalnych w pustym kontekście, to:

  • Dla każdego typu termin (funkcja tożsamości/I-kombinator),
  • W przypadku typów termin (kombinator K) oraz
  • W przypadku typów termin (kombinator S).

Są to typizowane reprezentacje rachunku lambda podstawowych kombinatorów logiki kombinatorycznej .

Każdy typ ma przyporządkowane zamówienie, numer . Dla typów podstawowych ; dla typów funkcji, . Oznacza to, że kolejność typu mierzy głębokość strzałki najbardziej zagnieżdżonej w lewo. Stąd:

Semantyka

Interpretacje wewnętrzne i zewnętrzne

Ogólnie rzecz biorąc, istnieją dwa różne sposoby przypisywania znaczenia po prostu wpisane do rachunku lambda, jak do wpisywanych języków bardziej ogólnie, czasami nazywany nieodłącznym vs. zewnętrzny lub Kościół -Style vs. Curry -Style . Semantyka wewnętrzna / w stylu kościelnym przypisuje znaczenie tylko dobrze napisanym terminom, a dokładniej, przypisuje znaczenie bezpośrednio pochodnym typowania. Skutkuje to tym, że terminom różniącym się tylko adnotacjami typu można jednak przypisać różne znaczenia. Na przykład termin tożsamości na liczbach całkowitych i termin tożsamości na wartości logiczne mogą oznaczać różne rzeczy. (Klasyczne zamierzone interpretacje to funkcja tożsamości na liczbach całkowitych i funkcja tożsamości na wartościach logicznych.) W przeciwieństwie do tego, semantyka zewnętrzna/w stylu Curry przypisuje znaczenie pojęciom niezależnie od typowania, tak jak byłyby one interpretowane w języku nieopisanym. W tym widoku i oznacza to samo ( tj. to samo co ).

Rozróżnienie między wewnętrzną i zewnętrzną semantyką jest czasami związane z obecnością lub brakiem adnotacji w abstrakcjach lambda, ale ściśle mówiąc to użycie jest nieprecyzyjne. Możliwe jest zdefiniowanie semantyki w stylu Curry'ego na terminach z adnotacjami po prostu przez zignorowanie typów ( tj. poprzez wymazanie typu ), ponieważ możliwe jest nadanie semantyki w stylu kościelnym na terminach nieopatrzonych adnotacjami, gdy typy można wydedukować z kontekstu ( tj. , poprzez wnioskowanie o typie ). Zasadnicza różnica między podejściami wewnętrznymi i zewnętrznymi polega po prostu na tym, czy reguły typowania są postrzegane jako definiujące język, czy jako formalizm służący do weryfikacji właściwości bardziej prymitywnego języka bazowego. Większość różnych interpretacji semantycznych omówionych poniżej można zobaczyć z perspektywy Kościoła lub Curry'ego.

Teoria równań

Prosto typizowany rachunek lambda ma tę samą teorię równań równoważności βη, co nieopisany rachunek lambda , ale podlega ograniczeniom dotyczącym typu. Równanie redukcji beta

utrzymuje się w kontekście kiedykolwiek i , podczas gdy równanie redukcji eta

trzyma się zawsze i nie pojawia się jako wolny w .

Semantyka operacyjna

Podobnie semantyka operacyjna rachunku lambda z prostym typem może być ustalona tak, jak w przypadku rachunku lambda bez typu, przy użyciu funkcji call by name , call by value lub innych strategii oceny . Podobnie jak w przypadku każdego języka maszynowego, bezpieczeństwo typów jest podstawową właściwością wszystkich tych strategii oceny. Ponadto opisana poniżej właściwość silnej normalizacji oznacza, że ​​każda strategia oceny zakończy się na wszystkich prostych warunkach.

Semantyka kategoryczna

Prosto wpisane rachunek Lambda (z -equivalence) jest wewnętrzny język z kartezjańskim zamknięte kategorie (CCCS), jak to po raz pierwszy zauważony przez Lambek . Przy jakimkolwiek określonym CCC, podstawowymi typami odpowiedniego rachunku lambda są tylko obiekty , a terminy to morfizmy . I odwrotnie, każdy prosty typ rachunku lambda daje CCC, którego obiektami są typy, a morfizmy są klasami równoważności terminów.

Aby korespondencja była jasna, do powyższego zazwyczaj dodawany jest konstruktor typu dla produktu kartezjańskiego . Aby zachować kategoryczność iloczynu kartezjańskiego , dodaje się reguły typu dla parowania , rzutowania i członu jednostkowego . Biorąc pod uwagę dwa terminy i , termin ma typ . Podobnie, jeśli mamy wyraz , to istnieją terminy i gdzie odpowiadają rzutom iloczynu kartezjańskiego. Termin jednostkowy typu 1 jest zapisywany i wymawiany jako 'nil', jest obiektem końcowym . Podobnie rozszerzono teorię równań, dzięki czemu:

To ostatnie jest czytane jako „ jeśli t ma typ 1, to redukuje się do zera ”.

Powyższe można następnie przekształcić w kategorię, biorąc typy jako obiekty . W morfizmamirównoważne klasy par , gdzie x oznacza zmienną (typu ), a T jest terminem (typu ), które nie mają wolnych zmienne w tym, z wyjątkiem (opcjonalnie) x . Zamknięcie uzyskuje się jak zwykle poprzez curry i aplikację .

Dokładniej, między kategorią kartezjańskich kategorii zamkniętych a kategorią teorii lambda typu prostego istnieją funktory .

Powszechne jest rozszerzenie tego przypadku na zamknięte, symetryczne kategorie monoidalne, przy użyciu liniowego systemu typu . Powodem tego jest to, że CCC jest szczególnym przypadkiem zamkniętej symetrycznej kategorii monoidalnej, która jest zwykle uważana za kategorię zbiorów . Jest to dobre dla kładzenia podstaw teorii mnogości , ale bardziej ogólne toposy wydają się zapewniać lepsze podstawy.

Semantyka dowodowa

Rachunek lambda o prostym typowaniu jest ściśle powiązany z implikacyjnym fragmentem zdaniowej logiki intuicjonistycznej , tj. logiki minimalnej , poprzez izomorfizm Curry-Howarda : terminy odpowiadają dokładnie dowodom w dedukcji naturalnej , a typy zamieszkałe są dokładnie tautologiami logiki minimalnej.

Alternatywne składnie

Przedstawiona powyżej prezentacja nie jest jedynym sposobem zdefiniowania składni prostego rachunku lambda. Jedną z alternatyw jest całkowite usunięcie adnotacji typu (tak, aby składnia była identyczna z niewpisanym rachunkiem lambda), przy jednoczesnym upewnieniu się, że terminy są dobrze wpisane za pomocą wnioskowania o typie Hindley-Milner . Algorytm wnioskowania kończy się, brzmi i jest kompletny: za każdym razem, gdy termin można wpisać, algorytm oblicza jego typ. Dokładniej, to oblicza termin za główny typ , ponieważ często nieopisanych termin (jak ) może mieć więcej niż jeden typ ( , , itd., Które są wszystkie wystąpienia głównego typu ).

Inna alternatywna prezentacja prostego typu rachunku lambda opiera się na dwukierunkowym sprawdzaniu typów , które wymaga więcej adnotacji typu niż wnioskowanie Hindleya-Milnera, ale jest łatwiejsze do opisania. System typów jest podzielony na dwa osądy, reprezentujące zarówno sprawdzanie, jak i syntezę , odpowiednio pisemny i pisemny . Operacyjnie wszystkie trzy składniki , , i są danymi wejściowymi do oceny sprawdzającej , podczas gdy ocena syntezy przyjmuje tylko dane wejściowe i jako dane wejściowe, tworząc typ jako dane wyjściowe. Te osądy są wyprowadzane według następujących zasad:

[1] [2]
[3] [4]
[5] [6]

Zauważ, że reguły [1]–[4] są prawie identyczne z regułami (1)–(4) powyżej, z wyjątkiem starannego wyboru sądów sprawdzających lub syntezujących. Te wybory można wyjaśnić w następujący sposób:

  1. Jeśli jest w kontekście, możemy zsyntetyzować type for .
  2. Rodzaje stałych terminów są stałe i można je zsyntetyzować.
  3. Aby sprawdzić, czy ma typ w jakimś kontekście, rozszerzamy kontekst o i sprawdzamy, czy ma typ .
  4. Jeśli syntetyzuje typ (w pewnym kontekście) i sprawdza z typem (w tym samym kontekście), to syntetyzuje typ .

Zauważ, że reguły syntezy są odczytywane od góry do dołu, podczas gdy reguły sprawdzania są odczytywane od dołu do góry. W szczególności zwróć uwagę, że nie potrzebujemy adnotacji na temat abstrakcji lambda w regule [3], ponieważ typ zmiennej związanej można wywnioskować z typu, w którym sprawdzamy funkcję. Na koniec wyjaśniamy reguły [5] i [6] w następujący sposób:

  1. Aby sprawdzić , czy ma typ , wystarczy zsyntetyzować typ .
  2. Jeśli sprawdzane jest z typem , termin wyraźnie oznaczony adnotacją jest syntetyzowany .

Dzięki tym dwóm ostatnim regułom, które nakładają się na syntezę i sprawdzanie, łatwo zauważyć, że każdy dobrze wpisany, ale nieopisany termin może być sprawdzony w systemie dwukierunkowym, o ile wstawimy „wystarczającą” adnotację typu. W rzeczywistości adnotacje są potrzebne tylko przy β-redeksach.

Generalne obserwacje

Biorąc pod uwagę standardową semantykę, po prostu typowany rachunek lambda jest silnie normalizujący : to znaczy, że dobrze wpisane terminy zawsze redukują się do wartości, tj . abstrakcji. Dzieje się tak, ponieważ rekurencja nie jest dozwolona przez reguły typowania: nie można znaleźć typów dla kombinatorów stałoprzecinkowych i terminu pętli . Rekurencję można dodać do języka, używając specjalnego operatora typu lub dodając ogólne typy rekurencyjne , chociaż oba eliminują silną normalizację.

Ponieważ jest to silnie normalizujące, rozstrzyga się, czy po prostu wpisany program rachunku lambda zatrzyma się, czy nie: w rzeczywistości zawsze się zatrzymuje. Możemy zatem wnioskować, że język nie jest zupełny pod względem Turinga .

Ważne wyniki

  • Tait wykazał w 1967 roku, że -redukcja mocno się normalizuje . W konsekwencji równoważność jest rozstrzygalna . Statman wykazał w 1977 roku, że problem normalizacji nie jest elementarną rekurencją , co później uprościł Mairson (1992). Problem jest znany w zestawie z hierarchią Grzegorczyk . Czysto semantyczny dowód normalizacji (patrz normalizacja przez ocenę ) podali Berger i Schwichtenberg w 1991 roku.
  • Unifikacja problemem -equivalence jest nierozstrzygalny. Huet pokazał w 1973 roku, że unifikacja trzeciego rzędu jest nierozstrzygalna, co zostało ulepszone przez Baxtera w 1978 roku, a następnie przez Goldfarba w 1981 roku, pokazując, że unifikacja drugiego rzędu jest już nierozstrzygnięta. Dowód, że dopasowanie wyższego rzędu (unifikacja, w której tylko jeden termin zawiera zmienne egzystencjalne) jest rozstrzygalny, został ogłoszony przez Colina Stirlinga w 2006 roku, a pełny dowód opublikowano w 2009 roku.
  • Liczby naturalne możemy zakodować za pomocą terminów typu ( liczby kościelne ). Schwichtenberg wykazał w 1976 roku, że dokładnie rozszerzone wielomiany są reprezentowane jako funkcje nad cyframi kościelnymi; są to z grubsza wielomiany zamknięte operatorem warunkowym.
  • Pełny wzór od jest przez interpretacji podstawowych typów w zestawach i typów funkcji przez odbiornik-theoretic miejsca funkcyjnego . Friedman wykazał w 1975 roku, że ta interpretacja jest kompletna dla -równoważności, jeśli typy bazowe są interpretowane przez zbiory nieskończone. Statman wykazał w 1983 roku, że -równoważność to maksymalna równoważność, która jest zwykle niejednoznaczna , tj. zamknięta pod podstawieniami typów ( Typowe twierdzenie Statmana o niejednoznaczności ). Konsekwencją tego jest to, że zachodzi własność modelu skończonego , tj. zbiory skończone są wystarczające do rozróżnienia terminów, które nie są identyfikowane przez -równoważność.
  • Plotkin wprowadził relacje logiczne w 1973 roku, aby scharakteryzować elementy modelu, które można zdefiniować za pomocą terminów lambda. W 1993 roku Jung i Tiuryn ​​wykazali, że ogólna forma relacji logicznej (relacje logiczne Kripkego o zmiennej arności) dokładnie charakteryzuje definiowalność lambda. Plotkin i Statman wywnioskowali, że rozstrzyga się, czy dany element modelu wygenerowanego ze zbiorów skończonych jest definiowalny za pomocą wyrażenia lambda ( przypuszczenie Plotkina-Statmana ). Ta hipoteza okazała się fałszywa przez Loadera w 1993 roku.

Uwagi

Bibliografia

Zewnętrzne linki