Dla tych z Was, którzy mają doświadczenie zarówno w Haskell, jak i niektórych odmianach Lispa, jestem ciekaw, jak „przyjemnie” (używając okropnego terminu) jest pisanie kodu w Haskell vs. Lisp.
Trochę tła: uczę się teraz Haskella, wcześniej pracowałem z Scheme i CL (i trochę wypad do Clojure). Tradycyjnie można by mnie uznać za fana języków dynamicznych ze względu na ich zwięzłość i szybkość. Szybko zakochałem się w makrach Lispa, ponieważ dało mi to kolejny sposób na uniknięcie gadatliwości i schematu.
Uważam, że Haskell jest niesamowicie interesujący, ponieważ wprowadza mnie w sposoby kodowania, o których istnieniu nie wiedziałem. Zdecydowanie ma pewne aspekty, które wydają się pomagać w osiągnięciu zwinności, takie jak łatwość pisania funkcji częściowych. Trochę martwię się jednak utratą makr Lispa (zakładam, że je zgubiłem; prawdę mówiąc, być może jeszcze się o nich nie dowiedziałem?) I statycznym systemem pisania.
Czy ktokolwiek, kto wykonał przyzwoitą ilość kodowania w obu światach, miałby ochotę skomentować, jak różnią się doświadczenia, które wolisz, i czy ta preferencja jest sytuacyjna?
źródło
Przede wszystkim nie martw się o utratę niektórych funkcji, takich jak dynamiczne pisanie. Ponieważ znasz Common Lisp, niezwykle dobrze zaprojektowany język, zakładam, że wiesz, że języka nie można zredukować do zestawu funkcji. Chodzi o spójną całość, prawda?
Pod tym względem Haskell świeci równie jasno jak Common Lisp. Jego funkcje razem zapewniają sposób programowania, który sprawia, że kod jest niezwykle krótki i elegancki. Brak makr jest nieco łagodzony przez bardziej wyszukane (ale również trudniejsze do zrozumienia i użycia) pojęcia, takie jak monady i strzały. System typów statycznych zwiększa twoją moc, a nie przeszkadza, jak ma to miejsce w większości języków zorientowanych obiektowo.
Z drugiej strony programowanie w Haskell jest znacznie mniej interaktywne niż Lisp, a olbrzymia ilość refleksji obecna w językach takich jak Lisp po prostu nie pasuje do statycznego obrazu świata, który zakłada Haskell. W związku z tym dostępne zestawy narzędzi różnią się znacznie między tymi dwoma językami, ale trudno je porównać.
Osobiście wolę ogólnie programować Lisp, ponieważ uważam, że pasuje do sposobu, w jaki lepiej pracuję. Nie oznacza to jednak, że ty też to zrobisz.
źródło
W Haskellu jest mniejsze zapotrzebowanie na metaprogramowanie niż w Common Lisp, ponieważ wiele można zbudować wokół monad, a dodana składnia sprawia, że osadzone DSL wyglądają mniej drzewiasto, ale zawsze jest Template Haskell, jak wspomniał ShreevatsaR , a nawet Liskell (semantyka Haskella + Lisp składnia), jeśli lubisz nawiasy.
źródło
Odnośnie makr, oto strona, która o tym mówi: Hello Haskell, Goodbye Lisp . Wyjaśnia punkt widzenia, w którym makra po prostu nie są potrzebne w Haskell. Zawiera krótki przykład do porównania.
Przykładowy przypadek, w którym makro LISP jest wymagane, aby uniknąć oceny obu argumentów:
Przykładowy przypadek, w którym Haskell nie ocenia systematycznie obu argumentów, bez potrzeby stosowania czegoś w rodzaju makrodefinicji:
I voilà
źródło
delay
nie mogą być funkcją.accept
to (E) DSL.accept
Funkcja jest analogiem makro przedstawionym na poprzednich stronach, a definicjav
jest dokładnie równoległa do definicjiv
na schemacie na slajdzie 40. Funkcje Haskell i Scheme obliczyć samo z tej samej strategii oceny. W najlepszym przypadku makro pozwala pokazać optymalizatorowi większą część struktury programu. Trudno jest twierdzić, że jest to przykład, w którym makra zwiększają moc ekspresji języka w sposób, który nie jest replikowany przez leniwą ocenę.automaton
corazletrec
,:
corazaccept
,->
coraz nic w tej wersji). Cokolwiek.Jestem programistą Common Lisp.
Po wypróbowaniu Haskella jakiś czas temu moim osobistym celem było trzymanie się CL.
Powody:
Haskell ma oczywiście swoje zalety i robi pewne rzeczy w zasadniczo inny sposób, ale po prostu nie daje mi to na dłuższą metę.
źródło
dilbert = dogbert.hire(dilbert);
” ?? Wątpię, aby wielu programistów Haskell mogło to czytać bez najmniejszego drgania.W Haskell możesz zdefiniować funkcję if, co jest niemożliwe w LISP-ie. Jest to możliwe dzięki lenistwu, które pozwala na większą modułowość w programach. Ten klasyczny artykuł Johna Hughesa : Dlaczego FP ma znaczenie , wyjaśnia, w jaki sposób lenistwo wzmacnia kompozycję.
źródło
fold
na przykład funkcje nieścisłe .Są naprawdę fajne rzeczy, które możesz osiągnąć w Lisp za pomocą makr, które są uciążliwe (jeśli to możliwe) w Haskell. Weźmy na przykład makro „memoize” (patrz Rozdział 9 PAIP Petera Norviga). Dzięki niemu możesz zdefiniować funkcję, powiedzmy foo, a następnie po prostu ocenić (memoize 'foo), co zastępuje globalną definicję foo wersją zapamiętaną. Czy możesz osiągnąć ten sam efekt w Haskell z funkcjami wyższego rzędu?
źródło
Kontynuując moją przygodę z nauką Haskella, wydaje się, że jedyną rzeczą, która pomaga w „zastępowaniu” makr, jest możliwość definiowania własnych operatorów wrostków oraz dostosowywania ich pierwszeństwa i asocjatywności. Trochę skomplikowany, ale ciekawy system!
źródło