Funkcionální programátor

Re:Funkcionální programátor
« Odpověď #360 kdy: 08. 07. 2015, 00:44:55 »
Tu logiku nechápu. Proč bych se nemohl monády zbavit? Maybe, nebo Either se zbavit lze. Jak vzniká souvislost, že: "kdyby to bylo možné, pak by Haskell čistý nebyl. Možné to není a Haskell čistý je."? Naopak mě přijde, že díky tomu, že IOMonádu nelze substituovat, tak to znamená, že není čistá.
Pokud máš někde proměnnou "a" typu IO Num, tak nemůžeš provést něco jako "runIO a", dostat z ní ten integer a dál pokračovat čistě jenom s integerem. Vždycky musíš začít v IO monádě (main fce) - z ní můžeš tímpádem mít větve, které taky provádí IO. Nemůžeš ale IO větev naroubovat na ne-IO větev. Aspoň myslím teda ;)


Re:Funkcionální programátor
« Odpověď #361 kdy: 08. 07. 2015, 00:45:49 »
IO Num
Vlastně Num by musel být constraint, ale tak rozumíme si že jo ;)

Greenhorn

Re:Funkcionální programátor
« Odpověď #362 kdy: 08. 07. 2015, 00:47:31 »
Stav je ve FRP uchován ve zpětných signálních vazbách. Neměnní se, pokaždé se vytvoří jeho modifikovaná kopie, a pošle se signálem dál.
Což je přesně tentýž princip jako mají monády, máš to o asi tři příspěvky výš ;) Akorát teda samotné IO žádný stav nepřenáší, ale kdybys chtěl, můžeš si ho tam dát.
Musím nesouhlasit. Vyzkoušel jste si FRP? Porovnávat IO monádu a FRP je silně podivné i pro začátečníka jako jsem já. FRP nezná měnitelný stav. Není tam nikde, stejně jako vedlejší efekty, a podle toho vypadá a chová se i kód. Neexistuje tam nic jako měnitelná reference, a ani něco takového není třeba. IO monáda a FRP je něco naprosto kategoricky odlišného. Toto už je za hranicí, to už cítím jako demagogie. 

Greenhorn

Re:Funkcionální programátor
« Odpověď #363 kdy: 08. 07. 2015, 00:48:41 »
Tu logiku nechápu. Proč bych se nemohl monády zbavit? Maybe, nebo Either se zbavit lze. Jak vzniká souvislost, že: "kdyby to bylo možné, pak by Haskell čistý nebyl. Možné to není a Haskell čistý je."? Naopak mě přijde, že díky tomu, že IOMonádu nelze substituovat, tak to znamená, že není čistá.
Pokud máš někde proměnnou "a" typu IO Num, tak nemůžeš provést něco jako "runIO a", dostat z ní ten integer a dál pokračovat čistě jenom s integerem. Vždycky musíš začít v IO monádě (main fce) - z ní můžeš tímpádem mít větve, které taky provádí IO. Nemůžeš ale IO větev naroubovat na ne-IO větev. Aspoň myslím teda ;)
O tom jsem mluvil. Není to možné prostě proto, že IO není deterministické, neboli čisté.

Greenhorn

Re:Funkcionální programátor
« Odpověď #364 kdy: 08. 07. 2015, 00:51:43 »
Ale kdepak. Prostě C je čistě funkcionální, a jakákoli funkce která má vedlejší efekty je ve výsledku jen lambda, kterou interpretuje runtime. Všechno je krásně čisté. Ještě potřebujeme ty monády, aby to mělo všechny náležitosti.
C není čistý, protože když dvakrát po sobě zavolám random(), vrátí mi pokaždé jinou hodnotu. V Haskellu nic takového není možné a proto je čistý.

To, že "a <- get" VYPADÁ jako volání funkce, na tom nic nemění, protože to volání fce NENÍ.
Ale je

random :: IO Int
random = ...

úplně to samé. A teď budeme tvrdit, že v Cčku random() vrátí jen lambdu kterou interpretuje runtime.


BoneFlute

  • *****
  • 2 047
    • Zobrazit profil
Re:Funkcionální programátor
« Odpověď #365 kdy: 08. 07. 2015, 00:53:07 »
Tu logiku nechápu. Proč bych se nemohl monády zbavit? Maybe, nebo Either se zbavit lze. Jak vzniká souvislost, že: "kdyby to bylo možné, pak by Haskell čistý nebyl. Možné to není a Haskell čistý je."? Naopak mě přijde, že díky tomu, že IOMonádu nelze substituovat, tak to znamená, že není čistá.
Pokud máš někde proměnnou "a" typu IO Num, tak nemůžeš provést něco jako "runIO a", dostat z ní ten integer a dál pokračovat čistě jenom s integerem. Vždycky musíš začít v IO monádě (main fce) - z ní můžeš tímpádem mít větve, které taky provádí IO. Nemůžeš ale IO větev naroubovat na ne-IO větev. Aspoň myslím teda ;)
Proč musím? Proč je to tak správně? A proč to znamená, že když by to bylo možné, tak by Haskell čistý nebyl?

Kód: [Vybrat]
unpackMonad :: Maybe Int -> Int
unpackMonad Nothing = 0
unpackMonad Maybe i = i
 

Re:Funkcionální programátor
« Odpověď #366 kdy: 08. 07. 2015, 00:56:07 »
Musím nesouhlasit. Vyzkoušel jste si FRP? Porovnávat IO monádu a FRP je silně podivné i pro začátečníka jako jsem já. FRP nezná měnitelný stav. Není tam nikde, stejně jako vedlejší efekty, a podle toho vypadá a chová se i kód. Neexistuje tam nic jako měnitelná reference, a ani něco takového není třeba. IO monáda a FRP je něco naprosto kategoricky odlišného. Toto už je za hranicí, to už cítím jako demagogie.
Ale monáda taky nic nemění, ani IO monáda. Říkám, máš to o pár příspěvků výš:

"Ona je to maskovaná funkce World -> (a, World)"

- vidíš to? Vezmu svět, aplikuju na něj něco, mám nový svět. Na nový svět opět aplikuju něco atd. Pořád ti to nepřijde podobné streamům? Neříkám, že je to totéž, ale ten způsob je velmi podobný. Akorátže u monád to máš celé zabalené do syntaktického cukru, aby to vypadalo rádobyimperativně.

O tom jsem mluvil. Není to možné prostě proto, že IO není deterministické, neboli čisté.
Ne. Není to možné přesně z opačného důvodu, kdyby taková funkce existovala, tak potom by to čisté nebylo. Teď to čisté je.

Ale je

random :: IO Int
random = ...

úplně to samé. A teď budeme tvrdit, že v Cčku random() vrátí jen lambdu kterou interpretuje runtime.
Není ani trochu. Protože IO Int není Int. Z IO Int nikdy Int nedostaneš, což je přesně to, co ti říkám výš.

Proč musím? Proč je to tak správně? A proč to znamená, že když by to bylo možné, tak by Haskell čistý nebyl?

Kód: [Vybrat]
unpackMonad :: Maybe Int -> Int
unpackMonad Nothing = 0
unpackMonad Maybe i = i

No protože pokud by tohle šlo udělat s IO monádou, tak bys právě dostal různé hodnoty pro různá volání funkce, a to prostě nesmíš dostat :)

U Maybe to nevadí, protože tam je předem jasné, co uvnitř je, a nemůže to být chvilku takhle a chvilku jinak.

BoneFlute

  • *****
  • 2 047
    • Zobrazit profil
Re:Funkcionální programátor
« Odpověď #367 kdy: 08. 07. 2015, 01:02:09 »
Ne. Není to možné přesně z opačného důvodu, kdyby taková funkce existovala, tak potom by to čisté nebylo. Teď to čisté je.
Kuc, kuc...

Proč musím? Proč je to tak správně? A proč to znamená, že když by to bylo možné, tak by Haskell čistý nebyl?

Kód: [Vybrat]
unpackMonad :: Maybe Int -> Int
unpackMonad Nothing = 0
unpackMonad Maybe i = i

No protože pokud by tohle šlo udělat s IO monádou, tak bys právě dostal různé hodnoty pro různá volání funkce, a to prostě nesmíš dostat :)
To už je lepší.

Jenže stále to neřeší ten problém. Stavím na tom, že substituce výrazů je podmínka pro označení jazyka za (pure) funkcionální. Tím, že jsi to zakázal befelem, jsi tu substituci neumožnil.

Greenhorn

Re:Funkcionální programátor
« Odpověď #368 kdy: 08. 07. 2015, 01:03:55 »
Musím nesouhlasit. Vyzkoušel jste si FRP? Porovnávat IO monádu a FRP je silně podivné i pro začátečníka jako jsem já. FRP nezná měnitelný stav. Není tam nikde, stejně jako vedlejší efekty, a podle toho vypadá a chová se i kód. Neexistuje tam nic jako měnitelná reference, a ani něco takového není třeba. IO monáda a FRP je něco naprosto kategoricky odlišného. Toto už je za hranicí, to už cítím jako demagogie.
Ale monáda taky nic nemění, ani IO monáda. Říkám, máš to o pár příspěvků výš:

"Ona je to maskovaná funkce World -> (a, World)"

- vidíš to? Vezmu svět, aplikuju na něj něco, mám nový svět. Na nový svět opět aplikuju něco atd. Pořád ti to nepřijde podobné streamům? Neříkám, že je to totéž, ale ten způsob je velmi podobný. Akorátže u monád to máš celé zabalené do syntaktického cukru, aby to vypadalo rádobyimperativně.

O tom jsem mluvil. Není to možné prostě proto, že IO není deterministické, neboli čisté.
Ne. Není to možné přesně z opačného důvodu, kdyby taková funkce existovala, tak potom by to čisté nebylo. Teď to čisté je.

Ale je

random :: IO Int
random = ...

úplně to samé. A teď budeme tvrdit, že v Cčku random() vrátí jen lambdu kterou interpretuje runtime.
Není ani trochu. Protože IO Int není Int. Z IO Int nikdy Int nedostaneš, což je přesně to, co ti říkám výš.

Proč musím? Proč je to tak správně? A proč to znamená, že když by to bylo možné, tak by Haskell čistý nebyl?

Kód: [Vybrat]
unpackMonad :: Maybe Int -> Int
unpackMonad Nothing = 0
unpackMonad Maybe i = i

No protože pokud by tohle šlo udělat s IO monádou, tak bys právě dostal různé hodnoty pro různá volání funkce, a to prostě nesmíš dostat :)

U Maybe to nevadí, protože tam je předem jasné, co uvnitř je, a nemůže to být chvilku takhle a chvilku jinak.
Takže, chci vysvětlení jak to že je možné v Haskellu 1:1 namapovat kód v Cčku i se všemi měnitelnými proměnnými a funkcemi do IO monády a tento kód se chová stejně jako kód v Cčku. Pokud trváte na tom že je to čistý kód, pak i samotné Cčko je čisté, stačí mu skutečně jen přidat ty monády a tvrdit to samé co u Haskellu.

Re:Funkcionální programátor
« Odpověď #369 kdy: 08. 07. 2015, 01:06:09 »
Jenže stále to neřeší ten problém. Stavím na tom, že substituce výrazů je podmínka pro označení jazyka za (pure) funkcionální. Tím, že jsi to zakázal befelem, jsi tu substituci neumožnil.
Říkám, že v čistém jazyce nemůžeš při dvou volání stejné fce se stejnými argumenty dostat něco jiného. Pokud by runIO existovalo, tak prostě uděláš dvakrát po sobě "runIO a" a pokaždé dostaneš něco jiného. Takže:

jazyk je čistý -> v jazyce nemůže existovat runIO

...ne naopak!

Greenhorn

Re:Funkcionální programátor
« Odpověď #370 kdy: 08. 07. 2015, 01:07:29 »
Jenže stále to neřeší ten problém. Stavím na tom, že substituce výrazů je podmínka pro označení jazyka za (pure) funkcionální. Tím, že jsi to zakázal befelem, jsi tu substituci neumožnil.
Říkám, že v čistém jazyce nemůžeš při dvou volání stejné fce se stejnými argumenty dostat něco jiného. Pokud by runIO existovalo, tak prostě uděláš dvakrát po sobě "runIO a" a pokaždé dostaneš něco jiného. Takže:

jazyk je čistý -> v jazyce nemůže existovat runIO

...ne naopak!
A proč by vrátilo runIO něco jiného při opakovaném volání. IO monáda je přece čistá.

Re:Funkcionální programátor
« Odpověď #371 kdy: 08. 07. 2015, 01:10:40 »
Takže, chci vysvětlení jak to že je možné v Haskellu 1:1 namapovat kód v Cčku i se všemi měnitelnými proměnnými a funkcemi do IO monády a tento kód se chová stejně jako kód v Cčku. Pokud trváte na tom že je to čistý kód, pak i samotné Cčko je čisté, stačí mu skutečně jen přidat ty monády a tvrdit to samé co u Haskellu.
Není to možné a ten kód se NECHOVÁ stejně.

Kód A:
Kód: [Vybrat]
int a = random();
int b = random();

(pseudo)kód B:
Kód: [Vybrat]
a <- random
b <- random

To, že A a B vypadá na pohled stejně, vůbec nic neznamená. Význam toho kódu je úplně jiný. Ten první kód dvakrát volá tutéž fci, ten druhý kód ve skutečnosti vytváří jakési lambdy, ty jaksi skládá za sebe pomocí jakéhosi fakového RealWorld.

V Haskellu prostě platí, že když dvakrát zavolám tutéž ***FUNKCI*** dvakrát, vrátí mi vždy to samé. "a <- random" ***NENí*** volání funkce. I kdyby tak ta syntaxe klidně stokrát vypadala. Není. Není a není. Tečka.

:)))

Re:Funkcionální programátor
« Odpověď #372 kdy: 08. 07. 2015, 01:11:43 »
A proč by vrátilo runIO něco jiného při opakovaném volání. IO monáda je přece čistá.
Definuj "IO monáda je čistá". Striktně a přesně.

Greenhorn

Re:Funkcionální programátor
« Odpověď #373 kdy: 08. 07. 2015, 01:18:25 »
A proč by vrátilo runIO něco jiného při opakovaném volání. IO monáda je přece čistá.
Definuj "IO monáda je čistá". Striktně a přesně.
Referenčně transparentní.

BoneFlute

  • *****
  • 2 047
    • Zobrazit profil
Re:Funkcionální programátor
« Odpověď #374 kdy: 08. 07. 2015, 01:19:54 »
Jenže stále to neřeší ten problém. Stavím na tom, že substituce výrazů je podmínka pro označení jazyka za (pure) funkcionální. Tím, že jsi to zakázal befelem, jsi tu substituci neumožnil.
Říkám, že v čistém jazyce nemůžeš při dvou volání stejné fce se stejnými argumenty dostat něco jiného. Pokud by runIO existovalo, tak prostě uděláš dvakrát po sobě "runIO a" a pokaždé dostaneš něco jiného. Takže:

jazyk je čistý -> v jazyce nemůže existovat runIO

...ne naopak!
O runIO nejde. Jde o to, že nejde udělat substituci výrazu.

Jazyk je čistý, pokud mohu, mimo jiné, provádět nahrazení výrazu její hodnotou - alespoň takhle jsem to vždycky četl. O runIO tam nic nebylo :-)

Když budu mět kdekoliv v kódu číslo, tak ho mohu bezezbytku přetavit na Maybe monádu. A naopak. Zatímco když budu mět to samé v IOMonádě, tak se jí, jako jediné, nezbavím. A při všech transformacích ji tam budu tahat jak vocásek. To znamená, že ta substituce se provede - ale s ocáskem. A možná proto bych ji za čistou neprohlásil.