Haskellowe wynurzenia

Od jakiegoś czasu usiłuję pisać w Haskellu. Się teraz zdecydowałem podzielić zdobytą wiedzą z polskim światkiem programowania. Przedstawię tutaj parę rzeczy jakie zdążyłem się dowiedzieć przez ten czas. Od razu mówię, że nie mam niewiadomo jakiego doświadczenia w Haskellu i jak palnę jakąś głupotę to będę wdzięczny za poprawienie.

Haskell jest pure-functional

Tak, tu wszystko musi być funkcją. Ale tak naprawdę ten wymieniany wszędzie, gdzie się da ficzer to raczej chwyt marketingowy. Wystarczy spojrzeć tylko na ten kawałek kodu:

main = do
  putStrLn "Jak masz na imię?"
  imie <- getLine
  putStrLn $ "Cześć " ++ imie

Jakby nie patrzeć to każdy "imperatywny" programista od razu zrozumie, co ten kod robi (pomijając to, że zrobi WTF na widok $ i ++). Czyli w Haskellu da się pisać imperatywnie. NIE. I jednocześnie tak. Kawałek kodu powyżej to lukier składniowy, który Haskell ma sobie, żeby klepać czytelny kod pozwalający łączyć nas ze "światem zewnętrznym" (tutaj w tej roli standardowe wejście i wyjście). Jeśli ktoś jest ciekawy jak ten kod wygląda po "ufunkcjunalnieniu", tutaj opis. Poza przypadkami łączności ze złym światem, w którym istnieje stan, haskelowcy zalecając pisać czysty, funkcyjny kod. Chociaż patrząc na niektóre biblioteki ludzie ładują monady, gdzie popadnie. Co to są monady? Właśnie...

Haskell jest trudny

O tak, kurewsko. Jeśli już uda nam się opanować parę zupełnie nieznanych obiektów, które "zwykłym" programistom są zupełnie nieznane jak monady, monoidy, funktory, curring czy nawet to, że niektóre typy były chyba wymyślane przez twórców Incepcji to nasze marzenia o stworzeniu naszego pierwszego funkcjonalnego programu pokrzyżuje sadystyczny kompilator. Ktoś nieobeznany napisał na wiki, że Haskell jest silnie typowany. Silnie typowana to jest Java, typy w Haskellu to dresy z dożywotnim karnetem na siłownię. Jeśli spróbujesz zrzutować jeden typ na drugi to po prostu kompilator da ci w ryj. Podobnie w setkach innych sytuacji, których zazwyczaj nie zrozumiesz. Ot, taki jego urok.

Jak już uda ci się jakimś cudem zrobić jakieś proof of technology w stylu zapisu do bazy czy parsowania JSONa, to albo się poddasz, albo będziesz chciał zrobić coś większego. I tu się pojawia kolejny problem, Haskell nie ma stanu. Jedyne rzeczy trzymające stan to niefunkcjonalny, zewnętrzny świat. Trzymanie stanu gry w pliku to raczej kiepski pomysł, trzeba radzić sobie inaczej. Najprościej zrobić funkcję, która zwraca nam zmienną z pożądaną modyfikacją, np.

data Worek = Worek Int deriving (Show)

zmienA (Worek a) = Worek $ a + 1

Haskell jest szybki

Oczywiście twórcy kompilatora to honorowi dręczyciele i wymagają nie tylko od programisty, ale także od siebie. Dlatego GHC jest nie odstaje dużo od C, wiele innych języków znacznie wyprzedza. Zasługi tu mają silne i statyczne typowanie oraz leniwa ewaluacja. Jeśli zawsze unikałeś rekurencji, tutaj nie musisz. Są one, jakby nie patrzeć wymagane przez język i kompilator je bez problemu optymalizuje.

Haskell jest zwięzły i czytelny

Trudno powiedzieć, za mało w tym piszę i siłą rzeczy nie umiem jeszcze pisać całkiem tak jak się powinno. Jestem jeszcze obciążony przez imperatywne pisanie i niektóre problemy próbuję sprowadzić do rzeczy znanych z innych języków. Na pewno każdy, kto używał jakichś wstawek funkcjonalnych wie, jak potrafią skrócić kod (map <3). Nawet w Javie 8 mają wprowadzić elementy funkcjonalne. Także na pewno ten paradygmat wpływa dobrze na jakość kodu, chociaż i tak sporą część - z powodu, który podałem w pierwszym punkcie - większą część kodu i tak się pisze pseudo-imperatywnie.

Haskell jest dojrzały

Kompilator ma tyle samo lat, co ja, więc już można liczyć, że wszystko działa dobrze i stabilnie. Ma pod sobą sporą bazę paczek i systemem do ogarniania tego (Cabal - niestety potrafi tworzyć dependency hell). Dokumentacja też jest niczego sobie, haddock to chyba pierwszy system jaki widziałem, który przebija JavaDoca. Idee ma podobną, dokumentacja przez komentarze w kodzie, ale sam sposób opisu poszczególnych bytów jest dla sporo czytelniejszy (tu też zasługa samego języka). Świetne jest też to wszystkie rzeczy linkują do siebie, bo wszystko jest w jednym miejscu.

Z drugiej strony widać, że tych pakietów mało, kto używa, bo często brakuje wielu potrzebnych rzeczy (albo to są moje imperatywne zachcianki). Bardzo łatwo też znaleźć błędy w kodzie (coś tam już zgłosiłem :]).

Haskell jest fajny

Nie wiem. Ja na razie to wszystko traktuję jako eksperyment, póki co jestem w trakcie udowadniania sobie, czy jestem w stanie stworzyć coś większego. Na to pytanie możesz sam odpowiedzieć.