Język Haskell
-------------
Cechą rozpoznawczą języka programowania Haskell jest jego semantyka *non-strict*. Są jednak lepsze powody, dla których warto ten język poznać, a może nawet polubić: wysoki poziom abstrakcji, wycyzelowana składnia, nowoczesny system typów, ogromne możliwości programowania rodzajowego i programowania w typach. Haskell jest także poligonem doświadczalnym społeczności zajmującej się naukowo językami programowania, więc śledzenie najnowszych rozszerzeń języka pozwala trzymać rękę na pulsie najnowszych trendów w tej dziedzinie.
Uczestnicy kursu będą mieli możliwość zapoznania się z samym językiem programowania, ale także z całym haskellowym ekosystemem: narzędziami, bibliotekami, idiomami. Mimo iż część z omawianych zagadnień ma dość zawiłe podstawy teoretyczne, kurs ma charakter praktyczny, a uczestnicy dowiedzą się, jak wykorzystać dane pojęcia i techniki w codziennym programowaniu. W szczególności nie trzeba nic wiedzieć o teorii kategorii.
Wymagania wstępne
-----------------
Podstawowe rozeznanie w programowaniu funkcyjnym. Zdecydowanie zapewnia je przedmiot *Programowanie funkcyjne*, ale porządne zrozumienie treści przedmiotu *Metody programowania* też powinno wystarczyć.
Tematy
------
- Narzędziownik: ghc, ghci, cabal, stack, haddock, quickcheck, hoogle.
- Podstawy programowania funkcyjnego w Haskellu. Przegląd podstawowych typów danych i biblioteki standardowej.
- Programowanie funkcyjne z typami i algebraicznymi strukturami danych, dopasowanie wzorca.
- ⊥ i wartości częściowe. Funkcje *non-strict*. Porządek obliczeń *non-strict* i zasada *full laziness*. Techniki programowania wykorzystujące leniwość: obiekty nieskończone, wykorzystanie leniwych struktur danych w modelu producent-konsument, obliczenia sterowane przepływem danych. Zwiększanie wydajności poprzez fuzję i wylesianie.
- Jednolinijkowce.
- Semantyka denotacyjna Haskella: **CPO**⊥. Indukcja w **CPO**⊥. Prawa równościowe. Wyliczanie programów ze specyfikacji. Optymalizacja przekładu za pomocą reguł przepisywania.
- Problemy wydajności języka *non-strict* (`foldr` vs. `foldl` itp.). Narzucanie przez programistę kolejności obliczeń: wymuszanie gorliwości, leniwe wzorce.
- Przeciążanie: klasy typów, zamknięte i otwarte rodziny typów, *monomorphism restriction*, pułapki zbyt odważnego systemu instancji.
- Bardziej zaawansowane aspekty systemu typów: polimorfizm wyższego rzędu (`RankNTypes`), typy egzystencjalne, typy fantomowe, uogólnione algebraiczne typy danych (`GADTs`), system F.
- Haskell jako metajęzyk: *deep and shallow embeddings*, monady, transformatory, funktory aplikatywne, optyki.
- Wejście/wyjście: monada IO, leniwe IO, typy rozpakowane i odczarowanie monady IO.
- Programowanie rodzajowe: algebraiczne rozumienie algebraicznych typów danych, programowanie *a la carte*, `Data.Data`, Template Haskell.
- Programowanie w typach: indeksowane typy danych, `DataKinds`, *kind polymorphism*.
- Kilka innych ciekawych abstrakcji: komonady, (ko-)Yoneda, rozszerzenia Kana.