Typy w Lisp i Scheme


10

Widzę teraz, że rakieta ma typy. Na pierwszy rzut oka wydaje się niemal identyczny z pisaniem Haskell. Ale czy CLP Lispa obejmuje niektóre kosmiczne typy Haskell? Tworzenie bardzo ścisłego typu Haskell i obiektu w dowolnym języku OO wydaje się nieco podobne. Po prostu wypiłem trochę pomocy kool Haskell i jestem totalnie paranoikiem, że jeśli pójdę drogą Lisp, będę się pieprzyć z powodu dynamicznego pisania.

Odpowiedzi:


6

System typu CL jest bardziej wyrazisty niż system Haskell, np. Możesz mieć typ (or (integer 1 10) (integer 20 30))wartości 1,2,...9,10,20,21,...,30.

Jednak kompilatory Lisp nie zmuszają ich do zrozumienia bezpieczeństwa typu w gardle, więc możesz zignorować ich „uwagi” - na własne ryzyko .

Oznacza to, że możesz napisać Haskell w Lisp (że tak powiem), deklarując wszystkie typy wartości i uważnie upewniając się, że wszystkie niezbędne typy są wywnioskowane, ale wtedy łatwiej jest używać Haskell.

Zasadniczo, jeśli chcesz silnego pisania statycznego, użyj Haskell lub OCaml, jeśli chcesz silnego pisania dynamicznego, użyj Lisp. Jeśli chcesz słabego pisania statycznego, użyj C, jeśli chcesz słabego pisania dynamicznego, użyj Perla / Pythona. Każda ścieżka ma swoje zalety (i fanatyków) i wady (i krytyków), więc skorzystasz z nauki ich wszystkich.


19
Każdy, kto używa określeń typu „wymuszanie bezpieczeństwa typu w gardle”, nie rozumie, co to jest bezpieczeństwo typu i dlaczego jest użyteczne.
Mason Wheeler

11
@MasonWheeler: każdy, kto wyciąga przemyślane wnioski z jednego zdania, będzie się mylił częściej niż inaczej. Jak np. W tym przypadku.
sds

4
Ponieważ tematem są języki, termin „do gardła” jest odpowiedni i trafny.
luser droog

1
@KChaloux: Miałem na myśli „ekspresyjny”, jak wyjaśniono w przykładzie.
sds

4
Masz to wszystko do tyłu. Pisanie dynamiczne to szczególny przypadek pisania statycznego, w którym zmusza się programistę do używania 1 typu do wszystkiego. Mogę zrobić to samo (werbalnie) w większości języków o typie statycznym, zadeklarując każdą zmienną jako typ Objectlub dowolny katalog główny drzewa typów. To jest mniej wyraziste, ponieważ jesteś pozbawiony z opcją na powiedzenie, że pewne zmienne mogą zawierać tylko określone wartości.
Doval

5

Wpisany Rakieta bardzo różni się od Haskell. Systemy typów w Lisp i Scheme, a także systemy typów w tradycyjnie ekosystemach bez typowych języków, mają fundamentalny cel, którego nie mają inne systemy typów - współdziałanie z istniejącym nietypowym kodem . Na przykład Rakieta Typowa wprowadziła zupełnie nowe reguły pisania, aby uwzględnić różne idiomy Rakiety. Rozważ tę funkcję:

(define (first some-list)
  (if (empty? some-list)
      #f
      (car some-list)))

W przypadku niepustych list zwraca pierwszy element. W przypadku pustych list zwraca wartość false. Jest to powszechne w nietypowych językach; język pisany użyłby jakiegoś typu opakowania, takiego jak Maybelub rzuciłby błąd w pustej skrzynce. Jeśli chcielibyśmy dodać typ do tej funkcji, jakiego typu należy użyć? Nie jest [a] -> a(w notacji Haskella), ponieważ może zwrócić wartość false. Tak też nie jest [a] -> Either a Boolean, ponieważ (1) zawsze zwraca false w pustym przypadku, nie jest to dowolna wartość logiczna i (2) każdy typ wstawia elementy Lefti fałszuje Righti wymaga „rozpakowania jednego”, aby dostać się do rzeczywistego elementu. Zamiast tego wartość zwraca prawdziwy związek- nie ma konstruktorów zawijania, po prostu zwraca jeden typ w niektórych przypadkach, a inny typ w innych przypadkach. W Typed Racket jest to reprezentowane przez konstruktor typu unii:

(: first (All (A) (-> (Listof A) (U A #f))))
(define (first some-list)
  (if (empty? some-list)
      #f
      (car some-list)))

Typ (U A #f)stwierdza, że ​​funkcja może zwrócić element listy lub wartość false bez żadnej Eitherinstancji zawijania . Kontroler typu może wywnioskować, że some-listjest to albo typ, (Pair A (Listof A))albo pusta lista, a ponadto wnioskuje, że w dwóch gałęziach instrukcji if wiadomo, która z nich jest przypadkiem . Kontroler typu wie, że w (car some-list)wyrażeniu lista musi mieć typ, (Pair A (Listof A))ponieważ warunek if to zapewnia. Nazywa się to typowaniem wystąpień i ma na celu ułatwienie przejścia z niepisanego kodu na kod maszynowy.

Problemem jest migracja. Istnieje mnóstwo nietypowego kodu Racket, a Typed Racket nie może zmusić cię do porzucenia wszystkich swoich ulubionych, nieopisanych bibliotek i spędzenia miesiąca na dodawaniu typów do bazy kodu, jeśli chcesz go użyć. Ten problem ma zastosowanie za każdym razem, gdy dodajesz typy stopniowo do istniejącej bazy kodu, zobacz TypeScript i jego Dowolny typ, aby zastosować javascript do tych pomysłów.

System stopniowego typu musi zapewniać narzędzia do obsługi typowych idiomów bez typu i interakcji z istniejącym nietypowym kodem. W przeciwnym razie zobaczenie „Dlaczego nie używamy już Core.typed” na przykład Clojure.


1
W ekonomii nazywa się to prawem Greshama : złe pieniądze wypierają dobro. Często znajduje zastosowanie także w inżynierii. Kiedy masz w systemie dwa teoretycznie równoważne podsystemy, zbyt często ten gorszy powoduje zbyt wiele problemów, aby uczynić ten lepszy wartym zastosowania, jak widzimy tutaj.
Mason Wheeler

„przykład zaprojektowania systemu typów, który”: to zdanie nie jest kompletne
zrzut z

@MasonWheeler Najgorsze jest, niech zgadnę, dynamiczne sprawdzanie typu. Więc jak tylko go wprowadzisz, nie warto przeprowadzać analizy statycznej?
coredump

1
@coredump - Warto wpisywać stopniowo, chyba że źle interakcja z niewypisanym kodem. Na przykład Dowolny typ w TypeScript po prostu każe sprawdzającemu typowi zrezygnować, po prostu odrzucając zalety systemu typów, ponieważ może to spowodować, że zła wartość rozprzestrzeni się przez duże ilości statycznie sprawdzanego kodu. Typed Racket wykorzystuje kontrakty i granice modułów, aby uniknąć tego problemu.
Jack

1
@coredump Przeczytaj artykuł Clojure. Dynamiczne pisanie, szczególnie w przypadku kodu innej firmy, który nie miał dostępnych typów statycznych, naprawdę spieprzyło ich próby ulepszenia bazy kodu za pomocą typów statycznych.
Mason Wheeler
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.