Seminář z funkcionálního programování

Domácí úkol 1

Implementační část

  • Úkol: Pomocí knihovny Parsec implementujte parser primitivní podmnožiny Haskellu.
  • Termín: 4. 4. 2020 23.59
  • Formát: Odevzdáváte jeden soubor HW01.hs, který vznikne doimplementováním parseru do poskytnuté kostry modulu. Odevzdávárna nahrávané soubory automaticky prefixuje vaším jménem. Odevzdávat můžete opakovaně, ale ujistěte se, že v odevzdávárně nezůstávají stará řešení. Nad každým odevzdáním budou spuštěny automatické testy, jejichž výsledek uvidíte v poznámkovém bloku.

Část peer review

TODO: technické detaily odevzdání peer review

Příklad peer review

Následující příklady zpětné vazby se týkají různých více či méně hypotetických úkolů a můžete se jimi inspirovat. Pochází ale z doby, kdy se recenze psaly do tří textových políček. Nyní budete komentáře vepisovat přímo do kódu, takže nebudete muset pracně popisovat, kterou funkci nebo řádku máte zrovna na mysli.

Co nefunguje?

  • Když zadám více přepínačů --help, program spadne na neúplné vzory (asi by stačilo na ř. 42 nepokračovat rekurzívním voláním).
  • Nefunguje správně redefinice proměnných: když je na vstupu "foo=x" a pak "foo=y", měla by být hodnota "y", ale Tvé řešení je spojí do "xy". Je to asi copy-paste chybou na ř. 101, kde už nemá být <>.
  • Vyhodnocování "Let" nepracuje správně s platností lokálních proměnných. Např. při "eval $ Let 'x' (Con 42) (Let 'x' (Con 66) (Var 'x'))" má být výsledek 66, ale ty vracíš 42.
  • Pokud program dostane "--verbose --silent", všímá si jen toho prvního a je ukecaný. Není to chyba, protože takový případ zadání nespecifikovalo, ale obvyklejší praxe je buď oznámit chybu, nebo z konfliktních přepínačů brát vždy ten poslední.
  • Nepovedlo se mi na žádném divném vstupu řešení rozbít; dobrá práce.

Co se vám líbí?

  • Zajímavé řešení přes vlastní fold na AST.
  • Dobrá dekomposice; ani by mě nenapadlo, že se dají funkce "foo" a "bar" takhle zobecnit.
  • Moc pěkné a účelné použití PatternGuards.
  • Líbí se mi, jak obratně používáš různé monadické funkce (liftM3, join, <*).
  • Oceňuji komentář u funkce "subeval", s ním byl kód jasný. Na druhou stranu ostatní komentáře by snad ani potřeba nebyly, ten kód je fakt dobře čitelný.

Co byste udělali jinak?

  • HLint má několik připomínek, až na zbytečné závorky s nimi souhlasím.
  • Předávání stavu jako pětice je nepřehledné, zvážil bych použít vlastní record.
  • Místy (zejm. f-ce "loremIpsum") už je těch monadických operátorů a závorek na jednom řádku moc a špatně se mi sledovalo, co se vlastně děje. Osobně bych části složitějších výrazů vytáhl do lokální definice, protože mi to umožní jim dát jméno a lépe se pak čte, co se děje o úroveň výš.
  • Většina rekurzívních funkcí nad Expr vypadá podobně; uvažoval bych nad foldem.
  • Řešit "dolorSitAmet" seznamovou monádou mi připadá matoucí, protože to nevnímám jako přirozeně nedeterministický výpočet, ale prostou seznamovou funkci.