Archiwum dla Wrzesień 2009
Najczęściej szukane programista haskell
Po miesiącu od uruchomienia bloga, po zaledwie tygodniu od kiedy Google znalazło mój blog (w czym oczywiście pomogłem) pierwsze zapytanie do wyszukiwarki odnosi do moich skromnych wpisów. Jakież to zapytanie? Otóż:

O! Spodziewałem się raczej technicznych pytań na temat Haskella. A tu proszę, zaczynamy od biznesu! Jestem pozytywnie zaskoczony.
Jeszcze nie wiem czy jest to sygnał zainteresowania, zapotrzebowania, popytu czy podaży na takie miejsca pracy, jednak hasło wydaje się być ze wszech miar interesujące. Sprawdźmy zatem jak to jest z pracą dla programistów znających język Haskell na świecie. Strona www.indeed.com pozwala przeszukiwać ogłoszenia o pracy pod względem występowania w nich słów kluczowych. Wpisałem w zapytaniu haskell language, erlang language, scala language, aby porównać trendy związane z najbardziej interesującymi mnie językami.
We wrześniu 2009 sytuacja przedstawiała się następująco:
Dane aktualnych na dzień, w którym czytasz ten wpis, możesz zobaczyć klikając w powyższy obraz.
Cóż to znaczy? Sztuka programowania w Haskellu czy podobnym języku funkcyjnym jest jak widać nadal unikatową umiejętnością. Dzisiaj. Na statystyki spojrzymy znowu za rok, ciekawe do jakich wniosków wtedy dojdziemy.
Jednak oficjalne statystyki nie mówią wszystkiego.
W wątku haskell-cafe Paul Johnson napisał:
Niedawno ktoś zapytał kto byłby teoretycznie zainteresowany pracą w języku Haskell. Dostał około 20 odpowiedzi. Podobne wyniki miał Microsoft Research w 2006 kiedy to ogłosili, że szukają trzeciej osoby do rozwoju GHC. Wtedy też pojawiło się 20 chętnych kandydatów.
Zatem jeśli następnym razem usłyszę „nie można znaleźć programistów” to odpowiem mniej więcej tak:
Jeśli dasz ogłoszenie o miejscu pracy dla programisty Haskella znajdziesz 20 kandydatów. Wszyscy ci ludzie będą z rodzaju takich, którzy chętnie uczą się nowych języków programowania. Chcą ciągle ulepszać swoje zdolności, ćwiczyć się, szlifować. Nikt nie uczy się Haskella tylko po to, żeby dostać pracę.
Jeśli dasz ogłoszenie o miejscu pracy dla programisty Javy pojawi się 200 kandydatów. W większości będą to ludzie, którzy nauczyli się Javy dlatego, że jest sporo miejsc pracy w języku Javie i jeśli będą umieć wystarczająco, żeby utrzymać się na stanowisku, nie będą widzieć żadnego powodu dla swojego własnego rozwoju.
Jeśli szukasz programisty Haskella lub pracy związanej z tym językiem dobrze będzie wykorzystać miejsca w sieci, gdzie spotykają się ludzie „z branży”. Dobrą stroną jest Haskell in Industry. Kiedy jakaś polska firma dokona tam pierwszego wpisu?
Dlaczego typLAB używa Haskella
Tłumaczenie: Why we use Haskell (Erik Hesselink)
Jako nowo utworzona spółka typLAB, mamy wiele decyzji technicznych do podjęcia. Jedną z ważniejszych jest wybór języka programowania. Ponieważ będziemy budować aplikacje webowe, więc wybór dotyczy zarówno klienta (czyli przeglądarki internetowej) jak i serwera.
Po stronie klienta nie ma wielu opcji, tam użyjemy JavaScript, chyba że chcielibyśmy zastosować Flash lub inną wtyczkę. Natomiast po stronie serwera mamy większą dowolność. Popularnym wyborem dla aplikacji webowych są dynamicznie typowane języki takie jak Ruby, Python czy PHP oraz statycznie typowane Java i C#.
Jednakże widzimy jeszcze inną możliwość. Dwóch z nas studiowało na kierunku Technologii Oprogramowania na Uniwersytecie w Utrechcie, gdzie często używaliśmy języka Haskell. Haskell jest językiem funkcyjnym co oznacza, że, w przeciwieństwie do języków imperatywnych, program składa się z wyrażeń a nie z instrukcji.
Jak już pewnie odgadłeś z tytułu, zdecydowaliśmy się na użycie Haskella po stronie serwera. Co nas do tego skłoniło?
Po pierwsze, lubimy funkcyjny model programowania. Modelowanie programów oparte o wartości zamiast o przerzucanie bitów po pamięci jest znacznie bliższe naszemu mentalnemu sposobowi myślenia. Po prostu piszemy co mamy w głowie a kompilator zajmuje się obliczeniami. To również skutkuje krótszym kodem: Haskell jest nadzwyczajnie zwięzły.
Następnym ważnym argumentem jest statyczny system typów Haskella. Jest on wystarczająco potężny, aby zapobiegać powstawaniu niepoprawnych programów a przy tym nie wchodzi programiście w drogę, jak to czasem się zdarza w tradycyjnych statycznie typowanych językach jak Java czy C#. Automatycznemu przypisywaniu typów zmiennych i funkcji nawet bez adnotacji programisty znacznie ułatwia pracę.
Haskell wyróżnia się spośród innych języków programowania swoją czystością: wyrażenie w Haskellu nie może robić nic innego jak tylko zwrócić swoją obliczoną wartość (funkcje nie mogą mieć efektów ubocznych). Dane są niemodyfikowalne: na przykład jeśli chcesz zmienić listę, tworzysz jej kopię (sprytne kompilatory będą współdzieliły jednakowe elementy). To znaczy, że nigdy nie ma strachu przed tym, że jakaś inna część programu zmieni nasze dane: można zawsze wnioskować tylko lokalnie. Jeszcze jednym plusem jest to, że język może być leniwy. Znaczy to, że wyrażenia nie są obliczanie do momentu, kiedy ich wartość będzie potrzebna. A to może prowadzić do zwiększenia wydajności z jednej strony a z drugiej pozwala na używanie nieskończonych struktur danych.
Jeśli zakażemy efektów ubocznych, to jak na przykład wykonać operacje wejścia wyjścia? Haskell do tego celu używa abstrakcji nazywanej monadą. Monada występuje w typie dając sygnał, że będziemy stosowali efekty uboczne. Monada wejścia wyjścia pozwala narzucić kolejność akcji, co pozwala bezpiecznie je wykonywać w leniwym języku. My używamy monad również do trzymania stanu, w związku ze zmiennymi i do wielu innych ciekawych rzeczy.
Czystość czyni też współbieżność dużo łatwiejszą: skoro dane są niemodyfikowalne, nie ma ryzyka przy współdzieleniu ich pomiędzy wątkami. Jeśli potrzebujesz współdzielić dane, Haskell umożliwia ci to na kilka sposobów, jedną z ciekawszych opcji jest programowa pamięć transakcyjna (STM), czyli bezzamkowy sposób na łączenie niepodzielnych akcji.
Ponieważ Haskell jest językiem funkcyjnym, funkcje są pełnoprawne: możesz je tworzyć w locie, możesz przekazywać je jako argumenty, zwracać jako wyniki czy umieszczać je w strukturach danych. To pozwala na proste tworzenie potężnych abstrakcji. Dla przykładu jedną z częściej używanych w Haskellu funkcji jest map. Przyjmuje ona jako argument inną funkcję przeliczającą wartość typu a na wartość typu b, a map używa jej do przeliczenia listy wartości typu a do listy wartości typu b, element po elemencie. Funkcja map abstrahuje więc iterację po liście. W podobny sposób możemy tworzyć własne abstrakcje. To często prowadzi to tworzenia języków lekkich (EDSL, embedded domain specific languages), szczególnie przydają się tutaj Haskellowe operatory infiksowe.
Połączenie zwięzłości, lokalności danych, silnych typów i formalnych efektów ubocznych ma bardzo ważna konsekwencję: zmiany stają się proste i bez ryzyka. Możesz zmieniać swój kod dowolnie i jeśli nadal przechodzi kontrolę typów, możesz być prawie pewien, że nadal działa poprawnie. W połączeniu z siłą abstrakcji umożliwia to nam szybkie tworzenie programów łatwych do zrozumienia i modyfikowania dla innych.
Na koniec dodajmy, ze bardzo pozytywnym aspektem Haskella jest grupa jego użytkowników. Istnieje sporo aktywnych blogów, duży i przyjazny kanał IRC (#haskell), dostępne w sieci repozytorium pakietów. Mamy świetny kompilator, menedżer pakietów oraz wiele wbudowanych narzędzi takich jak sprawdzanie pokrycia kodu.
Oczywiście z wyborem języka takiego jak Haskell wiąże się też pewne ryzyko. Ponieważ baza jego użytkowników nie jest tak duża jak niektórych innych języków, więc i dostępnych bibliotek jest mniej. Ale z tym sobie poradzimy, Haskell ma świetny interfejs do języka C. Z powodu leniwego trybu wykonywania problemy z wydajnością mogą być trudniejsze do zdiagnozowania i naprawy. No i oczywiście programistów Haskella jest mniej, więc znalezienie kogoś, kto może pomóc będzie nieco trudniejsze.
Bierzemy pod uwagę wszystkie za i przeciw i czujemy, że Haskell niesie ze sobą więcej korzyści niż zagrożeń. I najważniejsze: programowanie w Haskellu jest przyjemnością!
Wydajność języka Haskell 2006
Haskell już od wielu lat doceniany jest za wydajność aplikacji stworzonych w tym języku. Dzisiaj przedstawiam list napisany w 2006 roku przez Brenta Fulghama, człowieka, które zdecydowanie zna się na porównaniach wydajnościowych języków i ich implementacji. W jednym z następnych postów przyjrzymy się, co się zmieniło od 2006 roku do dzisiaj.

Poniżej tłumaczenie listu http://www.haskell.org/pipermail/haskell/2006-June/018127.html:
Drodzy panowie dr Hudak i dr Peyton-Jones:
(Upoważniam was do przekazania poniższej informacji wszystkim potencjalnie zainteresowanym).
Kilka lat temu przejąłem i ożywiłem stronę “Great Computer Language Shootout” gdyż chciałem stworzyć aktualnie porównanie implementacji języków programowania. Strona miała służyć jako amunicja w rozmowach ze współpracownikami negatywnie nastawionym do postępów informatyki. W tamtych czasach byłem głównie zainteresowany wydajnością języków Objective Caml oraz Lisp, ale byłem też zwróciłem uwagę na nowy (dla mnie) język Haskell.
Haskell miał (i nadal ma) piękną, matematyczną notację, która jest bardzo łatwa do odczytania. Ale miał tak niską wydajność, że nie liczyłem na użycie go do czegokolwiek za wyjątkiem prostych testów. Był w prawdzie obiecujący pod względem koncepcyjnym, ale wydawało się, ze na dłuższy czas pozostanie na półce z powodów czysto pragmatycznych.
Chciałbym poinformować o moim ogromnym zaskoczeniu, gdy zobaczyłem niesamowity postęp w zakresie wydajności w Glorious Haskell Compiler przez ostatni rok. Oczywiście wiele również pomogły osoby związane z listą haskell-cafe.
Za najbardziej zaskakującą własność kompilatora uważam to, że jest genialny jeśli chodzi o identyfikowanie niepotrzebnej pracy. Wiele z początkowych testów było napisanych tak, ażeby zmierzyć wydajność prostych języków skryptowych. Przez lata urosły do serii doróbek po to by czasy wykonania były wystarczająco duże do pomiarów podczas, gdy rosła szybkość procesorów jak i poziom zaawansowania implementacji. W wielu wypadkach testy polegają na obliczeniach w pętlach z dużych wartościach liczników. Dzięki temu Perl czy Python (ale również C, Java oraz C++) dyszą ciężko tracąc cenne cykle procesora ażebym mógł mierzyć czasy w sekundach a nie w milisekundach.
I wtedy pojawił się GHC, który odnosił ogromne zwycięstwa ponad innymi językami. Leniwa natura Haskella odrzucała niepotrzebne obliczenia i w mig dostarczała poprawnych rezultatów końcowych. Dlatego musieliśmy zrewidować wiele testów, aby zmusić programy do wykonania prawdziwej pracy, która nie mogła być pominięta. W niektórych przypadkach wymagamy wypisania wartości cząstkowych jako dowodu, że praca została wykonana. Po takich zmianach wyniki Haskella znów zaczęły mieścić się w statystykach.
Jednakże przez kilka ostatnich wydań GHC (oraz kilka ostatnich rund ulepszeń na haskell-cafe), GHC zbliżył się do samego szczytu osiągając wydajność podobną do C. Zauroczyło mnie to, że ta wydajność jest konsystentna pomiędzy różnymi platformami. O ile Java HotSpot działa świetnie na Intelu to moja maszyna z procesorem AMD zawsze w testach wypada gorzej niż Pentium IV. Natomiast GHC sprawuje się jednakowo dobrze na obu systemach i procentowo ma takie same wyniki w porównaniu z językiem C.
Uważam to za świetne, że mogę oczekiwać, iż aplikacje napisane w Haskellu będą miały rozsądną wydajność na wszystkich platformach typu x86 bez specjalnego tuningu. Java oraz kilka innych języków ma różną wydajność w zależności od platformy, prawdopodobnie z powodu optymalizacji dostępnych tylko dla procesorów firmy Intel.
W każdym razie chciałem tylko napisać krótką laurkę dla Haskella i powiedzieć wam jak wielkie wrażanie zrobiła na mnie jego wydajność. Najwyższy czas poważniej przyjrzeć się Haskellowi i wziąć go pod uwagę przy rozwiązywaniu codziennych problemów w pracy już teraz!
Z szacunkiem,
Brent Fulgham
http://shootout.alioth.debian.org/
Programowanie wielordzeniowe w Haskellu
Tłumaczenie M4 – Multicore Programming in Haskell Now!
Komputery z wieloma rdzeniami już tu są: czy twój język programowania jest na nie gotowy?
Haskell jest gotowy: zainstaluj kopię GHC prosto z sieci i już teraz zacznij pisać równoległe programy o wysokiej wydajności. Niniejsze seminarium nauczy cię jak wykorzystać równoległość Haskella na maszynie z wieloma rdzeniami, którą zapewne masz pod ręką. Wprowadzi główne konstrukcje równoległych modeli programowania takie jak:
- pół-formalna równoległość przy użyciu iskier
- w pełni formalna równoległość przy użyciu wątków i pamięci współdzielonej
- programowa pamięć transakcyjna
- równoległość bazująca na danych
Pokażemy jak przy użyciu tych abstrakcji budować szybsze programy. Przyglądniemy się uwarunkowaniom inżynieryjnym tworzenia programów równoległych oraz narzędziom pomocnym w ich debuggowaniu oraz sposobom badania ich wydajności.
Dostępne są już slajdy z seminarium (język angielski), które odbyło się we wrześniu 2009 roku.
Narodziny Grupy Przemysłowej Haskella
Poniżej tłumaczenie z Slides from the IHG talk at CUFP by Duncan Coutts.
Już od dawna wiadomo, że komercyjni użytkownicy Haskella mogliby wiele zyskać na powołaniu organizacji ich reprezentującej. Efekty działania takiej organizacji byłyby też ważne dla szerzej pojętej grupy użytkowników Haskella. Z kolei silniejsza grupa użytkowników niekomercyjnych wspierałaby użytkowników komercyjnych. W ten sposób powstałaby pętla sprzężenia zwrotnego typu dodatniego.
Na poprzedniorocznym CUFP użytkownicy wielu funkcyjnych języków programowania podnieśli kwestię braku organizacji, której można by zapłacić za zajmowanie się ważnymi, ale jednak żmudnymi pracami takimi jak utrzymywanie i udoskonalanie wspólnej infrastruktury. Krótko po CUFP w porozumieniu z głównymi komercyjnymi użytkownikami Haskella, takimi jak Galois czy Amgen, ruszyliśmy pełną parą i już w marcu 2009 roku ogłosiliśmy narodziny Grupy Przemysłowej Haskella (Industrial Haskell Group, IHG).
IHG wystartowała ze ściśle zdefiniowaną listą zadań i już teraz ma silny wpływ na stan platformy deweloperskiej języka Haskell. Oczekujemy, że działania grupy z czasem będą się nasilały i że stanie się ona ważną siłą wspierającą rozwój Haskella.
Prezentacja omawia motywację, która stała za powołaniem grupy IHG, opowiada o dotychczasowych doświadczeniach oraz o lekcjach, które mogą się być może przydać grupom związanym z innym językami funkcyjnymi. Przyjrzymy się też w jaki sposób zapewnić dobrą współpracę pomiędzy użytkownikami komercyjnymi i niekomercyjnymi.
Slajdy prezentacji „Narodziny Grupy Przemysłowej Haskella” (po angielsku).
Na stronie źródłowej dostępne jest również wideo.
Debugowanie w Haskellu
Przetłumaczone z Debugging in Haskell by Jeff Foster.
Zwykle martwiło mnie to, że jeśli użyję jakiegokolwiek IO w funkcji, trzeba będzie zmienić jej typ. Najczęściej to bardzo dobrze, że tak się dzieje. Ale jednak bywa to i bolesne, jeśli mam zmieniać cały kod tylko po to, żeby wypisać na ekran jedną liczbę!
Na szczęście dostępnych jest wiele rozwiązań.
Debugger GHCi pozwala na badanie kodu. Instrukcja :b N ustawia breakpoint na linii N załadowanego modułu. Wezmę dla przykładu anagrams i ustawię :b 30 na linii anagrams <- anagramList wordfile.
anagramsOf :: String -> IO ()
anagramsOf word = do
anagrams <- anagramList wordfile
putStrLn (show (Map.lookup (stringToKey word) anagrams))
Po uruchomieniu programu, gdy breakpoint zostanie osiągnięty otrzymamy co następuje:
Stopped at anagrams.hs:31:2-57 _result :: IO () = _ anagrams :: Map String (Set String) = _ word :: String = _ [anagrams.hs:31:2-57] *Main> :list 30 anagrams <- anagramList wordfile 31 putStrLn (show (Map.lookup (stringToKey word) anagrams))
Instrukcja :list jest używana do wypisania zmiennych wolnych w zasięgu (anagrams i word) i możemy je dalej badać w debuggerze. Specjalna zmienna _result to wynik całego wyrażenia. Gdy program zostanie przerwany, można użyć :trace żeby kontynuować do następnego breakpointu, zapisując przy tym historię wykonania. Polecenia :back i :forward pozwalając na pójście w górę i w dół listy obliczanych wyrażeń i oglądanie każdego z nich z bliska.
Haskell Wiki ma sekcję o debuggowaniu, która zaprowadziła mnie do modułu Debug.Trace. Funkcja trace pozwala wypisać tekst i zwraca wynik swojego drugiego parametru. Na przykład:
Debug.Trace.trace "1+1=" (1 + 1)
Funckja trace przychodzi z ostrzeżeniem, że nie jest bezpieczna pod względem typu. Ale do prostego debuggowania nadaje się jak najbardziej.
Przetłumaczone z Debugging in Haskell by Jeff Foster.
