Funkcionální programátor

BoneFlute

  • *****
  • 1 981
    • Zobrazit profil
Re:Funkcionální programátor
« Odpověď #240 kdy: 05. 07. 2015, 02:02:12 »
Takže si asi dokážeš představit, že mě moc netankuje když sice jazyk je pure, ale že kompilátor si dělá něco jiného je v pořádku.
Podle mě si úplně nerozumíme. Kompilátor/runtime si nedělá něco jiného. Dělá přesně to, co mu sémantika jazyka ukládá udělat. To ale nic nemění na tom, že pro jeden jazyk bys mohl mít sémantiku úplně jinou a pak by spuštění programu reálně způsobilo něco úplně jiného. To se myslím snažil Radek říct tím http://forum.root.cz/index.php?topic=11417.msg135027#msg135027

Jenže vlastnosti sémantiky ("runtimu") a vlastnosti jazyka jsou dvě různé věci. Typový systém je záležitostí jazyka. Souběhy a jejich důsledky jsou záležitostí sémantiky. Aspoň myslím teda ;)
Pokud ti jazyk zakazuje souběh, tak ho runtime nemůže udělat. Pokud jazyk nespecifikuje takovou situaci, pak ano.

Nerozumím tomu, jak by mohl mět jeden jazyk více sémantik (významů výrazů)? Můžeš to rozvést?


Re:Funkcionální programátor
« Odpověď #241 kdy: 05. 07. 2015, 02:10:14 »
Pokud ti jazyk zakazuje souběh, tak ho runtime nemůže udělat. Pokud jazyk nespecifikuje takovou situaci, pak ano.
Jazyk právě souběh nijak zakázat nemůže, to jde úplně mimo něj.

Nerozumím tomu, jak by mohl mět jeden jazyk více sémantik (významů výrazů)? Můžeš to rozvést?
Polopaticky řečeno, jazyk přece neřeší, co ty funkce opravdu dělají. Pro něj jsou to totální blackboxy. Zná jenom typ vstupů a typ výstupu, ale co se uvnitř opravdu děje, neřeší.

Příklad pro ten souběh: "ví" jazyk C, že fork spouští nějaký nový proces? Vůbec. Jak by ti jazyk jako takový mohl zakázat spustit nový proces, když on vůbec netuší a neřeší, co fork dělá. Pro něj je to prostě jenom "pid_t fork(void)" a pokud mu nedáváš žádný parametr a nechceš z něj dostat string, je happy :)

Pokud bys chtěl fork neumožnit, tak to uděláš třeba tak, že tvůj runtime vůbec nebude fci fork mít a nebude umožňovat volat systémová volání. A pak neforkneš ani kdyby ses na hlavu postavil. Ale jazyk za to nemůže, může za to runtime :)

BoneFlute

  • *****
  • 1 981
    • Zobrazit profil
Re:Funkcionální programátor
« Odpověď #242 kdy: 05. 07. 2015, 02:17:12 »
3. A teď, když budu mět funkci openFile :: FilePath -> IOMode -> IO Handle, tak na první pohled se chová jako můj druhý příklad. Jenže ve skutečnosti já nikdy nevím, kterou z těch dvou možností (otevře soubor | zařve) udělá. A to mě přijde jako dost velký rozdíl.
Nevím, jestli ti úplně rozumím. Zkusme si vzít raději operaci "načtení prvního bajtu ze souboru" a opět ji zapsat jako relaci... Jako máš [{1,2},{2,3},...] tak teď budeš mít jakoby navíc parametr "stav světa", který můžeš efektivně zúžit na "stav toho souboru, který mě zajímá", a dostaneš něco jako
Kód: [Vybrat]
[{"aaaa","a"},{"abbb","a"},{"baaa","b"},...] kde ten jeden parametr je "faktický obsah souboru" a to druhý je výsledek fce "načti mi první byte".  Tohle je naprosto čistá fce. Žádná magie, žádný monády, nic. Zcela čistá matematická fce. Čili jazyk jako takový nemá problém.

Jenže když ten program budeš chtít spustit (pomocí nějakého toho "stroje", jak jsem to psal výš), tak ten stroj musí ten skutečný stav světa zjistit - provést nějakou činnost. Tu činnost nedělá jazyk, tu dělá runtime. Jazyk zná jenom tu relaci, což je čistě statická, naprosto pure záležitost :) kde o žádném "spuštění" nedává vůbec smysl hovořit.

(Jé, já se tak těším na ten aha efekt.)

Představím si, že jsem kompilátor (naivní), tak bych z toho udělal switch, kde na základě toho první bajtu v souboru se rozhodnu jak budu pokračovat v dalších 256 cestách. Takhle si to představuji já, a takhle o tom uvažuji. Ale asi to stále není to, co máte na mysli.

Když si to pročítám, pro mě není problém, že si stroj musí zjistit skutečný stav světa, nebo, že musí provést nějakou činnost. To ať si dělá. Pro mě je kruciálně zásadní, že když předpis říká: tenhle vzorec skončí číslem, tak engine vrátí číslo. (Jestli ho nejdříve zjistí, nebo ne, mě nezajímá.) Když předpis říká, tenhle vzorec skončí výpisem obsahu souboru na obrazovku, tak engine vypíše obsah souboru na obrazovku. A že ten soubor nemá? To má blbý, jeho chyba. Předpis s tím nepočítal? Jak je to možné? To bude nějaká chyba jazyka.

Atd.

Re:Funkcionální programátor
« Odpověď #243 kdy: 05. 07. 2015, 02:27:42 »
Hele, nemůžeme si tykat?

Představím si, že jsem kompilátor (naivní), tak bych z toho udělal switch, kde na základě toho první bajtu v souboru se rozhodnu jak budu pokračovat v dalších 256 cestách. Takhle si to představuji já, a takhle o tom uvažuji. Ale asi to stále není to, co máte na mysli.
Jediný, co jsem měl namysli, je ten rozdíl mezi programem, který žije v ideálním světě, kde nic není potřeba načítat a všechno je jenom statická relace, a skutečným světem, kde je potřeba dělat nějakou činnost. V tom ideálním světě tě nijak netrápí souběhy a ani o nich vůbec nemá smysl hovořit*, protože vše je statické, nic se nemusí vypočítat, nic se nespouští.

* pokud by pro ně jazyk neměl nějakou úplně explicitní syntax, která by vůbec nebyla funkcí, ale něčím úplně odlišným, nějakou speciální konstrukcí.


P.S. už to raději nebudu dál rozvíjet a půjdu spát, nechme to uležet :) Raději nechám taky prostor kolegům, pořád mám trochu svrbění, jestli jsem někde v té úvaze neudělal chybu, která by si zasloužila uvést na pravou míru :)

BoneFlute

  • *****
  • 1 981
    • Zobrazit profil
Re:Funkcionální programátor
« Odpověď #244 kdy: 05. 07. 2015, 02:36:36 »
Pokud ti jazyk zakazuje souběh, tak ho runtime nemůže udělat. Pokud jazyk nespecifikuje takovou situaci, pak ano.
Jazyk právě souběh nijak zakázat nemůže, to jde úplně mimo něj.
Já se právě domnívám, že čumil přišel s tezí, že IOMonády se o toto snaží, a neúspěšně, a že jsou jiné a lepší a hlavně funkční způsoby, kterými by to jít mělo.
Zda má pravdu či ne, to už je jiná.

Ty se domníváš, že jazyk nemůže zakázat souběh tak nějak z principu? Nebo jak to myslíš?


Nerozumím tomu, jak by mohl mět jeden jazyk více sémantik (významů výrazů)? Můžeš to rozvést?
Polopaticky řečeno, jazyk přece neřeší, co ty funkce opravdu dělají. Pro něj jsou to totální blackboxy. Zná jenom typ vstupů a typ výstupu, ale co se uvnitř opravdu děje, neřeší.

Příklad pro ten souběh: "ví" jazyk C, že fork spouští nějaký nový proces? Vůbec. Jak by ti jazyk jako takový mohl zakázat spustit nový proces, když on vůbec netuší a neřeší, co fork dělá. Pro něj je to prostě jenom "pid_t fork(void)" a pokud mu nedáváš žádný parametr a nechceš z něj dostat string, je happy :)

Pokud bys chtěl fork neumožnit, tak to uděláš třeba tak, že tvůj runtime vůbec nebude fci fork mít a nebude umožňovat volat systémová volání. A pak neforkneš ani kdyby ses na hlavu postavil. Ale jazyk za to nemůže, může za to runtime :)
Ano, funkce jako blackbox vnímám stejně. Zná jen typ vstupů a výstupů.

A teď k tomu souběhu:
Java-like jazyky souběh řeší výjimkou. Tu si odchytíš, a něco provedeš.
Pure funkcionální jazyky souběh neumožňují, protože to odporuje jejich filozofii.

Takže, když jsem to popsal takto, tak ano, funkce jsou totální černé skříňky, ale to neznamená, že si ta černá skříňka může dělat úplně co chce. Nemůže. V typovaných jazycích se musí zodpovídat deklarovanému typu, a v pure funkcionálních jazycích si nesmí dovolit (mimojiné) souběh. (V jazycích s GC překvapí, když dojde k memory-leaku, zatímco u takového C se to považuje za povinnost programátora.)

Ještě jeden příklad:
Budeme mět tu funkci sum :: Int -> Int -> Int. Tato funkce je implementována přímo v nějaké Cčkovské rutině, takže naprosto mimo kontrolu engine atd. Ale přestože je tato funkce blackbox, tak si nemůže dovolit (a věřím, že je to i nějak ošéfovaný) vracet string. To prostě nemůže. Nebo může?


Re:Funkcionální programátor
« Odpověď #245 kdy: 05. 07. 2015, 02:44:12 »
Ty se domníváš, že jazyk nemůže zakázat souběh tak nějak z principu? Nebo jak to myslíš?
Řekl bych to úplně jednoduše takhle: role jazyka jako takového končí tím, jestli program jde nebo nejde přeložit. Čili jestli je syntakticky a typově správný. Nic víc po jazyku jako takovém nemůžeš chtít. Nemůže nic tušit o nějakém souběhu, nemůže ti zaručit správnost výpočtu, nemůže ti uvařit kafe ani vyčistit bazén. Čili na otázku "Ty se domníváš, že jazyk nemůže vyčistit bazén tak nějak z principu?" bych asi odpověděl "ano, tak nějak z principu" ;)

Ale zároveň si myslím, že to je jenom terminologické nedorozumění, že totiž pod pojem "jazyk" zahrnuješ třeba i interpret, standardní knihovnu atd. Já pod tím pojmem teď myslím fakt jenom "pravidla správné syntaxe" + typový systém.

...a už toho vážně nechám :) dobrou noc a díky za debatu!

BoneFlute

  • *****
  • 1 981
    • Zobrazit profil
Re:Funkcionální programátor
« Odpověď #246 kdy: 05. 07. 2015, 02:45:35 »
Hele, nemůžeme si tykat?
Můžem. To vám, bylo tobě a Radkovi Míčkovi, a ostatním.

Představím si, že jsem kompilátor (naivní), tak bych z toho udělal switch, kde na základě toho první bajtu v souboru se rozhodnu jak budu pokračovat v dalších 256 cestách. Takhle si to představuji já, a takhle o tom uvažuji. Ale asi to stále není to, co máte na mysli.
Jediný, co jsem měl namysli, je ten rozdíl mezi programem, který žije v ideálním světě, kde nic není potřeba načítat a všechno je jenom statická relace, a skutečným světem, kde je potřeba dělat nějakou činnost. V tom ideálním světě tě nijak netrápí souběhy a ani o nich vůbec nemá smysl hovořit*, protože vše je statické, nic se nemusí vypočítat, nic se nespouští.
No, ale dyť jo. Jenže rozdíl je mezi mou naivní implementací 256pozičního switche, která vždycky vybere nějakou cestu, a tudíž je IMHO pure; a mezi jinou implementací, která se na něco ptá bůhví čeho, a při tom dotazu se zasekne a čeká, a čeká, a čeká... a to (opět IMHO) nesmí. Protože pak vzniká ten rozpor mezi ideálním světem, a tím skutečným.

Dobrou.

Re:Funkcionální programátor
« Odpověď #247 kdy: 05. 07. 2015, 02:48:16 »
a tudíž je IMHO pure
Ještě jednou: purity je podle mýho vlastnost jazyka a nedává žádný smysl ji vztahovat na runtime.

BoneFlute

  • *****
  • 1 981
    • Zobrazit profil
Re:Funkcionální programátor
« Odpověď #248 kdy: 05. 07. 2015, 02:50:40 »
Ty se domníváš, že jazyk nemůže zakázat souběh tak nějak z principu? Nebo jak to myslíš?
Řekl bych to úplně jednoduše takhle: role jazyka jako takového končí tím, jestli program jde nebo nejde přeložit. Čili jestli je syntakticky a typově správný. Nic víc po jazyku jako takovém nemůžeš chtít. Nemůže nic tušit o nějakém souběhu, nemůže ti zaručit správnost výpočtu, nemůže ti uvařit kafe ani vyčistit bazén. Čili na otázku "Ty se domníváš, že jazyk nemůže vyčistit bazén tak nějak z principu?" bych asi odpověděl "ano, tak nějak z principu" ;)

Ale zároveň si myslím, že to je jenom terminologické nedorozumění, že totiž pod pojem "jazyk" zahrnuješ třeba i interpret, standardní knihovnu atd. Já pod tím pojmem teď myslím fakt jenom "pravidla správné syntaxe" + typový systém.
Když ti typový systém umožní zajistit, aby návratová hodnota byla číslo, proč by nemohla hlídat čistotu bazénu? V čem je principielní rozdíl?


a tudíž je IMHO pure
Ještě jednou: purity je podle mýho vlastnost jazyka a nedává žádný smysl ji vztahovat na runtime.
Důvod takového dogmatu?

Re:Funkcionální programátor
« Odpověď #249 kdy: 05. 07. 2015, 02:59:18 »
Když ti typový systém umožní zajistit, aby návratová hodnota byla číslo, proč by nemohla hlídat čistotu bazénu? V čem je principielní rozdíl?
Myslím jako opravdu fyzicky vyčistit, asi nepodařenej vtip :)

Důvod takového dogmatu?
To není dogma. Ale neumím si představit, jak bys chtěl purity definovat tak, aby se vztahovala na runtime. Ty totiž mj. jako programátor vůbec netušíš, co runtime dělá. Možná sdružuje nějaké struktury, možná si něco cachuje, možná něco mění in-situ, protože si spočítal, že to v tenhle okamžik udělat může. Nevíš. Runtime by měl jenom dodržet sémantiku jazyka, nic víc nevíš.

Čili "pure runtime" mi přijde podobné jako "modrá myšlenka". Podle mě bys musel nadefinovat nějak zvláštně slovo "modrá", aby to dávalo nějaký smysl.

...a už ale fakt dobrou! :))

BoneFlute

  • *****
  • 1 981
    • Zobrazit profil
Re:Funkcionální programátor
« Odpověď #250 kdy: 05. 07. 2015, 03:20:45 »
Když ti typový systém umožní zajistit, aby návratová hodnota byla číslo, proč by nemohla hlídat čistotu bazénu? V čem je principielní rozdíl?
Myslím jako opravdu fyzicky vyčistit, asi nepodařenej vtip :)
Je to nadsázka, ale ano opravdu fyzicky vyčistit: fill :: CleanPool -> IO Pool.

Důvod takového dogmatu?
To není dogma. Ale neumím si představit, jak bys chtěl purity definovat tak, aby se vztahovala na runtime. Ty totiž mj. jako programátor vůbec netušíš, co runtime dělá. Možná sdružuje nějaké struktury, možná si něco cachuje, možná něco mění in-situ, protože si spočítal, že to v tenhle okamžik udělat může. Nevíš. Runtime by měl jenom dodržet sémantiku jazyka, nic víc nevíš.

Čili "pure runtime" mi přijde podobné jako "modrá myšlenka". Podle mě bys musel nadefinovat nějak zvláštně slovo "modrá", aby to dávalo nějaký smysl.
Omlouvám se, myslím, že už chápu. Ano, spíše bych to měl nazvat korektností, než čistotou. A ve smyslu právě korektnosti = jakože ten engine korektně spracuje předpis, jsem to myslel. Mám za to, že smysl mých příspěvků by to nemělo změnit. A za nevhodně zvolený výraz se omlouvám.

JSH

Re:Funkcionální programátor
« Odpověď #251 kdy: 05. 07. 2015, 10:38:53 »
Já se právě domnívám, že čumil přišel s tezí, že IOMonády se o toto snaží, a neúspěšně, a že jsou jiné a lepší a hlavně funkční způsoby, kterými by to jít mělo.
Zda má pravdu či ne, to už je jiná.
Jop, přesně tak. Jím vyzdvihovaný Clean neumožňuje race conditions. Ale ne proto že by ho UT nějak vylučoval. Prostě tam zatím nikdo ty plnotučná vlákna neimplementoval. Jen paralelní vyhodnocování výrazů, které je principilelně slabší a tím i bezpečnější.
Citace
Ty se domníváš, že jazyk nemůže zakázat souběh tak nějak z principu? Nebo jak to myslíš?
Svým způsobem může, ale není to až tak užitečné. I když zakážeme souběh uvnitř programu, stále je tu souběh se vším co běží mimo něj. IMO je to moc omezení a ve výsledku toho moc nepřinese.

Citace
Ještě jeden příklad:
Budeme mět tu funkci sum :: Int -> Int -> Int. Tato funkce je implementována přímo v nějaké Cčkovské rutině, takže naprosto mimo kontrolu engine atd. Ale přestože je tato funkce blackbox, tak si nemůže dovolit (a věřím, že je to i nějak ošéfovaný) vracet string. To prostě nemůže. Nebo může?
Je to ošéfované tak, že na základě typu C funkce očekává Haskell po zavolání funkce v registru RAX výsledný int. Pokud tam nebude, tak spokojeně schroupe jakýkoliv odpad, co tam najde. Nemá šanci poznat že je na tom intu něco špatně.

Krom toho ta funkce může dělat i milion dalších věcí nad rámec typu. Může vypisovat do konzole, přepisovat disk a podobně. Haskell může jenom věřit programátorovi, že tam nedělá žádné prasárny. Pokud jo, smůla.

Re:Funkcionální programátor
« Odpověď #252 kdy: 05. 07. 2015, 11:50:04 »
Svým způsobem může, ale není to až tak užitečné. I když zakážeme souběh uvnitř programu, stále je tu souběh se vším co běží mimo něj. IMO je to moc omezení a ve výsledku toho moc nepřinese.
Já bych celkem trval na tom, že ani tak nemůže :) Neumožnit to můžeš jedině na úrovni runtimu prostě tak, že tam nebude žádná funkce, která by spouštěla nové vlákno, nebudou tam C pluginy a nebudeš moct pouštět OS volání. Pro účely téhle debaty je podle mě nutný jazyk (syntaxe + typový systém) a runtime (sémantika, "výkonný stroj") odlišovat jako dvě různé věci.

Pořád nám zůstává otázka, jestli by nešel typový systém udělat tak, aby umožňoval běh ve víc vláknech a zároveň by nějakou typovou magií uměl poskytovat nějaké záruky ohledně těch vláken. Radek zmiňoval Rust a Mezzo. Já je neznám, takže neumím posoudit, jestli to takhle nějak dělají.

Greenhorn

Re:Funkcionální programátor
« Odpověď #253 kdy: 05. 07. 2015, 13:07:31 »
Jestli Vám mohu skočit do řeči. Když jsem si detailně pročítal tuto diskuzi. Narazil jsem na další způsob IO v čistém jazyce. Mluvil o tom čumil. Reaktivita. Má s ní někdo tady zkušenost? Zkoušel jsem čumilem doporučovaný jazyk Elm, a je to opravdu hodně, hodně zajímavé z mého laického pohledu.

v

Re:Funkcionální programátor
« Odpověď #254 kdy: 05. 07. 2015, 13:16:37 »
Rust vs. race condition:
https://news.ycombinator.com/item?id=7009502
všimněte si jak rozlišují "race condition" a "data race"

poznámka bokem - překládalo se "race condition" vždycky jako "souběh"? na střední jsme tomu říkali "hazard" nebo "hazardní stav"