Widzę tutaj kilka interesujących dyskusji na temat pisania statycznego i dynamicznego. Generalnie wolę wpisywanie statyczne, ze względu na sprawdzanie typów kompilacji, lepiej udokumentowany kod itp. Zgadzam się jednak, że zaśmiecają one kod, jeśli są robione tak, jak robi to na przykład Java.
Więc zaraz zacznę budować własny funkcjonalny język stylów, a wnioskowanie o typie jest jedną z rzeczy, które chcę wdrożyć. Rozumiem, że to duży temat i nie próbuję tworzyć czegoś, czego wcześniej nie robiono, tylko podstawowe wnioskowanie ...
Jakieś wskazówki, co przeczytać, a które pomogą mi w tym? Najlepiej coś bardziej pragmatycznego / praktycznego w przeciwieństwie do bardziej teoretycznych tekstów teorii kategorii / teorii typów. Jeśli istnieje tekst do dyskusji na temat implementacji, zawierający struktury danych / algorytmy, byłoby to po prostu cudowne.
Odpowiedzi:
Znalazłem następujące zasoby pomocne w zrozumieniu wnioskowania o typie, w kolejności rosnącej trudności:
Ponieważ jednak najlepszym sposobem uczenia się jest robienie tego, zdecydowanie sugeruję implementację wnioskowania o typie dla języka funkcjonalnego zabawki poprzez wykonanie zadania domowego z kursu języków programowania.
Polecam te dwie dostępne prace domowe w ML, które możesz wykonać w mniej niż jeden dzień:
Te zadania pochodzą z bardziej zaawansowanego kursu:
Wdrażanie MiniML
Typy polimorficzne, egzystencjalne, rekurencyjne (PDF)
Dwukierunkowe sprawdzanie typów (PDF)
Podtytuł i obiekty (PDF)
źródło
Szkoda, że duża część literatury na ten temat jest bardzo bogata. Ja też byłem na twoim miejscu. Pierwsze wprowadzenie do tematu dostałem z Języki programowania: aplikacje i interpretacja
http://www.plai.org/
Spróbuję podsumować abstrakcyjną ideę, a następnie szczegóły, które nie były dla mnie od razu oczywiste. Po pierwsze, można pomyśleć o wnioskowaniu o typie o generowaniu, a następnie rozwiązywaniu ograniczeń. Aby wygenerować ograniczenia, należy powtórzyć drzewo składni i wygenerować jedno lub więcej ograniczeń w każdym węźle. Na przykład, jeśli węzeł jest
+
operatorem, wszystkie operandy i wyniki muszą być liczbami. Węzeł, który stosuje funkcję, ma ten sam typ co wynik funkcji i tak dalej.W przypadku języka bez
let
, możesz ślepo rozwiązać powyższe ograniczenia przez podstawianie. Na przykład:tutaj możemy powiedzieć, że warunek instrukcji if musi być logiczny, a typ instrukcji if jest taki sam, jak typ jej klauzul
then
ielse
. Ponieważ znamy liczby1
i2
jesteśmy liczbami, przez podstawienie wiemy, żeif
stwierdzenie jest liczbą.Tam, gdzie robi się nieprzyjemnie i czego przez chwilę nie mogłem zrozumieć, to niech:
Tutaj mamy powiązanie
id
z funkcją, która zwraca wszystko, co przekazałeś, inaczej znaną jako funkcja tożsamości. Problem polega na tym, że typ parametru funkcjix
jest inny przy każdym użyciuid
. Drugaid
to funkcja typua -> a
, gdziea
może być wszystko. Pierwsza jest typowa(a -> a) -> (a -> a)
. Jest to znane jako let-polimorfizm. Kluczem jest rozwiązanie więzów w określonej kolejności: najpierw rozwiąż ograniczenia dla definicjiid
. To będziea -> a
. Następnie świeże, oddzielne kopie typuid
można podstawić do ograniczeń dla każdego miejscaid
, na przykłada2 -> a2
ia3 -> a3
.Nie było to łatwo wyjaśnione w zasobach internetowych. Wspomną o algorytmie W lub M, ale nie o tym, jak działają w zakresie rozwiązywania ograniczeń, ani dlaczego nie działa on na polimorfizm let: każdy z tych algorytmów wymusza uporządkowanie rozwiązywania ograniczeń.
Uważam, że ten zasób jest niezwykle pomocny w łączeniu algorytmów W, M i ogólnej koncepcji generowania i rozwiązywania ograniczeń razem. Jest trochę gęsty, ale lepszy niż wiele:
http://www.cs.uu.nl/research/techreps/repo/CS-2002/2002-031.pdf
Wiele innych artykułów też jest fajnych:
http://people.cs.uu.nl/bastiaan/papers.html
Mam nadzieję, że pomoże to wyjaśnić nieco mroczny świat.
źródło
Oprócz Hindley Milner dla języków funkcjonalnych, innym popularnym podejściem do wnioskowania o typie dla języka dynamicznego jest
abstract interpretation
.Idea abstrakcyjnej interpretacji polega na napisaniu specjalnego interpretera dla języka, zamiast utrzymywać środowisko konkretnych wartości (1, false, closure), działa na abstrakcyjnych wartościach, czyli typach (int, bool itp.). Ponieważ interpretuje program na wartościach abstrakcyjnych, dlatego nazywa się to interpretacją abstrakcyjną.
Pysonar2 to elegancka implementacja abstrakcyjnej interpretacji dla Pythona. Jest używany przez Google do analizy projektów w Pythonie. Zasadniczo służy
visitor pattern
do wysyłania wywołania oceny do odpowiedniego węzła AST. Funkcja gościatransform
akceptuje wartość,context
w której zostanie oceniony bieżący węzeł, i zwraca typ bieżącego węzła.źródło
Typy i języki programowania Benjamin C. Pierce
źródło
Lambda the Ultimate, zaczynając tutaj .
źródło