Navigation
Page categories
Outline:
Last modification
2025-09-04
This is smol web. If you don't like it, fix your browser.

Informační stránka o cvičení z neprocedurálního programování.

Materiály ke čtení#

Kde sehnat vývojové prostředí?#

Na cvičeních budu používat:

Všechna prostředí jsou dostupná v labu. Na vlastní počítač s UNIXem/Linuxem si je můžete nainstalovat pomocí prakticky libovolného balíčkovacího systému. Instalační balíky pro Windows jsou dostupné z odkazů.

Za co bude zápočet?#

Za splnění následujících podmínek:

Na zkoušku je potřeba zápočet, proto je fajn mít všechno vyřešené do konce května.

Pokud v Haskellu i Prologu už programovat umíte a myslíte si, že požadavky pro vás budou triviální, dejte mi vědět mailem nebo na první hodině, ať se zbytečně nenudíte docházkou.

Zápočťáky#

Narozdíl od zápočťáků z “tradičních” programování není potřeba, aby zápočtový program byl nějak extrémně obsáhlý, ale je nutné jím demonstrovat, že umíte správně zneužít výhody logického/funkcionálního programování. Téma je libovolné (kromě úplně triviálních úloh dostupných v desítkách kopií na celém internetu), ale doporučuje se neodbíhat od témat, pro která byly neprocedurální jazyky stvořeny:

Konkrétní nápady:

Zápočťáky je vhodné nenatahovat — 100 řádků dostatečně “ostrého” kódu který nejúčinnějším způsobem řeší zadaný problém je úplně OK.

Termíny#

Upozornění: Pokud chcete zápočťák odevzdávat v červnu nebo později, může se stát, že nebudu k dispozici. Proto, pokud odevzdáváte pozdě a chcete stihnout termín nějaké zkoušky, předem počítejte s nepředvídatelným zpožděním zápočtu o 0 až 3 týdny.

Mezivýsledky#

Jsou k vidění v SISu ve studijních mezivýsledcích. Vysvětlivky:

Zadání domácích úkolů#

Řešení DÚ vkládejte do SISu pomocí rozhraní “studijní mezivýsledky”.

Průběh cvičení#

20. 2. 2019#

Úplný základ Prologu, atomy, klauzule, Skolemovské použití predikátů jako funkcí, vyhodnocování logické formule.

K zamyšlení: Zkuste vyhodnocovadlem logických formulí z cvičení vyřešit nějakou malou instanci SATu.

27. 2. 2019#

Imperativní konstrukce v Prologu, problém s konstruktivistickou sémantikou negace.

Seznamy a běžné funkce na zpracování seznamů: head vs. tail, běžné seznamoviny (append, reverse).

Stihli jsme i logickou hádanku.

6. 3. 2019#

Předávání predikátů jako proměnných, funkce vyšších řádů (filter, map).

Slovo o tail rekurzi, reverse s akumulátorem.

Pokročilá zábava se seznamy, čísla, třídění, matice.

13. 3. 2019#

Doděláme násobení matic. Otočení matice o 90 stupňů. Zip a fold. Stromy.

20. 3. 2019#

Deadline prvního úkolu!

Krutý trik na append/3 fungující v O(1).

Parsování prologem, generativní gramatiky.

Na cvičení se to trochu nestihlo udělat formálně, takže přidávám drobný přehled: Gramatická pravidla se v Prologu zapisují šipkou -->; pravidlo se převede na obdobu normálního pravidla (definovaného pomocí :-) ve kterém si jednotlivá pod-pravidla automaticky předávají seznam k naparsování a vrací “zbytek”. To jsou 2 parametry navíc, které se automaticky přidají ke každému termu (tj. gramatický term s N parametry se převede na normální term s N+2 parametry). Navíc jde vynutit vybrání několika termů “ručně” pomocí [hranatých závorek] a spuštění negramatického kódu (který nedostane seznam a zbytek) se provede pomocí {složených závorek}.

Například:

a --> b.
a(I) --> b(I), c.
a(I) --> b, [I], c.
a --> [X], {isdigit(X)}.

se přeloží na:

a(Z1, Z2) :- b(Z1, Z2).
a(I, Z1, Z3) :- b(I, Z1, Z2), c(Z2, Z3).
a(I, Z1, Z4) :- b(Z1,Z2), Z2=[I|Z3], c(Z3,Z4).
a(Z1,Z2) :- Z1=[X|Z2], isdigit(X).

Pro kompletnost přidávám demonstrační parser aritmetických výrazů (někteří si podobný program můžou pamatovat jako 300řádkovou zrůdnost v C, nebo možná ještě horší v C#).

27. 3. 2019#

Pro úplnost naparsujeme JSOŇ.

Úvod do funkcionálního programování (ve scheme), lambdy.

3. 4. 2019#

Úvod do Haskellu, práce se seznamy a jednoduchými typy. Vracet funkce je fajn.

10. 4. 2019#

Typy, Curry-style funkce. Lambdy. Stromy a nekonečné datové struktury.

Poslední příklad jsem přepsal z if na guard syntax (což je jen trochu hezčí metoda jak napsat hromadu ifů za sebou).

17. 4. 2019#

Ještě trochu zábavy se stromy. Typové třídy a instance.

23.4. 2019 dopoledne#

Ještě nějaká zábava se stromy. Typové třídy Eq, Functor a Foldable.

Vyskytla se otázka, proč některé typové třídy existují s typovým parametrem (např. instance Eq (Strom a) a jiné s typovým parametrem definovat nejde, např. instance Functor (Strom a).

Technický důvod: Eq má kind * -> Constraint, proto akceptuje věci s druhem *, tj. např. Int, Maybe Int nebo Strom Float. Obecně instance říká, že je schopná porovnávat konkrétní objekty jednoho typu. Všimněte si že např. objekty typu Maybe (Int->Int) nijak rozumně porovnávat nejde. Naproti tomu, Functor má kind (* -> *) -> Constraint, takže akceptuje jen jednoparametrové typové konstruktory, což je např. Strom, nebo Maybe nebo IO.

Praktický důvod: Třídy Functor, Foldable (a další, např. Applicative, Traversable a Monad) mají podstatně silnější požadavky na svoje instance:

Například pokud o Strom chcete tvrdit, že je Functor (tj. “kontejner”), musí to nutně být “kontejner” generický, tj. schopný obsahovat jak Int, tak String, tak Strom->[(Float,Float)], tak i jakýkoliv jiný typ. Toto chování vynucuje typ funkce fmap :: Functor f => (a->b) -> f a -> f b — kdybyste např. na Strom Int aplikovali fmap s funkcí typu Int->NecoNoveho, naprosto jasně očekáváte Strom NecoNoveho, bez ohledu na to jestli někdo dodefinoval konkrétní instanci pro Strom NecoNoveho.

Jinak řečeno, absence typového parametru v definici instance znemožňuje reagovat na konkrétní typ obsažený v kontejneru, čímž nepřímo vynucuje, že kontejner bude zcela generický pro všechny typy.

Pro Foldable to platí podobně — svůj kontejner musíte být schopní “seskládat” pomocí foldr vždycky stejně, zcela bez ohledu na to, co obsahuje. Některé funkce z Foldable které v kontejneru potřebují rozumně zpracovatelné hodnoty (např. elem, minimum nebo sum) toto dospecifikovávají extra požadavkem na typovou třídu vnitřního typu, např. elem :: (Foldable t, Eq a) => a -> t a -> Bool nebo sum :: (Foldable t, Num a) => t a -> a.

23.4. 2019 odpoledne#

Jak poměrně přirozeně dojít k monádám.

Pokud jste cvičení nestihli, zhruba podobný obsah mám ve slajdech z Haskellu dostupných odsud (aktuálně na stránkách cca 60 až 76).

Bonus: Pohled na ukrutnou pravdu o IO.

15. 5. 2019#

Applicative/Monad hierarchie. Použití State a celá ukrutná pravda o IO. Zmínku o Reader/Write jsme nestihli, ale Writer je víceméně tosamé, jako Commented z DÚ E.

22. 5. 2019 (bude)#

Monadické parsování (což je řekněme “killer app” celého Haskellu).

Můžete si stáhnout jednoduchou implementaci kterou budeme používat na cvičení.

Bonusy#

Věci co jsme napsali na hodinách budou k dispozici tady

Typing the technical interview.