Pisanie słabe vs. mocne jest dość niejasno zdefiniowane. Co więcej, ponieważ najbliższym powszechnym zastosowaniem „silnego pisania” jest odwoływanie się do rzeczy, które utrudniają rzucanie typów, co nie pozostawia nic więcej do opisania jeszcze silniejszych systemów typów. To tak, jakby powiedzieć, że jeśli możesz unieść mniej niż 30 funtów, jesteś słaby, a każdy, kto może podnieść więcej, należy do tej samej kategorii „silnych” - mylące rozróżnienie.
Wolę więc definicję:
- Słabo typowane systemy używają typów, aby zapobiec robieniu pewnych rzeczy (np. Błędów)
- Silnie typowane systemy używają typów do robienia rzeczy za Ciebie
Co mam na myśli przez robienie rzeczy dla ciebie? Cóż, przeanalizujmy napisanie interfejsu API konwersji obrazu w ramach Servant (w Haskell, ale tak naprawdę nie musisz tego wiedzieć, aby zobaczyć, zobaczysz ...)
{-# LANGUAGE
TypeOperators,
DataKinds
#-}
import Codec.Picture
import Data.Proxy
import Network.Wai.Handler.Warp (run)
import Servant
import Servant.JuicyPixels
main :: IO ()
main = run 8001 conversion
Oznacza to, że chcemy niektóre moduły, w tym pakiet Servant i wtyczkę JuicyPixels do Servant, oraz że głównym punktem wejścia programu jest uruchomienie funkcji „konwersji” na porcie 8001 jako serwer wykorzystujący backend Warp. Zignoruj bit języka.
conversion :: Application
conversion = serve (Proxy :: Proxy ConversionApi) handler
Oznacza to, że funkcja konwersji to serwer, na którym interfejs API musi być zgodny z typem „ConversionApi”, a żądania są obsługiwane przez funkcję handler
type ConversionApi
= ReqBody '[BMP, GIF, JPEG 50, PNG, TIFF, RADIANCE] DynamicImage
:> Post '[BMP, GIF, JPEG 50, PNG, TIFF, RADIANCE] DynamicImage
Określa ConvesionApi
typ. Mówi, że powinniśmy akceptować typy treści przychodzących określone na liście „[BMP, GIF, JPEG 50, PNG, TIFF, RADIANCE] i traktować je jako DynamicImage oraz że powinniśmy zwrócić DynamicImage przekonwertowany na ten sam zakres treści typy. Nie martw się dokładnie o to, co:>, na razie pomyśl o tym jako o szczęśliwej magii.
Tak więc, biorąc pod uwagę moją preferowaną definicję, źle napisany system może teraz zapewnić takie rzeczy jak:
- Nie zwracasz niewłaściwego typu treści wychodzących
- Nie analizujesz przychodzącego żądania jako niewłaściwego typu treści
- Gdyby nasz serwer był bardziej skomplikowany, uniemożliwiłby nam to tworzenie zniekształconych identyfikatorów URI, ale tak naprawdę nie zwracamy żadnych stron HTML zawierających linki (a typ zapewnia, że nie możemy!)
- Naprawdę ambitny system słabego pisania może nawet sprawdzić, czy wyczerpująco obsługujemy wszystkie przychodzące i wychodzące typy treści, pozwalając, aby ten typ działał również jako dokument specyfikacji, a nie tylko ograniczenie.
Wszystkie wzniosłe cele, ale w rzeczywistości niewystarczające do zakwalifikowania się jako system silnie typowy, biorąc pod uwagę powyższą definicję. A teraz musimy przejść do trudnej części pisania kodu zgodnego z tą specyfikacją. W naprawdę silnym systemie piszemy:
handler = return
A potem skończymy. To wszystko, nie ma już kodu do napisania . Jest to w pełni działający serwer WWW (modulo dowolne literówki, które przegapiłem). Ten typ powiedział kompilatorowi wszystko, czego potrzebuje do stworzenia naszego serwera WWW z typów i pakietów (technicznie modułów), które zdefiniowaliśmy i zaimportowaliśmy.
Jak więc nauczyć się tego robić na dużą skalę aplikacji? Cóż, tak naprawdę nie różni się zbytnio od używania ich w aplikacjach na mniejszą skalę. Typy absolutne nie dbają o to, ile kodu jest z nimi związane.
Kontrola typu wykonania jest prawdopodobnie rzeczą, której prawdopodobnie będziesz chciał uniknąć, ponieważ pochłania to ogromną korzyść i pozwala typom na skomplikowanie pracy nad projektem, a nie na uproszczenie typów.
Jako taki, jest to głównie kwestia praktyki modelowania rzeczy z typami. Dwa główne sposoby modelowania rzeczy (lub ogólnie budowania rzeczy) to oddolne i odgórne. Z góry na dół zaczyna się od najwyższego poziomu operacji, a podczas budowania modelu masz części, w których odkładasz modelowanie na później. Modelowanie oddolne oznacza, że zaczynasz od operacji podstawowych, tak jak zaczynasz od funkcji podstawowych, a następnie budujesz coraz większe modele, aż w pełni uchwycisz działanie projektu. Od dołu do góry jest bardziej konkretny i prawdopodobnie szybciej się buduje, ale z góry na dół może lepiej poinformować modele niższego poziomu o tym, jak muszą się właściwie zachowywać.
Rodzaje są to, w jaki sposób programy odnoszą się do matematyki, dosłownie, więc tak naprawdę nie ma górnej granicy tego, jak skomplikowane mogą być, ani punkt, w którym można „zrobić” naukę o nich. Praktycznie wszystkie zasoby poza kursami uniwersyteckimi wyższego poziomu są poświęcone temu, jak typy działają w określonym języku, więc musisz o tym również zadecydować.
Jak najlepiej mogę zaoferować, typy można rozwarstwiać w następujący sposób:
- Bardzo słabo wpisane, takie jak JavaScript, w którym zdefiniowano [] + {}
- Słabo wpisane jak Python, gdzie nie możesz zrobić [] + {}, ale nie jest to sprawdzane, dopóki nie spróbujesz
- Słabo wpisane, jak C lub Java, gdzie nie możesz zrobić [] + {}, ale jest to sprawdzane podczas kompilacji, jednak nie masz bardziej zaawansowanych funkcji typu
- Wokół granicy między słabo i mocno wpisanymi, takimi jak metaprogramowanie szablonu C ++, i prostszy kod Haskell, w którym typy wymuszają tylko właściwości.
- W pełni w mocno wpisanych, takich jak bardziej skomplikowane programy Haskell, w których typy wykonują różne czynności, jak pokazano powyżej
- Bardzo silnie typowane, jak Agda lub Idris, gdzie typy i wartości oddziałują na siebie i mogą się wzajemnie ograniczać. Jest to tak silne, jak tylko systemy typów, a programowanie w nich jest takie samo jak pisanie matematycznych dowodów na to, co robi twój program. Uwaga: kodowanie w Agda nie jest dosłownie pisząc dowodów matematycznych, typy są teorie matematyczne i funkcje z tych typów są konstruktywne przykłady potwierdzające te teorie.
Ogólnie rzecz biorąc, im niżej znajdujesz się na liście, tym więcej typów mogą dla Ciebie zrobić, ale na samym dole wspinasz się w stratosferę, a powietrze staje się nieco rzadkie - ekosystem opakowań jest znacznie mniejszy, a Ty ' Będę musiał sam napisać więcej rzeczy niż znaleźć odpowiednią bibliotekę. Bariera wejścia również rośnie wraz ze spadkiem, ponieważ musisz właściwie zrozumieć system typów wystarczający do pisania programów na dużą skalę.