Przeczytałem książkę Learn You a Haskell do momentu, w którym przedstawiają Monady i takie rzeczy jak Just a. Są dla mnie tak sprzeczne z intuicją, że po prostu mam ochotę się poddać, próbując się tego nauczyć.
Ale naprawdę chcę spróbować.
Zastanawiam się, czy mogę chociaż na jakiś czas uniknąć zaawansowanych koncepcji i po prostu zaczynam używać innych części języka do wykonywania wielu praktycznych zadań z bardziej podstawowymi częściami Haskell, tj. Funkcjami, standardowym IO, obsługą plików, interfejs do bazy danych i tym podobne.
Czy to rozsądne podejście do nauki korzystania z Haskell?
Odpowiedzi:
Najpierw rozróżnijmy uczenie się abstrakcyjnych pojęć i uczenie się ich konkretnych przykładów .
Nie zajdziesz daleko, ignorując wszystkie konkretne przykłady, z tego prostego powodu, że są one wszechobecne. W rzeczywistości abstrakcje istnieją w dużej części, ponieważ jednoczą rzeczy, które i tak byś robił z konkretnymi przykładami.
Same abstrakcje są z pewnością przydatne , ale nie są natychmiast potrzebne. Dość daleko można całkowicie zignorować abstrakcje i bezpośrednio użyć różnych typów. W końcu będziesz chciał je zrozumieć, ale zawsze możesz do nich wrócić później. W rzeczywistości mogę prawie zagwarantować, że jeśli to zrobisz, po powrocie do niego uderzysz się w czoło i zastanawiasz się, dlaczego spędziłeś tyle czasu na robieniu rzeczy zamiast korzystania z wygodnych narzędzi ogólnego zastosowania.
Weź
Maybe a
jako przykład. To tylko typ danych:To wszystko samo z siebie; jest to wartość opcjonalna. Albo masz „tylko” coś w rodzaju
a
, albo nie masz nic. Załóżmy, że masz jakąś funkcję wyszukiwania, która powracaMaybe String
do reprezentowania szukaniaString
wartości, która może nie być obecna. Więc dopasuj wzór do wartości, aby zobaczyć, która to jest:To wszystko!
Naprawdę, nic więcej nie potrzebujesz. Żadnych
Functor
s,Monad
ani nic innego. Wyrażają one typowe sposoby używaniaMaybe a
wartości ... ale są to tylko idiomy, „wzorce projektowe”, jakkolwiek chcesz to nazwać.Jedynym miejscem, którego tak naprawdę nie można całkowicie uniknąć, jest
IO
tajemnicza czarna skrzynka, więc nie warto próbować zrozumieć, co to znaczy jako coś takiegoMonad
.W rzeczywistości oto ściągawka na wszystko, o czym naprawdę musisz wiedzieć
IO
na razie:Jeśli coś ma typ
IO a
, oznacza to, że jest to procedura , która coś robi i wyrzucaa
wartość.Gdy masz blok kodu za pomocą
do
notacji, napisz coś takiego:... oznacza wykonanie procedury po prawej stronie
<-
i przypisanie wyniku do nazwy po lewej stronie.Natomiast jeśli masz coś takiego:
... oznacza przypisanie wartości wyrażenia zwykłego (nie procedury) po prawej
=
stronie nazwy po lewej stronie.Jeśli umieścisz tam coś bez przypisania wartości, na przykład:
... oznacza wykonanie procedury i zignorowanie wszystkiego, co zwróci. Niektóre procedury mają ten typ
IO ()
-()
typ jest rodzajem symbolu zastępczego, który nic nie mówi, więc oznacza to, że procedura coś robi i nie zwraca wartości. Coś jakvoid
funkcja w innych językach.Wykonanie tej samej procedury więcej niż raz może dać różne wyniki; taki jest pomysł. Dlatego nie ma możliwości „usunięcia”
IO
wartości, ponieważ coś w niejIO
nie jest wartością, jest to procedura uzyskania wartości.Ostatni wiersz w
do
bloku musi być prostą procedurą bez przypisania, gdzie wartość zwracana tej procedury staje się wartością zwracaną dla całego bloku. Jeśli chcesz, aby wartość zwracana używała już przypisanej wartości,return
funkcja przyjmuje zwykłą wartość i daje ci procedurę braku działania, która zwraca tę wartość.Poza tym nie ma w tym nic specjalnego
IO
; procedury te same w sobie są zwykłymi wartościami i można je przekazywać i łączyć na różne sposoby. Tylko wtedy, gdy są wykonywane wdo
bloku wywołanym przezmain
coś, co robią.A więc w czymś takim, jak ten całkowicie nudny, stereotypowy przykładowy program:
... możesz to odczytać jak imperatywny program. Definiujemy procedurę o nazwie
hello
. Po wykonaniu najpierw wykonuje procedurę drukowania wiadomości z pytaniem o twoje imię; następnie wykonuje procedurę, która odczytuje wiersz danych wejściowych i przypisuje wynik doname
; następnie przypisuje wyrażenie do nazwymsg
; następnie drukuje wiadomość; następnie zwraca nazwę użytkownika jako wynik całego bloku. Ponieważname
jest toString
, oznaczahello
to, że procedura zwraca aString
, więc ma typIO String
. A teraz możesz wykonać tę procedurę w innym miejscu, tak jak to się dziejegetLine
.Pfff, monady. Kto ich potrzebuje?
źródło
Są niezbędne. Bez nich zbyt łatwo jest używać Haskell jako kolejnego imperatywnego języka i chociaż Simon Peyton Jones nazwał go kiedyś Haskell, „najlepszym imperatywnym językiem programowania na świecie”, nadal brakuje ci najlepszej strony.
Monady, transformaty monad, monoidy, funktory, funktory aplikacyjne, funktory kontrastowe, strzałki, kategorie itp. Są wzorami projektowymi. Po dopasowaniu konkretnej rzeczy, którą tworzysz do jednej z nich, możesz czerpać z ogromnego bogactwa funkcji napisanych abstrakcyjnie. Te klasy nie są po prostu po to, by cię mylić, są po to, aby ułatwić ci życie i zwiększyć produktywność. Są one, moim zdaniem, największym powodem zwięzłości dobrego kodu Haskell.
źródło
Czy jest to absolutnie konieczne, jeśli chcesz po prostu coś uruchomić? Nie.
Czy jest to konieczne, jeśli chcesz pisać piękne idiomatyczne programy Haskell? Absolutnie.
Programując w Haskell, warto pamiętać o dwóch rzeczach:
System typów jest w stanie Ci pomóc. Jeśli skomponujesz swój program z wysoce polimorficznego kodu ciężkiego na typeclass, bardzo często możesz znaleźć się w cudownej sytuacji, w której rodzaj funkcji, którą chcesz, poprowadzi cię do (jednej!) Poprawnej implementacji .
Różne dostępne biblioteki zostały opracowane zgodnie z zasadą nr 1.
Pisząc program w Haskell, zaczynam od pisania typów. Potem zaczynam od nowa i zapisuję kilka bardziej ogólnych typów (i jeśli mogą to być wystąpienia istniejących klas, tym lepiej). Następnie piszę niektóre funkcje, które dają mi wartości typów, które chcę. (Potem gram z nimi
ghci
i może napiszę kilka testów QuickCheck.) I na koniec przyklejam to wszystko razemmain
.Można napisać brzydkiego Haskella, który po prostu coś działa. Ale kiedy osiągniesz ten etap, musisz się jeszcze wiele nauczyć.
Powodzenia!
źródło