Systemy typów: nominalne vs. strukturalne, jawne vs. dorozumiane

24

Jestem trochę zdezorientowany różnicą między systemami typu nominalnego i strukturalnego. Czy ktoś może wyjaśnić, czym się różnią?

Z tego co rozumiem:

  • Nominalna: Kompatybilność typów zależy od nazwy typu.
  • Strukturalny: Kompatybilność typów oparta jest na strukturze typów, np. W C, jeśli 2 zmienne są typami struktur o różnych nazwach, ale o tej samej strukturze, wówczas ich typy są kompatybilne.

Teraz o jawnym i dorozumianym: dlaczego różni się od pisania statycznego i dynamicznego? Podczas pisania statycznego typy będą jawne, podczas gdy podczas pisania dynamicznego typy są niejawne. Czy mam rację?

Noor
źródło

Odpowiedzi:

29

W systemie z dynamicznym typowaniem wartości mają typy w czasie wykonywania, ale zmienne i funkcje nie. W systemie o typie statycznym zmienne i funkcje mają typy znane i sprawdzane podczas kompilacji. Np. W Pythonie xmoże być wszystko ; w czasie wykonywania, jeśli jest 1to liczba, a jeśli tak "foo", to ciąg. Będziesz wiedział tylko, który typ xbył w czasie wykonywania, i może być inny przy każdym uruchomieniu programu. W języku takim jak Java piszesz, int xjeśli xma być liczbą, i wiesz, że w czasie kompilacji xzawsze musi to być int.

Oba typy „jawne” i „niejawne” odnoszą się do systemów typu statycznego . Cechą charakterystyczną systemu statycznego jest to, że typy są znane w czasie kompilacji, ale niekoniecznie muszą być zapisane. W Javie typy są jawne - musisz je zapisać. W Javie metoda może wyglądać mniej więcej tak:

public int foo(String bar, Object baz) { ... }

Typy są znane zarówno w czasie kompilacji (statyczne), jak i zapisywane (jawne). Istnieją jednak języki, które nie zmuszają Cię do napisania tego typu. Mogą wywnioskować rodzaj funkcji na podstawie jej ciała i sposobu jej użycia. Przykładem może być OCaml, w którym możesz napisać coś takiego:

let foo x = x + 1

Odkąd +używałeś, OCaml może zorientować się, że xto intwszystko musi być samo w sobie. Tak więc typ foo( foo : int -> int) jest znany w czasie kompilacji, podobnie jak przykład Java. Jest całkowicie statyczny. Ponieważ jednak kompilator może samodzielnie ustalić, jakie typy muszą być, nie musisz sam ich zapisywać: są niejawne.

W skrócie: to, czy system typów jest jawny czy niejawny, jest własnością systemów statycznych . Jest to zupełnie inne pytanie, czy system typów jest dynamiczny czy statyczny.

Często masz systemy typów, które są czasami jawne, a czasem niejawne.

Na przykład uważam, że C # pozwala wnioskować typy za pomocą varsłowa kluczowego. Zamiast pisać int x = 10, możesz pisać, var x = 10a kompilator odkrywa, że ​​to xmusi być int. C ++ robi coś podobnego z auto. Systemy te są zwykle jawne, ale mają pewne wnioski.

Z drugiej strony istnieją systemy, które są zwykle niejawne, ale czasami zmuszają cię do napisania podpisu typu. Haskell jest świetnym przykładem. Przez większość czasu Haskell może wnioskować o typach dla Ciebie. Czasami jednak możesz napisać dwuznaczny kod show . read, w którym Haskell nie jest w stanie samodzielnie rozróżnić typów. W tym przypadku można byłoby zmuszone do jednoznacznie określić typ albo showalbo read. Ponadto niektóre bardziej zaawansowane funkcje systemu typów (takie jak polimorfizm rangi n) powodują, że wnioskowanie jest nierozstrzygalne - to znaczy nie ma gwarancji, że się zatrzyma. Oznacza to, że kod korzystający z tej funkcji często wymaga wyraźnych podpisów typu.

Tikhon Jelvis
źródło
2
W rzeczywistości istnieje kilka języków, które można nazwać wyraźnym dynamicznym pisaniem . Zazwyczaj te języki umożliwiają dodawanie adnotacji do wyrażeń za pomocą typów, a następnie typy te będą sprawdzane w środowisku wykonawczym względem typu wykonania wyrażenia.
Jörg W Mittag
tylko precyzja: systemy typów nie są niejawne ani jawne. Chodzi tu tylko o wnioskowanie typu, które jest zasadniczo sposobem generowania prawidłowych terminów w systemie typów na podstawie innej (czasem nieokreślonej) składni.
Eduardo Pareja Tobes
Dobra odpowiedź, ale nie dotyczy to typowania nominalnego vs. strukturalnego. Edycja byłaby świetna.
lunchmeat317
7
  • statyczny vs dynamiczny opisuje, kiedy typy są sprawdzane (mniej więcej w czasie kompilacji lub w czasie wykonywania)

  • Nominalny vs strukturalny opisuje, kiedy dwa typy są uważane za takie same.

(I są odmiany, najbardziej znanym jest wariant typowania strukturalnego, który uwzględnia tylko to, co jest używane zamiast całego typu znanego jako typowanie kacze).

Cztery kombinacje (statyczny nominalny, statyczny strukturalny, dynamiczny nominalny, dynamiczny strukturalny) są możliwe, a języki dość często nie są wyłącznie w jednej klasie, ale mają aspekty, które są w innych.

Na przykład systemy typów w C ++ są statyczne, głównie nominalne, ale strukturalne, jeśli wziąć pod uwagę szablony (a część problemów związanych z koncepcjami w C ++ można rozważyć jako konflikt między tymi, którzy chcą od pisania typu „duck” do pełnej formy pisania strukturalnego i tych, którzy chcą przejść do pisania nominalnego). A użycie klas i dziedziczenia pozwala w niektórych przypadkach używać dynamicznego i nominalnego pisania.

Język, w którym systemy typu dynamicznego często używają typowania strukturalnego, ale CLOS jako aspekty nominalne.

AProgrammer
źródło
1

Strukturalny: Kompatybilność typów oparta jest na strukturze typów, np. W C, jeśli 2 zmienne są typami struktur o różnych nazwach, ale o tej samej strukturze, wówczas ich typy są kompatybilne.

Zazwyczaj tak nie jest. Wpisywanie strukturalne oznacza, że Bjest to podtyp tego, Aczy może on spełniać Ainterfejs. Zazwyczaj oznacza to posiadanie członków o tej samej nazwie; nie tylko ta sama struktura w pamięci.

Różni się to od typowania nominalnego, które wymaga nadpisania w deklaracji.

Telastyn
źródło
1

Najlepsze wyjaśnienie, jakie widziałem na temat rozróżnienia pomiędzy (a właściwie subskrybowaniem) systemów typu dynamicznego i statycznego, znajduje się w tym blogu autorstwa Boba Harpera:

Jego główny punkt można podsumować jako:

  • języki dynamiczne to języki statyczne z tylko jednym typem
Eduardo Pareja Tobes
źródło
1
Linki mogą się zepsuć; powinieneś zacytować najodpowiedniejsze fragmenty artykułu, aby zostały zachowane dla potomności, nawet jeśli blog będzie kaput.
Doval
2
Pewnie. Myślę, że w tym przypadku wystarczy dodane zdanie :)
Eduardo Pareja Tobes