Widziałem kilka źródeł powtarzających opinię, że „Haskell stopniowo staje się językiem opartym na typach zależnych”. Wydaje się, że implikacja jest taka, że przy coraz większej liczbie rozszerzeń języka Haskell dryfuje w tym ogólnym kierunku, ale jeszcze go tam nie ma.
Zasadniczo chciałbym wiedzieć o dwóch rzeczach. Po pierwsze, po prostu, co właściwie oznacza „bycie językiem o typie zależnym” ? (Miejmy nadzieję, że nie jest to zbyt techniczne).
Drugie pytanie brzmi ... jaka jest wada? Chodzi mi o to, że ludzie wiedzą, że zmierzamy w tę stronę, więc musi to mieć jakąś przewagę. A jednak jeszcze nas tam nie ma, więc musi istnieć jakiś minus, który powstrzymuje ludzi przed pójściem na całość. Mam wrażenie, że problemem jest gwałtowny wzrost złożoności. Ale nie bardzo rozumiem, czym jest pisanie zależne, nie wiem na pewno.
Wiem tylko , że za każdym razem, gdy zaczynam czytać o zależnym typie języka programowania, tekst jest całkowicie niezrozumiały ... Prawdopodobnie w tym tkwi problem. (?)
źródło
Odpowiedzi:
Typowanie zależne to tak naprawdę tylko ujednolicenie wartości i poziomów typów, więc możesz parametryzować wartości na typach (jest to już możliwe w przypadku klas typów i parametrycznego polimorfizmu w Haskell) i możesz parametryzować typy na wartościach (ściśle mówiąc, nie jest to możliwe jeszcze w Haskell , chociaż
DataKinds
bardzo się zbliża).Edycja: Najwyraźniej od tego momentu myliłem się (patrz komentarz @ pigworker). Resztę tego zachowam jako zapis mitów, którymi byłem karmiony. : P
Problem z przejściem na w pełni zależne typowanie, z tego, co słyszałem, polega na tym, że złamałoby to ograniczenie fazy między typem a poziomami wartości, co pozwala skompilować Haskell do wydajnego kodu maszynowego z wymazanymi typami. Przy naszym obecnym poziomie technologii język zależnie typizowany musi w pewnym momencie przejść przez interpreter (albo natychmiast, albo po skompilowaniu do zależnie wpisanego kodu bajtowego lub podobnego).
Niekoniecznie jest to fundamentalne ograniczenie, ale osobiście nie jestem świadomy jakichkolwiek bieżących badań, które wyglądają obiecująco pod tym względem, ale które jeszcze nie dotarły do GHC. Jeśli ktokolwiek wie więcej, byłbym szczęśliwy, gdyby został poprawiony.
źródło
Zależnie wpisany Haskell, teraz?
Haskell jest w niewielkim stopniu językiem zależnym od typografii. Istnieje pojęcie danych na poziomie typu, teraz dzięki bardziej rozsądnemu typowaniu
DataKinds
, i są pewne środki (GADTs
), aby nadać reprezentację danych na poziomie typu w czasie wykonywania. W związku z tym wartości elementów czasu wykonywania skutecznie pojawiają się w typach , co oznacza, że język jest wpisywany zależnie.Proste typy danych są promowane do poziomu rodzaju, dzięki czemu wartości, które zawierają, mogą być używane w typach. Stąd archetypowy przykład
staje się możliwe, a wraz z nim definicje takie jak
co jest miłe. Zauważ, że długość
n
jest czysto statyczną rzeczą w tej funkcji, zapewniając, że wektory wejściowe i wyjściowe mają tę samą długość, nawet jeśli ta długość nie odgrywa żadnej roli w wykonaniuvApply
. Natomiast to o wiele trudniejsze (czyli niemożliwe) do realizacji funkcji, które sprawia, żen
kopie danax
(co byłobypure
dovApply
„s<*>
)ponieważ ważne jest, aby wiedzieć, ile kopii wykonać w czasie wykonywania. Wpisz singletony.
Dla dowolnego typu promowanego możemy zbudować rodzinę singletonów, indeksowaną na typie promowanym, zamieszkałą przez duplikaty jej wartości w czasie wykonywania.
Natty n
jest typem kopii wykonawczych poziomu typun :: Nat
. Teraz możemy pisaćMamy więc wartość na poziomie typu połączoną z wartością czasu wykonywania: inspekcja kopii wykonawczej poprawia statyczną wiedzę o wartości na poziomie typu. Mimo że terminy i typy są rozdzielone, możemy pracować w sposób zależny od typu, używając konstrukcji singleton jako rodzaju żywicy epoksydowej, tworząc wiązania między fazami. To daleko od dopuszczenia dowolnych wyrażeń w czasie wykonywania w typach, ale to nie jest nic.
Co jest paskudne? Czego brakuje?
Naciskajmy na tę technologię i zobaczmy, co zaczyna się chwiać. Można by pomyśleć, że singletonami powinny być zarządzalne w nieco bardziej niejawny sposób
pozwalając nam pisać, powiedzmy,
To działa, ale teraz oznacza, że nasz oryginalny
Nat
typ zrodził trzy kopie: rodzaj, rodzina singletonów i klasa singleton. Mamy dość niezgrabny proces wymiany jawnychNatty n
wartości iNattily n
słowników. Co więcej,Natty
nie jestNat
: mamy pewien rodzaj zależności od wartości czasu wykonywania, ale nie takiego, o jakim myśleliśmy na początku. Żaden w pełni zależnie typowany język nie sprawia, że typy zależne są tak skomplikowane!Tymczasem, choć
Nat
można awansować,Vec
nie można. Nie możesz indeksować według typu indeksowanego. Pełne języków zależnie wpisywanych na maszynie nie narzucają żadnych ograniczeń, aw mojej karierze jako popisywanie się zależnie od maszynistki nauczyłem się uwzględniać przykłady indeksowania dwuwarstwowego w moich przemówieniach, aby uczyć ludzi, którzy zrobili indeksowanie jednowarstwowe Trudno, ale można nie oczekiwać, że złożę się jak domek z kart. Jaki jest problem? Równość. GADT działają, tłumacząc ograniczenia, które uzyskujesz niejawnie, gdy konstruktorowi nadasz określony typ zwracany na jawne wymagania równań. Lubię to.W każdym z naszych dwóch równań obie strony mają życzliwość
Nat
.Teraz spróbuj tego samego tłumaczenia dla czegoś indeksowanego na wektorach.
staje się
a teraz tworzymy ograniczenia równościowe pomiędzy
as :: Vec n x
iVCons z zs :: Vec (S m) x
gdzie obie strony mają różne składniowo (ale dające się udowodnić równe) rodzaje. Rdzeń GHC nie jest obecnie wyposażony w taką koncepcję!Czego jeszcze brakuje? Cóż, większości Haskell brakuje na poziomie typu. Język terminów, które możesz promować, zawiera tylko zmienne i konstruktory spoza GADT. Gdy już je masz,
type family
maszyna pozwala na pisanie programów na poziomie typu: niektóre z nich mogą być całkiem podobne do funkcji, które rozważałbyś napisanie na poziomie terminu (np. WyposażenieNat
w dodawanie, więc możesz podać dobry typ do dołączeniaVec
) , ale to tylko zbieg okoliczności!Inną rzeczą, której brakuje w praktyce, jest biblioteka, która wykorzystuje nasze nowe możliwości do indeksowania typów według wartości. Co robić
Functor
i czymMonad
się stać w tym nowym, wspaniałym świecie? Myślę o tym, ale wciąż jest dużo do zrobienia.Uruchamianie programów na poziomie typu
Haskell, podobnie jak większość języków programowania o typach zależnych, ma dwie operacyjne semantyki. Istnieje sposób, w jaki system czasu wykonywania uruchamia programy (tylko wyrażenia zamknięte, po usunięciu typu, wysoce zoptymalizowany), a także sposób, w jaki narzędzie do sprawdzania typów uruchamia programy (rodziny typów, „Prolog klasy typów” z otwartymi wyrażeniami). Dla Haskella normalnie nie pomieszasz tych dwóch, ponieważ wykonywane programy są w różnych językach. Języki z typami zależnymi mają oddzielne modele wykonawcze i statyczne dla tego samego języka programów, ale nie martw się, model czasu wykonywania nadal pozwala na wymazywanie typów i, w rzeczy samej , wymazywanie dowodów: to właśnie jest ekstrakcja Coqamechanizm daje; przynajmniej to robi kompilator Edwina Brady'ego (chociaż Edwin usuwa niepotrzebnie zduplikowane wartości, a także typy i dowody). Rozróżnienie faz może już nie być rozróżnieniem na kategorię syntaktyczną , ale jest żywe i ma się dobrze.
Języki zależnie wpisane na maszynie, będąc całkowitymi, pozwalają sprawdzaczowi typów na uruchamianie programów bez strachu przed czymś gorszym niż długie oczekiwanie. W miarę jak Haskell staje się coraz bardziej zależny, stajemy przed pytaniem, jaki powinien być jego statyczny model wykonania? Jednym podejściem mogłoby być ograniczenie wykonywania statycznego do funkcji całkowitych, co dałoby nam taką samą swobodę działania, ale mogłoby zmusić nas do rozróżnienia (przynajmniej w przypadku kodu na poziomie typu) między danymi a kodowanymi, abyśmy mogli stwierdzić, czy należy wymuszać wypowiedzenie lub produktywność. Ale to nie jedyne podejście. Możemy wybrać znacznie słabszy model wykonania, który niechętnie uruchamia programy, kosztem wykonywania mniejszej liczby równań tylko przez obliczenia. W efekcie to właśnie robi GHC. Zasady typowania dla rdzenia GHC nie wspominają o uruchamianiu programy, ale tylko do sprawdzania dowodów dla równań. Podczas tłumaczenia do rdzenia, solver ograniczeń GHC próbuje uruchomić programy na poziomie typu, generując mały srebrzysty ślad dowodu, że dane wyrażenie jest równe swojej normalnej formie. Ta metoda generowania dowodów jest trochę nieprzewidywalna i nieuchronnie niekompletna: zwalcza na przykład przerażająco wyglądającą rekurencję i jest to prawdopodobnie rozsądne. Jedną rzeczą, o którą nie musimy się martwić, jest wykonywanie
IO
obliczeń w narzędziu do sprawdzania typów: pamiętaj, że sprawdzanie typów nie musi nadawaćlaunchMissiles
tego samego znaczenia, co system wykonawczy!Kultura Hindley-Milner
System typu Hindley-Milner osiąga naprawdę niesamowity zbieg okoliczności czterech odrębnych rozróżnień, z niefortunnym kulturowym efektem ubocznym, że wielu ludzi nie widzi różnicy między różnicami i zakłada, że zbieg okoliczności jest nieunikniony! O czym ja mówię?
Jesteśmy przyzwyczajeni do pisania terminów i pozostawiania typów do wywnioskowania ... a następnie wymazania. Jesteśmy przyzwyczajeni do ilościowego określania zmiennych typu z odpowiednią abstrakcją typu i aplikacją działającą cicho i statycznie.
Nie musisz zbytnio oddalać się od waniliowej Hindley-Milner, zanim te rozróżnienia przestaną być wyrównane, a to nie jest złe . Na początek możemy mieć ciekawsze typy, jeśli zechcemy je napisać w kilku miejscach. W międzyczasie nie musimy pisać słowników klas typów, gdy używamy przeciążonych funkcji, ale te słowniki są z pewnością obecne (lub wbudowane) w czasie wykonywania. W językach z typami zależnymi spodziewamy się wymazania więcej niż tylko typów w czasie wykonywania, ale (tak jak w przypadku klas typów), że niektóre niejawnie wywnioskowane wartości nie zostaną usunięte. Np.
vReplicate
Argument numeryczny często można wywnioskować z typu żądanego wektora, ale nadal musimy go znać w czasie wykonywania.Które wybory językowe powinniśmy przeanalizować, ponieważ te zbiegi okoliczności już nie istnieją? Np. Czy to prawda, że Haskell nie daje możliwości
forall x. t
jawnego utworzenia instancji kwantyfikatora? Jeśli kontroler typu nie może odgadnąćx
przez ujednoliceniet
, nie mamy innego sposobu, aby powiedzieć, cox
musi być.Szerzej, nie możemy traktować „wnioskowania o typie” jako monolitycznej koncepcji, z której mamy wszystko albo nic. Na początek musimy oddzielić aspekt „uogólnienia” (reguła Milnera „pozwól”), który polega w dużej mierze na ograniczaniu istniejących typów, aby zapewnić, że głupia maszyna może je odgadnąć, od aspektu „specjalizacji” (zasada Milnera „var „reguła”), która jest tak samo skuteczna, jak narzędzie do rozwiązywania ograniczeń. Możemy spodziewać się, że typy najwyższego poziomu będą trudniejsze do wywnioskowania, ale informacje o typie wewnętrznym pozostaną dość łatwe do rozpowszechnienia.
Dalsze kroki dla Haskella
Widzimy, że typy i poziomy rodzaju rosną do siebie bardzo podobnie (i mają już wewnętrzną reprezentację w GHC). Równie dobrze możemy je połączyć. Byłoby fajnie
* :: *
, gdybyśmy mogli: straciliśmy logiczną solidność dawno temu, kiedy pozwoliliśmy na dno, ale solidność typu jest zwykle słabszym wymaganiem. Musimy sprawdzić. Jeśli musimy mieć różne poziomy typu, rodzaju itp., Możemy przynajmniej upewnić się, że wszystko na poziomie typu i wyższym zawsze może być promowane. Byłoby wspaniale po prostu ponownie wykorzystać polimorfizm, który już mamy dla typów, zamiast ponownie wymyślać polimorfizm na poziomie rodzaju.Powinniśmy uprościć i uogólnić obecny system ograniczeń, dopuszczając niejednorodne równania, w
a ~ b
których rodzajea
ib
nie są syntaktycznie identyczne (ale można udowodnić, że są równe). To stara technika (w mojej pracy magisterskiej z ubiegłego wieku), która znacznie ułatwia radzenie sobie z uzależnieniem. Moglibyśmy wyrazić ograniczenia w wyrażeniach w GADT, a tym samym złagodzić ograniczenia dotyczące tego, co można promować.Powinniśmy wyeliminować potrzebę budowy singleton przez wprowadzenie zależnego od typu funkcyjnego
pi x :: s -> t
. Funkcja z takim typem może być jawnie zastosowana do dowolnego wyrażenia typu,s
które znajduje się na przecięciu języka typu i terminów (a więc zmienne, konstruktory, a więcej w przyszłości). Odpowiednia lambda i aplikacja nie zostałyby usunięte w czasie wykonywania, więc moglibyśmy pisaćbez wymiany
Nat
przezNatty
. Domenapi
może być dowolnego typu, który można promować, więc jeśli można promować GADT, możemy pisać zależne sekwencje kwantyfikatorów (lub „teleskopy”, jak je nazwał de Briuijn)na dowolną długość, jakiej potrzebujemy.
Celem tych kroków jest wyeliminowanie złożoności poprzez bezpośrednią pracę z bardziej ogólnymi narzędziami, zamiast zadowalać się słabymi narzędziami i niezgrabnym kodowaniem. Obecne częściowe poparcie sprawia, że korzyści wynikające z zależnych typów Haskella są droższe, niż powinny.
Zbyt trudne?
Typy zależne denerwują wielu ludzi. Denerwują mnie, ale lubię się denerwować, a przynajmniej trudno mi się nie denerwować. Ale to nie pomaga, że wokół tematu jest taka mgła ignorancji. Po części wynika to z faktu, że wszyscy wciąż musimy się wiele nauczyć. Wiadomo jednak, że zwolennicy mniej radykalnych podejść budzą strach przed typami zależnymi, nie zawsze jednak upewniając się, że fakty są całkowicie zgodne z nimi. Nie będę wymieniać imion. Te „nierozstrzygalne sprawdzanie typów”, „niekompletne Turinga”, „brak rozróżnienia fazowego”, „brak wymazywania typu”, „wszędzie dowody” itd., Utrzymują się, mimo że są śmieciami.
Z pewnością nie jest tak, że programy napisane zależnie muszą zawsze być poprawne. Można poprawić podstawową higienę swoich programów, wymuszając dodatkowe niezmienniki w typach bez konieczności przechodzenia do pełnej specyfikacji. Małe kroki w tym kierunku dość często skutkują znacznie silniejszymi gwarancjami z niewielkimi lub żadnymi dodatkowymi zobowiązaniami dowodowymi. Nie jest prawdą, że programy napisane na typie zależnym są nieuchronnie pełne dowodów, w istocie zazwyczaj biorę obecność jakichkolwiek dowodów w moim kodzie jako wskazówkę do zakwestionowania moich definicji .
Podobnie jak w przypadku każdego wzrostu artykulacji, możemy swobodnie mówić zarówno ohydne, jak i nowe rzeczy. Na przykład istnieje wiele kiepskich sposobów definiowania drzew wyszukiwania binarnego, ale to nie znaczy, że nie jest to dobry sposób . Ważne jest, aby nie zakładać, że złych doświadczeń nie da się poprawić, nawet jeśli przyznanie się do tego wypacza ego. Projektowanie definicji zależnych to nowa umiejętność, która wymaga uczenia się, a bycie programistą Haskell nie czyni cię automatycznie ekspertem! A nawet jeśli niektóre programy są obrzydliwe, dlaczego miałbyś odmawiać innym wolności do bycia sprawiedliwym?
Dlaczego nadal zawracać sobie głowę Haskellem?
Naprawdę lubię typy zależne, ale większość moich projektów hakerskich wciąż jest w Haskell. Czemu? Haskell ma klasy typów. Haskell ma przydatne biblioteki. Haskell ma praktyczne (choć dalekie od ideału) podejście do programowania z efektami. Haskell ma kompilator siły przemysłowej. Języki z typami zależnymi są na znacznie wcześniejszym etapie rozwoju społeczności i infrastruktury, ale dojdziemy do tego z prawdziwą zmianą pokoleniową w tym, co jest możliwe, np. Za pomocą metaprogramowania i typów generycznych. Ale wystarczy rozejrzeć się wokół tego, co ludzie robią w wyniku kroków Haskella w kierunku typów zależnych, aby zobaczyć, że można uzyskać wiele korzyści, popychając również obecną generację języków do przodu.
źródło
fmap read getLine >>= \n -> vReplicate n 0
. Jak zauważyłeś,Natty
jest daleko od tego. Ponadto vReplicate powinno dać się przetłumaczyć na rzeczywistą tablicę pamięci, na przykładnewtype SVector n x = SVector (Data.Vector.Vector x)
, gdzien
ma rodzajNat
(lub podobny). Być może kolejny punkt demonstracyjny „popisywania się zależnie od typu”?John to kolejne błędne przekonanie dotyczące typów zależnych: nie działają one, gdy dane są dostępne tylko w czasie wykonywania. Oto jak możesz zrobić przykład getLine:
Edycja: Hm, to miał być komentarz do odpowiedzi świniarza. Wyraźnie zawodzę w SO.
źródło
Vec Zy -> IO String
. Nie możesz tego użyćwithZeroes
, ponieważ typZy
nie może być ujednolicony z forall n. Może uda ci się to obejść w jednym lub dwóch specjalnych przypadkach, ale szybko wymyka się to spod kontroli.forall n
ma to sens. Bardziej precyzyjne ograniczenia można wprowadzić w ten sam sposób. Czy masz lepszy przykład niżVec Zy
(program nadal musiałby obsługiwać użytkownika wprowadzającego 5 zamiast 0)?Vec Zy -> IO String
a drugąVec n -> IO String
, i chcesz użyć pierwszej tylko wtedy, gdy typ jest zgodny. Tak, jest to możliwe, ale mechanizmy umożliwiające to są niezgrabne. I to jest bardzo prosta logika; jeśli masz bardziej złożoną logikę, jest gorzej. Może być również konieczne ponowne napisanie dużej ilości kodu w CPS. I nadal nie masz wyrażenia na poziomie typu, które jest zależne od terminu na poziomie wartościzeroes :: IO (Some (Flip Vec Int))
.pigworker podaje doskonałą dyskusję, dlaczego powinniśmy zmierzać w kierunku typów zależnych: (a) są niesamowite; (b) faktycznie uprościłyby wiele z tego, co już robi Haskell.
A jeśli chodzi o "dlaczego nie?" pytanie, myślę, że jest kilka punktów. Pierwszą kwestią jest to, że chociaż podstawowe pojęcie leżące u podstaw typów zależnych jest łatwe (zezwalaj na zależność typów od wartości), konsekwencje tego podstawowego pojęcia są zarówno subtelne, jak i głębokie. Na przykład rozróżnienie między wartościami i typami jest wciąż żywe i dobre; ale omawianie różnicy między nimi jest dalekobardziej zniuansowany niż u Hindleya - Milnera czy Systemu F. W pewnym stopniu wynika to z faktu, że typy zależne są zasadniczo trudne (np. logika pierwszego rzędu jest nierozstrzygalna). Ale myślę, że większym problemem jest tak naprawdę to, że brakuje nam dobrego słownictwa do wychwytywania i wyjaśniania, co się dzieje. W miarę jak coraz więcej ludzi uczy się o typach zależnych, rozwiniemy lepsze słownictwo, dzięki czemu rzeczy staną się łatwiejsze do zrozumienia, nawet jeśli podstawowe problemy są nadal trudne.
Druga kwestia dotyczy faktu, że Haskell rośniewobec typów zależnych. Ponieważ czynimy stopniowe postępy w realizacji tego celu, ale tak naprawdę go nie osiągamy, utknęliśmy w języku, który ma przyrostowe łaty na przyrostowych. To samo wydarzyło się w innych językach, gdy popularne stały się nowe pomysły. Java nie miała (parametrycznego) polimorfizmu; a kiedy w końcu go dodali, było to oczywiście stopniowe ulepszenie z pewnymi wyciekami abstrakcji i okaleczoną mocą. Okazuje się, że mieszanie podtypów i polimorfizmu jest z natury trudne; ale to nie jest powód, dla którego generiki Java działają tak, jak działają. Działają tak, jak robią, ze względu na ograniczenie polegające na stopniowym ulepszaniu starszych wersji Javy. Jak wyżej, dalej w czasach, kiedy wynaleziono OOP i ludzie zaczęli pisać „obiektywne” C (nie mylić z Objective-C) itd. Pamiętaj, że C ++ zaczynał się pod pozorem bycia ścisłym nadzbiorem C. Dodanie nowych paradygmatów zawsze wymaga zdefiniowania języka od nowa, albo też doprowadziło do jakiegoś skomplikowanego bałaganu. Chodzi mi o to, że dodanie do Haskella typów prawdziwie zależnych będzie wymagało pewnej ilości patroszenia i restrukturyzacji języka - jeśli mamy to zrobić dobrze. Ale naprawdę ciężko jest zaangażować się w tego rodzaju remont, podczas gdy stopniowy postęp, jaki poczyniliśmy, wydaje się tańszy w krótkim okresie. Naprawdę nie ma zbyt wielu ludzi, którzy włamują się do GHC, ale istnieje spora ilość starszego kodu, który można zachować przy życiu. To jest jeden z powodów, dla których istnieje tak wiele języków spin-off, takich jak DDC, Cayenne, Idris itp. C ++ zaczął się pod pozorem bycia ścisłym nadzbiorem C. Dodanie nowych paradygmatów zawsze wymaga zdefiniowania języka od nowa, albo kończy się na skomplikowanym bałaganie. Chodzi mi o to, że dodanie do Haskella typów prawdziwie zależnych będzie wymagało pewnej ilości patroszenia i restrukturyzacji języka - jeśli mamy to zrobić dobrze. Ale naprawdę ciężko jest zaangażować się w tego rodzaju remont, podczas gdy stopniowy postęp, jaki poczyniliśmy, wydaje się tańszy w krótkim okresie. Naprawdę nie ma zbyt wielu ludzi, którzy włamują się do GHC, ale istnieje spora ilość starszego kodu, który można zachować przy życiu. To jest jeden z powodów, dla których istnieje tak wiele języków spin-off, takich jak DDC, Cayenne, Idris itp. C ++ zaczął się pod pozorem bycia ścisłym nadzbiorem C. Dodanie nowych paradygmatów zawsze wymaga zdefiniowania języka od nowa, albo kończy się na skomplikowanym bałaganie. Chodzi mi o to, że dodanie do Haskella typów prawdziwie zależnych będzie wymagało pewnej ilości patroszenia i restrukturyzacji języka - jeśli mamy to zrobić dobrze. Ale naprawdę ciężko jest zaangażować się w tego rodzaju remont, podczas gdy stopniowy postęp, jaki poczyniliśmy, wydaje się tańszy w krótkim okresie. Naprawdę nie ma zbyt wielu ludzi, którzy włamują się do GHC, ale istnieje spora ilość starszego kodu, który można zachować przy życiu. To jest jeden z powodów, dla których istnieje tak wiele języków spin-off, takich jak DDC, Cayenne, Idris itp. albo skończy się na jakimś skomplikowanym bałaganie. Chodzi mi o to, że dodanie do Haskella typów prawdziwie zależnych będzie wymagało pewnej ilości patroszenia i restrukturyzacji języka - jeśli mamy to zrobić dobrze. Ale naprawdę ciężko jest zaangażować się w tego rodzaju remont, podczas gdy stopniowy postęp, jaki poczyniliśmy, wydaje się tańszy w krótkim okresie. Naprawdę nie ma zbyt wielu ludzi, którzy włamują się do GHC, ale istnieje spora ilość starszego kodu, który można zachować przy życiu. To jest jeden z powodów, dla których istnieje tak wiele języków spin-off, takich jak DDC, Cayenne, Idris itp. albo skończy się na jakimś skomplikowanym bałaganie. Chodzi mi o to, że dodanie do Haskella typów prawdziwie zależnych będzie wymagało pewnej ilości patroszenia i restrukturyzacji języka - jeśli mamy to zrobić dobrze. Ale naprawdę ciężko jest zaangażować się w tego rodzaju remont, podczas gdy stopniowy postęp, jaki poczyniliśmy, wydaje się tańszy w krótkim okresie. Naprawdę nie ma zbyt wielu ludzi, którzy włamują się do GHC, ale istnieje spora ilość starszego kodu, który można zachować przy życiu. To jest jeden z powodów, dla których istnieje tak wiele języków spin-off, takich jak DDC, Cayenne, Idris itp. Naprawdę ciężko jest zaangażować się w tego rodzaju remont, podczas gdy stopniowy postęp, jaki poczyniliśmy, wydaje się tańszy w krótkim okresie. Naprawdę nie ma zbyt wielu ludzi, którzy włamują się do GHC, ale istnieje spora ilość starszego kodu, który można zachować przy życiu. To jest jeden z powodów, dla których istnieje tak wiele języków spin-off, takich jak DDC, Cayenne, Idris itp. Naprawdę ciężko jest zaangażować się w tego rodzaju remont, podczas gdy stopniowy postęp, jaki poczyniliśmy, wydaje się tańszy w krótkim okresie. Naprawdę nie ma zbyt wielu ludzi, którzy włamują się do GHC, ale istnieje spora ilość starszego kodu, który można zachować przy życiu. To jest jeden z powodów, dla których istnieje tak wiele języków spin-off, takich jak DDC, Cayenne, Idris itp.
źródło