Funkcionální programátor

Radek Miček

Re:Funkcionální programátor
« Odpověď #165 kdy: 01. 07. 2015, 22:57:40 »
Mě tam zase zaujalo to vztekání se ohledně Race Condition. Je fakt, že když je něco funkcionální podle té čumilově definice, tak k souběhu nesmí dojít. Představuji si naivní situaci, kdy jedna funkce v sobě volá jinou funkci, která čeká na vrácení hodnoty předchozí funkce. Každopádně, když použiji dvě funkce (forknuté ze stejného IO), které čtou ze stejného souboru (zamčeného), tak se prostě zaseknou bez ohledu na to, že jsou monadické. (Trošku vařím z vody, k forkIO jsem se ještě nedostal.) A vzhledem k tomu, že se zaseknou, tak je porušena funkcionálnost.

Ty funkce se nezaseknou - normálně doběhnou a vrátí hodnotu typu IO a pro nějaké a. Vrácené hodnoty se pak skombinují pomocí >>= z IO monády a vznikne jedna obří hodnota IO () - tu vrátí funkce main - žádný vedlejší efekt se neprovede, nic se nezasekne.


já bych řekl, že třeba systémové volání v IO se zaseknout může

Ano, ale váš kód žádné systémové volání neprovádí. Ten pouze vrací popis, jaké systémové volání se má provést (popis typu IO a).


BoneFlute

  • *****
  • 1 981
    • Zobrazit profil
Re:Funkcionální programátor
« Odpověď #166 kdy: 01. 07. 2015, 23:02:01 »
Takže otevřu soubor, získám instanci na ten soubor (definovanou jako UT), takže ten soubor už nemůžu otevřít jinde a získat druhou instanci na ten souboru?
Jestli se soubor nedá otevřít jinde musí hlídat OS. Protože musí hlídat i jiné procesy. Je to o něčem jiném.
Pokud soubor otevřu pro čtení, tak nemusí být unikátní. Můžu si handle zkopírovat a ten soubor předat 10 různým funkcím. Na všech místech dostanu stejná data.
Pokud otevřu soubor pro čtení i zápis, tak dostanu unikátní referenci na něj. Teď ten soubor nemůžu číst z více míst, protože zápis z jednoho místa by ten soubor změnil a na druhém míste bych dostal jiná data. Další funkci ho můžu předat až mi ho ta první zase vrátí. Samozřejmě se to dá obejít, třeba ten soubor otevřít vícekrát. Takže to chrání hlavně před chybami.
Tak samozřejmě se bavíme o otevření na více místech v rámci toho programu. A předpokládáme, že do toho souboru jiný program nezasahuje. Je to ideální případ pro ilustraci.


Takže otevřu soubor, získám instanci na ten soubor (definovanou jako UT), takže ten soubor už nemůžu otevřít jinde a získat druhou instanci na ten souboru?
Pokud otevřu soubor pro čtení i zápis, tak dostanu unikátní referenci na něj. Teď ten soubor nemůžu číst z více míst, protože zápis z jednoho místa by ten soubor změnil a na druhém míste bych dostal jiná data. Další funkci ho můžu předat až mi ho ta první zase vrátí. Samozřejmě se to dá obejít, třeba ten soubor otevřít vícekrát. Takže to chrání hlavně před chybami.
Jak to myslíš, že se to dá obejít? V rámci jedné aplikace se v jednom vlákně otevře soubor jako UT, a v jiném vlákně si ho otevřu taky? No tak to je mi ten UT dost k ničemu, když mám dvě reference na to samé. (Považuji to za dvě stejné reference, protože je to jen obálka nad tím souborem. Jak si systém zajistí, aby to tak bylo, už je implementační detail.)

BoneFlute

  • *****
  • 1 981
    • Zobrazit profil
Re:Funkcionální programátor
« Odpověď #167 kdy: 01. 07. 2015, 23:05:57 »
Mě tam zase zaujalo to vztekání se ohledně Race Condition. Je fakt, že když je něco funkcionální podle té čumilově definice, tak k souběhu nesmí dojít. Představuji si naivní situaci, kdy jedna funkce v sobě volá jinou funkci, která čeká na vrácení hodnoty předchozí funkce. Každopádně, když použiji dvě funkce (forknuté ze stejného IO), které čtou ze stejného souboru (zamčeného), tak se prostě zaseknou bez ohledu na to, že jsou monadické. (Trošku vařím z vody, k forkIO jsem se ještě nedostal.) A vzhledem k tomu, že se zaseknou, tak je porušena funkcionálnost.

Ty funkce se nezaseknou - normálně doběhnou a vrátí hodnotu typu IO a pro nějaké a. Vrácené hodnoty se pak skombinují pomocí >>= z IO monády a vznikne jedna obří hodnota IO () - tu vrátí funkce main - žádný vedlejší efekt se neprovede, nic se nezasekne.


já bych řekl, že třeba systémové volání v IO se zaseknout může

Ano, ale váš kód žádné systémové volání neprovádí. Ten pouze vrací popis, jaké systémové volání se má provést (popis typu IO a).

Takže tu máme jazyk Haskell, který je čistě funkcionální, a pak interprety/kompilátory, který ty jazyky neimplementují přesně? Takže když napíši program v Haskellu vracející IO se systémovým voláním, které vede k souběhu, tak neexistuje implementace kompilátoru, která by si s tím poradila. Správně?

BoneFlute

  • *****
  • 1 981
    • Zobrazit profil
Re:Funkcionální programátor
« Odpověď #168 kdy: 01. 07. 2015, 23:09:45 »

Obecně typový systém nic (takového) negarantuje. Například, říká-li typový systém, že výraz má typ int, neznamená to, že když výraz vyhodnotíte, tak dostanete celé číslo - klidně můžete dostat řetězec nebo instanci třídy Pes nebo něco úplně jiného.

Celé číslo byste dostal, pokud by byl typový systém korektní (sound) vzhledem k nějaké (operační) sémantice.

Typový systém mi zabrání přeložit program, který používá funkci, jenž podle signatury má vracet int, ale nevrací. Záleží na tom, zda to nazveš korektností, nebo garancí? Program z toho nevytvořím, takže mi to přijde garantovaný ažaž.

Radek Miček

Re:Funkcionální programátor
« Odpověď #169 kdy: 01. 07. 2015, 23:16:10 »
Mě tam zase zaujalo to vztekání se ohledně Race Condition. Je fakt, že když je něco funkcionální podle té čumilově definice, tak k souběhu nesmí dojít. Představuji si naivní situaci, kdy jedna funkce v sobě volá jinou funkci, která čeká na vrácení hodnoty předchozí funkce. Každopádně, když použiji dvě funkce (forknuté ze stejného IO), které čtou ze stejného souboru (zamčeného), tak se prostě zaseknou bez ohledu na to, že jsou monadické. (Trošku vařím z vody, k forkIO jsem se ještě nedostal.) A vzhledem k tomu, že se zaseknou, tak je porušena funkcionálnost.

Ty funkce se nezaseknou - normálně doběhnou a vrátí hodnotu typu IO a pro nějaké a. Vrácené hodnoty se pak skombinují pomocí >>= z IO monády a vznikne jedna obří hodnota IO () - tu vrátí funkce main - žádný vedlejší efekt se neprovede, nic se nezasekne.


já bych řekl, že třeba systémové volání v IO se zaseknout může

Ano, ale váš kód žádné systémové volání neprovádí. Ten pouze vrací popis, jaké systémové volání se má provést (popis typu IO a).

Takže když napíši program v Haskellu vracející IO se systémovým voláním, které vede k souběhu, tak neexistuje implementace kompilátoru, která by si s tím poradila.

Váš program v Haskellu, vaše funkce main vrací popis toho, jaká systémová volání se mají provést. Funkce main čistá, jelikož vrací pokaždé stejný popis.

Spuštění toho popisu není součástí vašeho programu - ať to spuštění popisu vede k čemukoliv, tak to nemá vliv na to, zda je jazyk čistě funkcionální. Programy v čistě funkcionálních jazycích tak mohou dělat vše co programy v jiných jazycích - ručně alokovat paměť, přistupovat na určité adresy v paměti, způsobovat race conditions.


v

Re:Funkcionální programátor
« Odpověď #170 kdy: 01. 07. 2015, 23:18:04 »
Mě tam zase zaujalo to vztekání se ohledně Race Condition. Je fakt, že když je něco funkcionální podle té čumilově definice, tak k souběhu nesmí dojít. Představuji si naivní situaci, kdy jedna funkce v sobě volá jinou funkci, která čeká na vrácení hodnoty předchozí funkce. Každopádně, když použiji dvě funkce (forknuté ze stejného IO), které čtou ze stejného souboru (zamčeného), tak se prostě zaseknou bez ohledu na to, že jsou monadické. (Trošku vařím z vody, k forkIO jsem se ještě nedostal.) A vzhledem k tomu, že se zaseknou, tak je porušena funkcionálnost.

Ty funkce se nezaseknou - normálně doběhnou a vrátí hodnotu typu IO a pro nějaké a. Vrácené hodnoty se pak skombinují pomocí >>= z IO monády a vznikne jedna obří hodnota IO () - tu vrátí funkce main - žádný vedlejší efekt se neprovede, nic se nezasekne.


já bych řekl, že třeba systémové volání v IO se zaseknout může

Ano, ale váš kód žádné systémové volání neprovádí. Ten pouze vrací popis, jaké systémové volání se má provést (popis typu IO a).

a co tohle:

import Control.Concurrent.MVar

main = do
   v <- newMVar 0
   takeMVar v
   print 1
   takeMVar v
   print 2

BoneFlute

  • *****
  • 1 981
    • Zobrazit profil
Re:Funkcionální programátor
« Odpověď #171 kdy: 01. 07. 2015, 23:24:13 »
Takže když napíši program v Haskellu vracející IO se systémovým voláním, které vede k souběhu, tak neexistuje implementace kompilátoru, která by si s tím poradila.

Váš program v Haskellu, vaše funkce main vrací popis toho, jaká systémová volání se mají provést. Funkce main čistá, jelikož vrací pokaždé stejný popis.

Spuštění toho popisu není součástí vašeho programu - ať to spuštění popisu vede k čemukoliv, tak to nemá vliv na to, zda je jazyk čistě funkcionální. Programy v čistě funkcionálních jazycích tak mohou dělat vše co programy v jiných jazycích - ručně alokovat paměť, přistupovat na určité adresy v paměti, způsobovat race conditions.

Tomu, že IOMonáda je popis já, věřím, že dostatečně, rozumím.

Vás bych ale poprosil zda byste odpověděl na otázku: Když napíšu v Haskellu jakožto pure funkcionálním jazyku program který je schopen vést k souběhu, tak mám či nemám k dispozici kompilátor, který je schopen jej přeložit tak, aby k souběhu nedošlo (páč souběh odporuje definici funkcionality).

lkm

Re:Funkcionální programátor
« Odpověď #172 kdy: 01. 07. 2015, 23:28:32 »
Spuštění toho popisu není součástí vašeho programu - ať to spuštění popisu vede k čemukoliv, tak to nemá vliv na to, zda je jazyk čistě funkcionální. Programy v čistě funkcionálních jazycích tak mohou dělat vše co programy v jiných jazycích - ručně alokovat paměť, přistupovat na určité adresy v paměti, způsobovat race conditions.

To se kardinálně pletete, funkcionální program může nanejvýš vyblít skript pro nefunkcionální část a tím to hasne. Pak musí nastoupit nefunkcionální programátor a tento musí napsat nefunkcionální interpret toho nefunkcionálního skriptu. Tvrzení že když může funkcionální program vyblít skript tak může všechno, je od základu pomýlené.

Radek Miček

Re:Funkcionální programátor
« Odpověď #173 kdy: 01. 07. 2015, 23:32:24 »

Obecně typový systém nic (takového) negarantuje. Například, říká-li typový systém, že výraz má typ int, neznamená to, že když výraz vyhodnotíte, tak dostanete celé číslo - klidně můžete dostat řetězec nebo instanci třídy Pes nebo něco úplně jiného.

Celé číslo byste dostal, pokud by byl typový systém korektní (sound) vzhledem k nějaké (operační) sémantice.

Typový systém mi zabrání přeložit program, který používá funkci, jenž podle signatury má vracet int, ale nevrací.

Obecně nic takového neplatí - typový systém a operační sémantika jsou dvě nezávislé věci. Například jazyky Dart a Typescript mají záměrně nekorektní typové systémy.

Citace
Záleží na tom, zda to nazveš korektností, nebo garancí? Program z toho nevytvořím, takže mi to přijde garantovaný ažaž.

Korektností (angl. soundness) myslím přesně definovanou věc. Součástí důkazu korektnosti bývá věta "preservation", která říká, že se typ termu během vyhodnocování nemění (což mj. ne ve všech jazycích platí).

Radek Miček

Re:Funkcionální programátor
« Odpověď #174 kdy: 01. 07. 2015, 23:37:40 »
Vás bych ale poprosil zda byste odpověděl na otázku: Když napíšu v Haskellu jakožto pure funkcionálním jazyku program který je schopen vést k souběhu, tak mám či nemám k dispozici kompilátor, který je schopen jej přeložit tak, aby k souběhu nedošlo (páč souběh odporuje definici funkcionality).

Nevím, zda takový kompilátor existuje.

Pokud neexistuje, ničemu to nevadí - nic to nemění na věci, že všechny výrazy v Haskellu (až na unsafePerformIO apod.) jsou referenčně transparentní.

Re:Funkcionální programátor
« Odpověď #175 kdy: 01. 07. 2015, 23:47:59 »
Obecně nic takového neplatí - typový systém a operační sémantika jsou dvě nezávislé věci. Například jazyky Dart a Typescript mají záměrně nekorektní typové systémy.
Můžeš tohle prosím rozvést nebo dát nějaký odkaz? Zajímalo by mě, jak přesně nekorektní a jaký je ten záměr (k čemu to má vést).

BoneFlute

  • *****
  • 1 981
    • Zobrazit profil
Re:Funkcionální programátor
« Odpověď #176 kdy: 01. 07. 2015, 23:53:33 »
Vás bych ale poprosil zda byste odpověděl na otázku: Když napíšu v Haskellu jakožto pure funkcionálním jazyku program který je schopen vést k souběhu, tak mám či nemám k dispozici kompilátor, který je schopen jej přeložit tak, aby k souběhu nedošlo (páč souběh odporuje definici funkcionality).

Nevím, zda takový kompilátor existuje.

Pokud neexistuje, ničemu to nevadí - nic to nemění na věci, že všechny výrazy v Haskellu (až na unsafePerformIO apod.) jsou referenčně transparentní.
Pokud to nevíte vy, tak to pro mě znamená, že neexistuje :-)

Všechny výrazy v Haskellu odpovídají ideálům FP, ale když se v praxi na ně nemůžete spolehnout, tak bohužel platí, že:
jak vidno, FP má opravdu velmi mnoho výhod, a nedodržení podmínek FP nás v jazycích pak stojí vysokou cenu.

Všechny výrazy v Haskellu jsou referenčně transparentní... ale čistě teoreticky, dokavad to nechcete použít.

Pak se tedy obávám, že vyskakování čumila je více než dost pochopitelné, když věnujete čas, úsilí a peníze do něčeho, co vám slibuje něco co nakonec nedodrží. Asi bych vyskakoval taky, když bych si Haskell nezamiloval kůli něčemu jinému.

Radek Miček

Re:Funkcionální programátor
« Odpověď #177 kdy: 02. 07. 2015, 00:01:51 »
Obecně nic takového neplatí - typový systém a operační sémantika jsou dvě nezávislé věci. Například jazyky Dart a Typescript mají záměrně nekorektní typové systémy.
Můžeš tohle prosím rozvést nebo dát nějaký odkaz? Zajímalo by mě, jak přesně nekorektní a jaký je ten záměr (k čemu to má vést).

Kvůli pohodlí programátorů - viz Unsound and Incomplete. Nebo Why Dart Types Are Optional and Unsound nebo oficiální manuál TypeScriptu.

Radek Miček

Re:Funkcionální programátor
« Odpověď #178 kdy: 02. 07. 2015, 00:07:12 »
Všechny výrazy v Haskellu odpovídají ideálům FP, ale když se v praxi na ně nemůžete spolehnout, tak bohužel platí, že:
jak vidno, FP má opravdu velmi mnoho výhod, a nedodržení podmínek FP nás v jazycích pak stojí vysokou cenu.

Všechny výrazy v Haskellu jsou referenčně transparentní... ale čistě teoreticky, dokavad to nechcete použít.

Ale ty výrazy jsou referenčně transparentní i prakticky a GHC toho využívá při optimalizacích - například Stream Fusion, nebo obecně uživatelem definovaná přepisovací pravidla - kdyby ten jazyk nebyl čistý, tohle by bylo mnohem obtížnější.

Radek Miček

Re:Funkcionální programátor
« Odpověď #179 kdy: 02. 07. 2015, 00:24:17 »
odpovídají ideálům FP, ale když se v praxi na ně nemůžete spolehnout, tak bohužel platí, že:

Pokud hledáte typový systém, který zabrání vzniku race conditions, tak můžete zkusit Rust (jeho bezpečný fragment) nebo Mezzo.

Ani jeden z nich není čistě funkcionální.