Funkcionální programátor

čumil

Re:Funkcionální programátor
« Odpověď #105 kdy: 29. 06. 2015, 19:01:06 »
Protože může forknout IO monádu, respektive, že IO monáda něčemu takovému nezabraňuje jako v případě uniqueness typování.
Tak znova. IO monáda forknutí brání. Proto tam kua taky je. To forknutí se dělá tak, že se ta monáda obejde. Je to tak těžké pochopit???

Jo, mohli bychom říct "tohle už není monáda, byla porušena integrita", ale k čemu by to bylo?
Nebrání, forknutí IO neporuší typový systém Haskellu, uniqueness typing naopak forknutí brání, jinak by byl porušen typový systém.


Radek Miček

Re:Funkcionální programátor
« Odpověď #106 kdy: 29. 06. 2015, 19:02:29 »
Jo, mohli bychom říct "tohle už není monáda, byla porušena integrita", ale k čemu by to bylo?

Není důvod říkat, že to není monáda, když to monáda je (axiomy monád platí). Podobně tím není porušena referenční transparentnost.

JSH

Re:Funkcionální programátor
« Odpověď #107 kdy: 29. 06. 2015, 19:09:55 »
Asi mi něco uniká, ale nedá mi, abych se nezeptal - není svět "forknutý" jaksi sám o sobě, respektive není hlavní problém v tom, že se po tom samém světě potulují různé entity, které svou přítomností ten společný svět mění? A pokud ano, není vlastně jedno, zda do světa, který je z důvodu přístupu ostatních entit nepredikovatelný a není možné si ho označkovat časem a očekávat po IO akci deterministický stav v čase t+1, přistupuje n entit nebo n+1, přičemž ta +1 je forknutá původní entita našeho programu napsaného v Haskellu?
Jde o seřazení operací které čtou a mění vnější svět. Samozřejmě že se dají synchronizovat jen změny světa, které udělal ten program. Samo že se ten svět mění i sám o sobě, ale nám jde o řazení našich operací.

Funkcionální jazyky neřeší vedlejší efekty, ale některé základní operace je samozřejmě mají (čtení znaku, souboru, ...), takže se musí nějak zařídit aby překladač ty operace nepřerovnal. Ale u všeho ostatního je to přerovnávání žádoucí.

U Unique typů se zavádí pomocný objekt Svět, který každá IO operace dostane jako parametr a vrátí ho upravený. Pokud typový systém zajistí že ten objekt existuje jenom jeden, tak se IO operace dají prodrátovat tím Světovým objektem jen za sebe.

IO Monád v haskellu dělá úplně to samé akorát ten Světový objekt je schovaný uvnitř a unikátnost nezajišťuje typový systém ale omezení operací, kterými se dají ty jednotlivé IO operace kombinovat.

Co tady čumil pořád opakuje je, že monády nejsou dost čisté, protože je z praktických důvodů možné obejít typový systém, svět forknout a spustit další vlákno. Kdyby se přidaly vlákna do Cleanu, tak tam bude muset být úplně stejný hack.

čumil

Re:Funkcionální programátor
« Odpověď #108 kdy: 29. 06. 2015, 19:15:08 »
Takže. Můj poslední koment v tomhle vlákně. Je mi kuli nemoci blbě, takže nemám gule na to tady vést dál diskuzi, která jak vidím nic nepřinesla, vlastně si zase druhá strana jede to svoje. Což je škoda, zvláště jde li o něco tak krásného jako je funkcionální paradigma.

Haskell není čistý. Je zbytečné se vrtat ve vnitřnostech, akorát se zakecá to hlavní. Ve FP jazyce není třeba sdílenou paměť zamykat, nikdy se nemění. V Haskellu to neplatí. Ve FP jazyce vám v paměti nikdy nevznikne data race (a nejen v paměti, kdekoli, funkce nemají vedlejší efekty ...). V Haskellu musíme paměť zamykat aby se tak nestalo. Vše ukazuje že Haskell není čistý. Tečka.

Metody jak zajistit skutečně plnohodnotné IO se zachováním čistoty jsem už napsal. Není už nic více k řečení. Jen mne dost mrzí, že plno lidí, používajících FP nevidí jeho skutečnou krásu a sílu. Možná že toto zmatení, co vlastně FP je a není i způsobuje, že dosud nebylo více rozšířeno prostě proto, že plno nováčků vidí v logice nekonzistenci.

JSH

Re:Funkcionální programátor
« Odpověď #109 kdy: 29. 06. 2015, 19:16:13 »
Nebrání, forknutí IO neporuší typový systém Haskellu, uniqueness typing naopak forknutí brání, jinak by byl porušen typový systém.
OKI, forkni mi monádu bez implementace na úrovni runtime (která samozřejmě typový systém obchází). Je to obdobné obejití typového systému, které by bylo potřeba pro spuštění plnotučného vlákna v Cleanu.

Ano, pokud zakážeme plnotučná vlákna, pak monády fungují úplně stejne jako unikátní typy. Hlavně proto, že IO monád je zabalený unikátní RealWorld, akorát je ta unikátnost zajištěná trochu jinak.



Radek Miček

Re:Funkcionální programátor
« Odpověď #110 kdy: 29. 06. 2015, 19:24:52 »
Haskell není čistý. Je zbytečné se vrtat ve vnitřnostech, akorát se zakecá to hlavní. Ve FP jazyce není třeba sdílenou paměť zamykat, nikdy se nemění. V Haskellu to neplatí. Ve FP jazyce vám v paměti nikdy nevznikne data race (a nejen v paměti, kdekoli, funkce nemají vedlejší efekty ...). V Haskellu musíme paměť zamykat aby se tak nestalo. Vše ukazuje že Haskell není čistý. Tečka.

Čistota jazyka ospravedlňuje používat tzv. substituční model, když zkoumáme kód v tom jazyce.

Naopak čistota neříká nic o tom, zda tam může nastat race-condition, zda lze přistupovat k paměti, která nepatří procesu, zda lze mít více vláken, zda může nastat dead-lock atd.

v

Re:Funkcionální programátor
« Odpověď #111 kdy: 29. 06. 2015, 19:33:51 »
zdá se, že Clean má standardní knihovnu a zdá se, že ta má modul StdProcess, zmínka o funkci startIO, *World -> *World, víc to nestuduju, jestli se pletu tak mě někdo opravte

Inkvizitor

Re:Funkcionální programátor
« Odpověď #112 kdy: 29. 06. 2015, 20:19:24 »
Jde o seřazení operací které čtou a mění vnější svět. Samozřejmě že se dají synchronizovat jen změny světa, které udělal ten program. Samo že se ten svět mění i sám o sobě, ale nám jde o řazení našich operací.

Funkcionální jazyky neřeší vedlejší efekty, ale některé základní operace je samozřejmě mají (čtení znaku, souboru, ...), takže se musí nějak zařídit aby překladač ty operace nepřerovnal. Ale u všeho ostatního je to přerovnávání žádoucí.

Dobrá, děkuju. Já jsem Haskellem trochu zasažený (hrál jsem si s ním na úrovni studia nějakých tutoriálů včetně nekonečných pokusů definovat co je monáda a spol., řešení úloh v Projektu Euler, jednodušších praktických prográmků, pročtení Real World Haskell i Learn You a Haskell, Typeclassopedie atd.). Dokonce jsem si chvilku hrál i s Concurrent Cleanem. Takže si troufám tvrdit, že v zásadě rozumím, o čem je řeč, ale nechápu spíš smysl sporu.

Jestliže do-notace definuje akci a v rámci IO monády (jak tady někdo psal, snad to moc nezkomolím) předpisuje akci pro interpret, který interaguje s vnějším světem, samozřejmě fork vlákna způsobí, že už nelze říci, která akce následuje po které. Nicméně se ptám, není porušením deterministického pořadí operací existence funkce typu random(), která samozřejmě existuje v Haskellu a jak koukám do knihoven Cleanu, je tam MersenneTwister a nevím, jak v Haskellu a Cleanu zabránit, aby v závislosti na vrácené hodnotě provedl jednu nebo druhou (třetí) operaci. Nebo samozřejmě to dělení může být na základě hodnoty načtené ze standardního vstupu, což je v zásadě totéž.

Jinými slovy mi přijde spor IO monády vs uniqueness typování poněkud malicherný, jelikož ve skutečnosti je problémem dichotomie funkcionální čistoty a reálného světa, kterou nelze žádným trikem přelstít, tudíž žádný prakticky použitelný jazyk nelze označit za čistě funkcionální, ale jsou jazyky, ve kterých lze napsat modul, který čistě funkcionální je, nicméně k tomu, aby dokázal alespoň vypsat výsledek výpočtu, potřebuje slupku, která udělá akci, jež vede k tomu výpisu. Haskell nabízí mechanismus pro vytvoření takové slupky, jenže ta slupka ožije až tím interpreterem, bez něj je to pořád jenom předpis a ne živá slupka.

No a teď zpátky k tomu forku - je samozřejmě poněkud nepříjemné, že nám z jednoho jabka vzniknou dvě a tudíž rozumování o výsledku bytí původně jednoho jabka ve světě je podstatně složitější, ale konečně složitější. Jenomže základní složitost není ve forkovitosti nebo IOMonádovitosti, ale ve slupkovitosti reálného programu.

Tudíž na jednu stranu chápu tvrzení, že Haskell není čistě funkcionální jazyk, na druhou stranu ale žádný prakticky použitelný jazyk není čistě funkcionální, tudíž striktní a úzká definice je dosti neužitečná.

v

Re:Funkcionální programátor
« Odpověď #113 kdy: 29. 06. 2015, 20:32:39 »
malicherný

je malicherný, o tom snad nikdo nepochybuje, pro mě osobně to je intelektuální cvičení jehož předměte je ekvivalence IO monády v jednovláknovém prostředí a uniqness type

fork .. random()

já bych to zas tolik nepitval, mezi vláknem a procesem není tak velký rozdíl, program napsaný v Haskellu se dá spustit dvakrát paralelně, každé monády se vytvořit víc instancí (i když na IO je potřeba speciální magie) a random je akce v IO, které modifikuje její stav

JSH

Re:Funkcionální programátor
« Odpověď #114 kdy: 29. 06. 2015, 20:47:57 »
Jestliže do-notace definuje akci a v rámci IO monády (jak tady někdo psal, snad to moc nezkomolím) předpisuje akci pro interpret, který interaguje s vnějším světem, samozřejmě fork vlákna způsobí, že už nelze říci, která akce následuje po které. Nicméně se ptám, není porušením deterministického pořadí operací existence funkce typu random(), která samozřejmě existuje v Haskellu a jak koukám do knihoven Cleanu, je tam MersenneTwister a nevím, jak v Haskellu a Cleanu zabránit, aby v závislosti na vrácené hodnotě provedl jednu nebo druhou (třetí) operaci. Nebo samozřejmě to dělení může být na základě hodnoty načtené ze standardního vstupu, což je v zásadě totéž.
MerseneTwister i ostatní pseudonáhodné generátory jsou deterministické. Třeba Haskellovská třída RandomGen popisuje objekt který obsahuje stav nějakého random generátoru. A funkce next vrací náhodné číslo a generátor s novým stavem. Vlastně se to dost podobá tomu RealWorld a taky to jde zabalit do monády :)
Pokud se MerseneTwister inicializuje stejně, tak bude vždycky vracet stejná čísla. Stejně tak deterministický program bude se stejným vstupem dělat to samé, takže ani ten standardní vstup determinismem nezahýbe.

Citace
Jinými slovy mi přijde spor IO monády vs uniqueness typování poněkud malicherný, jelikož ve skutečnosti je problémem dichotomie funkcionální čistoty a reálného světa, kterou nelze žádným trikem přelstít, tudíž žádný prakticky použitelný jazyk nelze označit za čistě funkcionální, ale jsou jazyky, ve kterých lze napsat modul, který čistě funkcionální je, nicméně k tomu, aby dokázal alespoň vypsat výsledek výpočtu, potřebuje slupku, která udělá akci, jež vede k tomu výpisu. Haskell nabízí mechanismus pro vytvoření takové slupky, jenže ta slupka ožije až tím interpreterem, bez něj je to pořád jenom předpis a ne živá slupka.

No a teď zpátky k tomu forku - je samozřejmě poněkud nepříjemné, že nám z jednoho jabka vzniknou dvě a tudíž rozumování o výsledku bytí původně jednoho jabka ve světě je podstatně složitější, ale konečně složitější. Jenomže základní složitost není ve forkovitosti nebo IOMonádovitosti, ale ve slupkovitosti reálného programu.

Tudíž na jednu stranu chápu tvrzení, že Haskell není čistě funkcionální jazyk, na druhou stranu ale žádný prakticky použitelný jazyk není čistě funkcionální, tudíž striktní a úzká definice je dosti neužitečná.
Ten spor vidím v ještě drobnější nuanci. Vypsání výsledku se dá udělat dokonale čistě. Jedno vlákno (z pohledu IO) bude čisté jak podle mně, tak podle čumila. Rozpor mezi mnou a čumilem byl vlastně v nuancích co je a co není čisté funkcionální programování. V cleanu nejsou plnotučná vlákna a díky tomu jdou seřadit operace tak, že program nemá uvnitř sebe šanci na nějaké race conditions a podobné věci. Není tam třeba synchronizovat paměť, ... Dá se využít více vláken, ale jen pro vyhodnocování výpočtů bez vedlejších efektů. Všechno s vedlejšími efekty je sesynchronizované jako by bylo v jednom vlákně. U Haskellu je to taky možné, pokud se povolí jen omezená paralelizace (např funkce "par") a nepovolí plnotučná vlákna (forkIO). A díky tomu, že se dá obejít typový systém a spustit další vlákna, není podle čumila Haskell čistě funkcionální.

Je to malicherný spor, to je jasné ;)

JSH

Re:Funkcionální programátor
« Odpověď #115 kdy: 29. 06. 2015, 20:50:45 »
zdá se, že Clean má standardní knihovnu a zdá se, že ta má modul StdProcess, zmínka o funkci startIO, *World -> *World, víc to nestuduju, jestli se pletu tak mě někdo opravte
Byl by odkaz?

Radek Miček

Re:Funkcionální programátor
« Odpověď #116 kdy: 29. 06. 2015, 20:56:53 »
Tudíž na jednu stranu chápu tvrzení, že Haskell není čistě funkcionální jazyk, na druhou stranu ale žádný prakticky použitelný jazyk není čistě funkcionální, tudíž striktní a úzká definice je dosti neužitečná.

Pokud budete jako čistě funkcionální označovat jazyky, kde jsou všechny výrazy referenčně transparentní (výraz e je referenčně transparentní, pokud mohu v každém programu nahradit libovolné výskyty e hodnotou e a chování programu se nezmění), pak Haskell je čistě funkcionální (jak jsem již řekl, nepočítám do toho unsafePerformIO a spol.).

V čistě funkcionálních jazycích pak můžete používat substituční model - výrazy nahrazovat jejich hodnotami bez toho, aby se změnil význam programu. Třeba v OCamlu tohle nefunguje, tam se výraz print_endline "Hi" vyhodnotí na hodnotu () typu unit - když byste výraz print_endline "Hi" nahradil hodnotou (), přišel byste o vedlejší efekt, tj. změnil by se význam program. Zatímco v Haskellu výraz putStrLn "Hi" můžete chápat tak, že vrací hodnotu typu IO (), která pouze popisuje jaký vedlejší efekt se má udělat - kdybyste tuto hodnotu uměl přímo zkonstruovat, mohl byste jí nahradit výraz putStrLn "Hi" a význam programu by se nezměnil (nahradil byste výraz, který konstruuje popis, již zkonstruovaným popisem).

Kromě toho bývají Hindley–Milnerovské typové systémy jednodušší v čistých jazycích - v těch nečistých musíte omezit generalizaci (např. pomocí value restriction). Rovněž se některé optimalizace provádí snáze v čistých jazycích - proto je monadický kód v OCamlu, Scale a F# tak pomalý.

v

Re:Funkcionální programátor
« Odpověď #117 kdy: 29. 06. 2015, 21:02:18 »
zdá se, že Clean má standardní knihovnu a zdá se, že ta má modul StdProcess, zmínka o funkci startIO, *World -> *World, víc to nestuduju, jestli se pletu tak mě někdo opravte
Byl by odkaz?

http://clean.cs.ru.nl/download/supported/ObjectIO.1.2/doc/tutorial.pdf

v

Re:Funkcionální programátor
« Odpověď #118 kdy: 29. 06. 2015, 21:12:09 »
Ten spor vidím v ještě drobnější nuanci. Vypsání výsledku se dá udělat dokonale čistě. Jedno vlákno (z pohledu IO) bude čisté jak podle mně, tak podle čumila. Rozpor mezi mnou a čumilem byl vlastně v nuancích co je a co není čisté funkcionální programování. V cleanu nejsou plnotučná vlákna a díky tomu jdou seřadit operace tak, že program nemá uvnitř sebe šanci na nějaké race conditions a podobné věci. Není tam třeba synchronizovat paměť, ... Dá se využít více vláken, ale jen pro vyhodnocování výpočtů bez vedlejších efektů. Všechno s vedlejšími efekty je sesynchronizované jako by bylo v jednom vlákně. U Haskellu je to taky možné, pokud se povolí jen omezená paralelizace (např funkce "par") a nepovolí plnotučná vlákna (forkIO). A díky tomu, že se dá obejít typový systém a spustit další vlákna, není podle čumila Haskell čistě funkcionální.

Je to malicherný spor, to je jasné ;)

brání uniqness type implementaci něčeho jako forkIO? tj. v Clean asi forkWorld? přijde mi, že ne, ale nevim

JSH

Re:Funkcionální programátor
« Odpověď #119 kdy: 29. 06. 2015, 21:47:32 »
brání uniqness type implementaci něčeho jako forkIO? tj. v Clean asi forkWorld? přijde mi, že ne, ale nevim
Podle čumila nejspíš jo :
Citace
Pokud v Cleanu bude svět forknut, přestane být uniqueness typovaný a bude porušena jeho syntaktická integrita. Kdežto IO monáda je IO monádou i když je forknutá, žádné porušení systému se nekoná.
Já osobně v tom vidím spíš slovíčkaření.