Tobě "do" syntaxe připadá složitá? Jediný, co potřebuješ pochopit, je rozdíl mezi pure a non-pure funkcí.
Žádné non-pure fce ale neexistují 
No jasně, tak rozdíl mezi pure funkcí a IO akcí. Ale opakuju otázku - co je na IO monádu složitého? Ten monád je doslova (jak jsi psal) to, že pouští jeden "příkaz" za druhým. Žádné výhybky tam nejsou, žádné nedeterministické větvení, nic. Co na tom je složitého? Je to středník, který je naprogramovaný jako středník, takže "do" se chová tak, jak by člověk ve většině programovacích jazyků čekal ("return" na první pohled nevypadá jako šťastná volba, ale po několika kapitolách pure programování mě teda ani nenapadlo, že by to snad tu funkci mělo ukončit - to jsem fakt spíš bojoval s tím, kdy použít "let" a kdy "<-").
Taky se v tom začínám ztrácet, ale tak nějak ty tady v zásadě pořád říkáš, že laziness v zásadě způsobuje složitost haskellu a následně se takové věci jako řazení IO musí řešit přes monády. Já bych asi i souhlasil s tím, že to byl historický vývoj, ale dostali jsme se někam, kde se ukazuje, že to sice na začátku jako opičárna vypadala, ale vlastně to byl docela dobrý nápad.
- v pure výpočtech je laziness celkem putna, mnohdy je spíš lepší
- haskell je v zásadě celý pure včetně IO
- podle tebe je celé IO opičárna, ale mě nějak vůbec není jasné, co by mělo být lepší. Přestat si v IO hrát na pure programování, a pak když se rozhodneš, že místo IO použiješ nějaký Free, nebo to obalíš RWS, tak ten refaktoring bude znamenat přepisování do nějaké jiné syntaxe? Nebo že ti překladač bude automaticky detekovat, jestli je funkce v IO nebo ne a v nějaké syntaxi typu "f(print "a", print "b")" to bude nějak automaticky vyhodnocovat... a pak začneš řešit "ale co když to vyhodnotit nechci" a "v jakém pořadí se to má vyhodnotit".... není to trochu komplikace?