O rany, cieszę się, że mogę odpowiedzieć na to pytanie najlepiej, jak potrafię. Mam nadzieję, że potrafię odpowiednio uporządkować myśli.
Jak wspomniano @Doval i pytający wskazał (choć niegrzecznie), tak naprawdę nie masz systemu typów. Masz system dynamicznych kontroli za pomocą znaczników, który jest ogólnie znacznie słabszy, a także znacznie mniej interesujący.
Pytanie „co to jest system typów” może być dość filozoficzne i moglibyśmy wypełnić książkę różnymi punktami widzenia na ten temat. Ponieważ jednak jest to strona dla programistów, postaram się zachować moją odpowiedź tak praktyczną, jak to możliwe (i naprawdę, typy są niezwykle praktyczne w programowaniu, pomimo tego, co niektórzy mogą myśleć).
Przegląd
Zacznijmy od siedzenia w spodniach, aby zrozumieć, do czego służy system typów, zanim przejdziemy do bardziej formalnych podstaw. System typów narzuca strukturę naszym programom . Mówią nam, jak możemy połączyć różne funkcje i wyrażenia razem. Bez struktury programy są nie do utrzymania i niezwykle złożone, gotowe do wyrządzenia szkody przy najmniejszym błędzie programisty.
Pisanie programów z układem typów jest jak prowadzenie samochodu w idealnym stanie - hamulce działają, drzwi zamykają się bezpiecznie, silnik jest naoliwiony itp. Pisanie programów bez układu typu jest jak jazda motocyklem bez kasku z wykonanymi kołami z spaghetti. Nie masz absolutnie żadnej kontroli nad sobą.
Uziemienie dyskusji załóżmy, że mamy język z dosłownej wypowiedzi num[n]
i str[s]
że reprezentuje liczebnik N i łańcuch s, odpowiednio, i prymitywne funkcje plus
i concat
, z zamierzonego znaczenia. Oczywiście nie chcesz być w stanie napisać czegoś takiego jak plus "hello" "world"
lub concat 2 4
. Ale jak możemy temu zapobiec? A priori nie ma metody odróżnienia cyfry 2 od dosłownego ciągu „świat”. Chcielibyśmy powiedzieć, że wyrażeń tych należy używać w różnych kontekstach; mają różne typy.
Języki i typy
Cofnijmy się nieco: czym jest język programowania? Ogólnie rzecz biorąc, możemy podzielić język programowania na dwie warstwy: składnię i semantykę. Są one również nazywane odpowiednio statyką i dynamiką . Okazuje się, że system typów jest niezbędny do pośredniczenia w interakcji między tymi dwiema częściami.
Składnia
Program jest drzewem. Nie daj się zwieść wierszom tekstu pisanym na komputerze; są to tylko czytelne dla człowieka reprezentacje programu. Sam program jest abstrakcyjnym drzewem składni . Na przykład w C możemy napisać:
int square(int x) {
return x * x;
}
To jest konkretna składnia programu (fragment). Reprezentacja drzewa to:
function square
/ | \
int int x return
|
times
/ \
x x
Język programowania dostarcza gramatyki określający aktualne drzew tego języka (zarówno składni abstrakcyjnej betonu lub mogą być używane). Zwykle odbywa się to za pomocą zapisu BNF. Zakładam, że zrobiłeś to dla języka, który stworzyłeś.
Semantyka
OK, wiemy, co to jest program, ale to tylko statyczna struktura drzewa. Przypuszczalnie chcemy, aby nasz program rzeczywiście coś obliczał . Potrzebujemy semantyki.
Semantyka języków programowania to bogata dziedzina nauki. Ogólnie rzecz biorąc, istnieją dwa podejścia: semantyka denotacyjna i semantyka operacyjna . Semantyka denotacyjna opisuje program, mapując go na pewną podstawową strukturę matematyczną (np. Liczby naturalne, funkcje ciągłe itp.). to nadaje sens naszemu programowi. Przeciwnie, semantyka operacyjna definiuje program, opisując szczegółowo jego wykonanie. Moim zdaniem semantyka operacyjna jest bardziej intuicyjna dla programistów (w tym mnie), więc trzymajmy się tego.
Nie będę omawiał, jak zdefiniować formalną semantykę operacyjną (szczegóły są nieco zaangażowane), ale w zasadzie chcemy zasad takich jak:
num[n]
jest wartością
str[s]
jest wartością
- Jeśli
num[n1]
i num[n2]
oceniamy na liczby całkowite n_1$ and $n_2$, then
plus (num [n1], num [n2]) `ocenia na liczbę całkowitą $ n_1 + n_2 $.
- Jeśli
str[s1]
i analizuje str[s2]
ciągi s1 i s2, to concat(str[s1], str[s2])
ocenia na ciąg s1s2.
Itd. Zasady są w praktyce o wiele bardziej formalne, ale rozumiesz sedno. Jednak wkrótce mamy problem. Co się stanie, gdy napiszemy:
concat(num[5], str[hello])
Hm To dość zagadka. Nigdzie nie zdefiniowaliśmy reguły łączenia liczb z ciągiem znaków. Moglibyśmy spróbować stworzyć taką regułę, ale intuicyjnie wiemy, że ta operacja jest bez znaczenia. Nie chcemy, aby ten program był prawidłowy. W ten sposób jesteśmy nieuchronnie prowadzeni do typów.
Rodzaje
Program jest drzewem zdefiniowanym przez gramatykę języka. Programy mają znaczenie dzięki regułom wykonania. Ale niektórych programów nie można uruchomić; to znaczy, niektóre programy są bez znaczenia . Te programy są źle wpisane. W ten sposób pisanie charakteryzuje znaczące programy w języku. Jeśli program jest dobrze napisany, możemy go uruchomić.
Podajmy kilka przykładów. Ponownie, podobnie jak w przypadku reguł oceny, przedstawię reguły pisania nieformalnie, ale można je usztywnić. Oto kilka zasad:
- Token formularza
num[n]
ma typ nat
.
- Token formularza
str[s]
ma typ str
.
- Jeśli wyrażenie
e1
ma typ, nat
a wyrażenie e2
ma typ nat
, to wyrażenie plus(e1, e2)
ma typ nat
.
- Jeśli wyrażenie
e1
ma typ, str
a wyrażenie e2
ma typ str
, to wyrażenie concat(e1, e2)
ma typ str
.
Zatem zgodnie z tymi regułami istnieje plus(num[5], num[2])
typ nat
, ale nie możemy przypisać typu do plus(num[5], str["hello"])
. Mówimy, że program (lub wyrażenie) jest dobrze napisany, jeśli możemy przypisać mu dowolny typ, a w przeciwnym razie jest źle napisany. System typów jest poprawny, jeśli wszystkie dobrze napisane programy mogą zostać wykonane. Haskell jest zdrowy; C nie jest.
Wniosek
Istnieją inne poglądy na typy. Typy w pewnym sensie odpowiadają logice intuicyjnej i mogą być również postrzegane jako obiekty w teorii kategorii. Zrozumienie tych połączeń jest fascynujące, ale nie jest konieczne, jeśli ktoś chce tylko napisać lub nawet zaprojektować język programowania. Jednak zrozumienie typów jako narzędzia do kontrolowania formacji programów jest niezbędne do projektowania i rozwoju języka programowania. Podrapałem tylko powierzchnię tego, co typy mogą wyrazić. Mam nadzieję, że uważasz, że są one warte zachodu w Twoim języku.