Czy są jakieś wady lub problemy z Haskell?

47

Patrzę na nurkowanie w Haskell dla mojego następnego (stosunkowo trywialnego) osobistego projektu. Powody, dla których walczę z Haskellem są:

  1. Przejdź na język funkcjonalny
  2. Prędkość. Chociaż jestem pewien, że można to argumentować, profilowanie, które widziałem, gwoździe Haskell blisko C ++ (i wydaje się być nieco szybsze niż Erlang).
  3. Prędkość. Serwer internetowy Warp wydaje się być szalony szybki w porównaniu do praktycznie wszystkiego innego .

Biorąc to pod uwagę, szukam wad i problemów związanych z Haskellem. Sieć ma ogromną ilość informacji o tym, dlaczego Haskell jest dobrą rzeczą, ale nie znalazłem wielu tematów na temat jej brzydkiej strony (poza chwytami związanymi z jej składnią, o które w ogóle nie dbam).

Przykładem tego, czego szukam, może być GIL Pythona. Coś, co nie pochyliło się, dopóki naprawdę nie zacząłem używać współbieżności w środowisku CPython.

Demian Brecht
źródło
4
Znalazłem to na stackoverflow: stackoverflow.com/questions/1695076/pros-and-cons-of-haskell
FrustratedWithFormsDesigner
26
Słyszałem, że mniejsi programiści zajmowali się problemami topnienia mózgu. Jest to bardzo drogi stan w leczeniu.
ChaosPandion,
1
@FrustratedWithFormsDesigner: Dzięki za link. Jednak wciąż nie ma żadnych odniesień do jakichkolwiek technicznych wad Haskell. Czy to możliwe, że nie ma żadnych? ;)
Demian Brecht
6
@ChaosPandion: Słyszałem to samo .. Ale jeśli nie topisz mózgu, to naprawdę próbujesz ? ;) Poza tym tak naprawdę nie
Demian Brecht
3
@ChaosPandion: I większość planów zdrowotnych tego nie obejmuje. :(
FrustratedWithFormsDesigner

Odpowiedzi:

48

Kilka wad, o których mogę myśleć:

  • Ze względu na naturę języka i jego silne korzenie w świecie akademickim społeczność jest bardzo matematyczna; jeśli jesteś pragmatyczną osobą, może to być czasami przytłaczające, a jeśli nie znasz żargonu, będziesz miał trudniejszy czas niż w przypadku wielu innych języków.
  • Chociaż istnieje ogromne bogactwo bibliotek, dokumentacja jest często zwięzła.
  • Delikatne samouczki dla początkujących są nieliczne i trudne do znalezienia, więc początkowa krzywa uczenia się jest dość stroma.
  • Kilka funkcji językowych jest niepotrzebnie nieporadnych; wyraźnym przykładem jest to, jak składnia rekordu nie wprowadza zakresu nazewnictwa, więc nie ma sposobu, aby mieć tę samą nazwę pola rekordu w dwóch różnych typach w tej samej przestrzeni nazw modułów.
  • Haskell domyślnie leniwie ocenia i chociaż jest to często świetna rzecz, czasami może cię ukąsić. Naiwne stosowanie leniwej oceny w nie trywialnych sytuacjach może prowadzić do niepotrzebnych wąskich gardeł wydajności, a zrozumienie tego, co dzieje się pod maską, nie jest proste.
  • Leniwa ocena (szczególnie w połączeniu z czystością i agresywnie optymalizującym kompilatorem) oznacza również, że nie możesz łatwo uzasadnić kolejności wykonania; w rzeczywistości nie wiesz nawet, czy dany fragment kodu jest rzeczywiście oceniany w danej sytuacji. W związku z tym debugowanie kodu Haskell wymaga innego sposobu myślenia, choćby dlatego, że przechodzenie przez kod jest mniej przydatne i mniej znaczące.
  • Ze względu na czystość Haskella nie można używać efektów ubocznych do robienia rzeczy takich jak I / O; musisz użyć leniwej oceny monady i „nadużycia”, aby osiągnąć interaktywność, i przeciągnij monadyczny kontekst wszędzie tam, gdzie chcesz zrobić operacje wejścia / wyjścia. (Jest to właściwie dobra cecha na wiele sposobów, ale czasami uniemożliwia pragmatyczne kodowanie).
tdammers
źródło
16
Istnieje kilka naprawdę dobrych książek wprowadzających dostępnych teraz za darmo online. Learn You a Haskell for Great Good to jedna z najlepszych książek dla początkujących, jaką kiedykolwiek czytałem, a Real World Haskell to świetny pośredni zasób.
Tikhon Jelvis
1
@TikhonJelvis: Są to rzeczywiście jedyni dwaj kandydaci, których warto użyć; „Learn You A Haskell” zmieszało mnie bardziej niż cokolwiek innego, „Real World Haskell” działał dla mnie, ale zakłada trochę podstawy programistyczne. Jest też „Delikatne wprowadzenie do Haskell”, ale jest prawie łagodne, zwłaszcza jeśli brakuje ci wiedzy matematycznej.
tdammers
Używam „Delikatnego wprowadzenia do Haskell” i „Real World Haskell”. Połączenie tych dwóch dostarczyło mi wielu przydatnych informacji. Jestem na poziomie, na którym jestem gotowy na nietrywialny projekt, ale niestety nie mam na to dużo czasu.
Giorgio
9
„jeśli jesteś osobą pragmatyczną ...”: czasami używanie języka zorientowanego na matematykę może być bardzo pragmatyczną decyzją, jeśli pozwoli ci to uniknąć wielu błędów w późniejszym czasie. Oczywiście zawsze powinieneś znaleźć równowagę między tym, ile czasu oszczędzasz za pomocą narzędzia, a tym, ile dodatkowego czasu potrzebujesz, aby nauczyć się z niego korzystać.
Giorgio
Monady działałyby (i działają w innych językach) dokładnie tak samo w surowym języku. Absolutnie nie „nadużywasz” leniwej oceny w celu osiągnięcia interaktywności, napisanie ścisłego programu interaktywnego w Haskell jest banalne.
średnik
19

Większość wad Haskell (jak również większość zalet Haskell) wynika z dwóch charakterystycznych cech: jest leniwy i czysto funkcjonalny.

Leniwość sprawia, że ​​trudniej jest uzasadnić wydajność. Zwłaszcza dla osób nieprzyzwyczajonych do lenistwa, ale nawet doświadczonym Haskellerom może być trudno dostrzec, jak lenistwo wpłynie na wydajność w niektórych przypadkach.

Lenistwo oznacza również, że trudniej jest tworzyć dokładne testy porównawcze bez korzystania z bibliotek takich jak Criterion.

Bycie czysto funkcjonalnym oznacza, że ​​za każdym razem, gdy potrzebujesz użyć zmiennych struktur danych (w przypadkach, w których nie można osiągnąć pożądanej wydajności bez nich - chociaż dzięki optymalizatorowi GHC, który nie zdarza się tak często, jak myślisz), będziesz utknął w monadzie IO (lub ST), co czyni kod bardziej kłopotliwym.

Ponieważ wymieniłeś prędkość jako jeden ze swoich celów, powinienem zauważyć, że często istnieją ogromne różnice w wydajności między ręcznie zoptymalizowanym kodem Haskell a kodem Haskell, który został napisany bez większego zastanowienia się nad wydajnością (bardziej niż w innych językach). A ręcznie zoptymalizowany kod Haskell jest często dość brzydki (choć przypuszczam, że dotyczy to również większości innych języków).

sepp2k
źródło
1
Czysto funkcjonalny jest w rzeczywistości cechą sprzedaży, a nie wadą. Język „leniwy” nie ma sensu, leniwy kontra ścisły jest kwestią typów, a zarówno typy leniwe, jak i surowe mają swoje zastosowania. (Więc Haskell jest tak okaleczony przez nie mający ścisłe typy jak większość języków są kalekie, nie mając leniwe typy.) Główne downsides Haskell są jej brzydko System moduł (moduły nie są pierwszej klasy) i zajęcia typu fakt rzeczywiście przełamać modułowość (the Reguła „jedna instancja na typ” zmusza kompilator do utrzymywania globalnej listy instancji klas typów).
pyon
21
„A ręcznie zoptymalizowany kod Haskell jest często dość brzydki (choć przypuszczam, że dotyczy to również większości innych języków)”. To. Kiedy ludzie chcą pokazać elegancję Haskell, publikują krótki i słodki kod, który niestety dałby całkiem słabą wydajność, gdyby działał na ilości danych zbliżonych do produkcji. Kiedy ludzie chcą pokazać, że „Haskell jest tak szybki jak C ++”, publikują zawiły i trudny do odczytania kod, który jest wciąż wolniejszy niż znacznie bardziej czytelna wersja w C.
quant_dev
12

Nie jestem ekspertem od Haskell: nauczyłem się podstaw, ale niestety nie miałem okazji zrobić poważnego projektu w Haskell (chciałbym, bo bardzo lubię ten język).

Jednak z tego, co wiem i z dyskusji z kimś, kto pracował w dziedzinie dość bliskiej programowaniu funkcjonalnemu, Haskell może nie być najlepszym rozwiązaniem, jeśli chcesz wdrożyć algorytmy grafów, w których musisz np. Przejść przez wykres i wykonać wiele lokalnych zmian w strukturze wykresu.

Ponieważ wykres nie ma ogólnie struktury rekurencyjnej, uważam, że najlepszym podejściem jest zbudowanie jednej kopii wykresu przy użyciu struktur i wskaźników między nimi (jak można to zrobić np. W C ++) i manipulowanie tą kopią poprzez zmianę wskaźników, tworzenie lub niszczenie węzłów i tak dalej.

Zastanawiam się, jak takie struktury danych i operacje mogą być właściwie obsługiwane w Haskell, ponieważ o ile wiem w Haskell, nie jest możliwe użycie powyższej reprezentacji / podejścia. W tym artykule krótko omówiono niektóre problemy z algorytmami graficznymi w Haskell

EDYTOWAĆ

Niedawno rozmawiałem z ekspertem od programowania funkcjonalnego i potwierdził on, że wydajne wdrażanie niektórych algorytmów graficznych może być dość trudne w Haskell: poruszanie się po wskaźnikach, takich jak w C lub C ++, może być znacznie szybsze.

Giorgio
źródło
Interesujące uwagi (i link) na temat manipulacji grafem / przejścia w czysto funkcjonalnym świecie. Nie zastanawiałem się nad tym.
Demian Brecht
7
Ciekawym tematem są czysto funkcjonalne algorytmy graficzne. Idiomatycznym rozwiązaniem jest naśladowanie reprezentacji imperatywnej poprzez zastąpienie wskaźników czysto funkcjonalnymi słownikami, np. Mapowanie danego wierzchołka na zbiór wierzchołków, do których ma on krawędzie. Jednakże, jeśli nie zostanie użyty słaby słownik, spowoduje to wyciek pamięci, ponieważ nie można zebrać nieosiągalnych podrafrafów i nie ma znanego, czysto funkcjonalnego słownika słabego. Podsumowując, najnowocześniejsze, czysto funkcjonalne rozwiązanie jest znacznie bardziej skomplikowane i znacznie mniej wydajne!
Jon Harrop
1
Z drugiej strony algorytmy graficzne mogą być bardzo trudne do debugowania, a trwała struktura danych może złagodzić ten problem ...
Jon Harrop
Zastanawiałem się, czy byłoby możliwe opracowanie typu danych graficznych (zgodnie z ideą ByteString: wydajna wewnętrzna reprezentacja plus funkcje konwersji / dostępu). Korzystanie z monad powinno umożliwiać modyfikowanie takich wykresów. Oczywiście rozwiązałoby to problem reprezentowania wykresów, ale nie dotyczy implementacji algorytmów graficznych.
Giorgio
DAG to jedno. Do wszystkiego innego możesz wykorzystać lenistwo i „zawiązać węzeł”.
danielm
4

Wadą Haskell jest to, że jest inaczej. Jest to większy krok od języków, których częściej się uczy lub mówi, więc będzie większa krzywa uczenia się. Jest również mniej popularny w języku, który może ograniczyć dostępność pomocy, jeśli utkniesz. To naprawdę nie są poważne wady.

Jedyną potencjalną wadą jest to, że jest to język funkcjonalny, więc jest mniej przydatny w niektórych domenach problemowych, ale dotyczy to również języków obiektowych. Ogólnie języki nie mają prawdziwych negatywów wykraczających poza krzywe uczenia się, przynajmniej w przypadku stosunkowo popularnych języków. Tak długo, jak język jest kompletny, jest teoretycznie zdolny do wszystkiego.

Ryathal
źródło
3
Kompletność Turinga to czerwony śledź. Teoria obliczeń! = Praktyczne programowanie.
1
@ delnan dlatego powiedziałem teoretycznie
Ryathal
2
Jakie są „domeny problemowe”, dla których Haskell jest rzekomo mniej przydatny?
Andres F.,
3
Chociaż to prawda, społeczność jest mniejsza , w rzeczywistości jest nieproporcjonalnie aktywna. Myślę, że kanał #haskell na freenode jest tylko w tyle za popularnością #python w kanałach językowych, a odpowiadanie na pytania dotyczące Haskell na SO jest zaskakująco konkurencyjne :)
Tikhon Jelvis 26.01.12
@AndresF. - Nie posunąłbym się nawet do powiedzenia „mniej przydatny”, ale oto niektóre obszary, w których Haskell zdecydowanie pokazuje swoje niemowlęctwo: 1) ciężki DP - kodowałem prosty algorytm plecaka i byłem dosłownie zszokowany tym, jak było powoli. Wykorzystywałem tablice pudełkowe, więc spodziewałem się trochę narzutu, ale było znacznie gorzej, niż się spodziewałem. 2) duże nietrywialne gry - AFRP jest w powijakach, więc nie ma szczególnie dobrych ram, a wydajność jest wciąż zbyt trudna do przewidzenia. Minie dużo czasu, zanim zobaczymy wersję Dooma w Haskell. (frag się nie liczy - nie ma AI.)
rtperson 31.01.12
0

Biorąc to pod uwagę, szukam wad i problemów związanych z Haskellem

„Problemy z Haskellem” zwykle pojawiają się w niektórych domenach. Haskell to wspaniały język do programowania aplikacji, znacznie przyjemniejszy w pisaniu niż cokolwiek innego. Problemy zwykle pojawiają się, gdy próbujesz zrobić coś, na co nie ma dobrego wsparcia, na przykład:

  • Kompilacja krzyżowa. GHC można zbudować jako kompilator krzyżowy, ale proces jest raczej zaangażowany.
  • Aplikacje osadzone. Haskell ma zarządzanie pamięcią za pośrednictwem śmietnika, więc ten nie jest zbyt zaskakujący.
  • Prędkość. Haskell nie jest tak szybki jak Rdza, choć w większości przypadków będzie konkurował dość dobrze. Zależy to w dużej mierze od dziedziny aplikacji - czyste obliczenia są dobrze zoptymalizowane, ale coś takiego jak „wczytaj plik do bufora i policz liczbę linii” jest trudniejsze do wyrażenia w Haskell.

źródło