Funkcionální programátor

Radek Miček

Re:Funkcionální programátor
« Odpověď #375 kdy: 08. 07. 2015, 01:21:16 »
Vaše argumenty lze po mírné modifikaci nasadit na jakýkoli jazyk, a poté tvrdit že je čistý. Stačí jen vytvořit monády. což není problém.

Na jakýkoliv jazyk to nasadit nejde - musel byste změnit definici toho jazyka.

Například jednoduchý jazyk, na nějž to nejde nasadit, je ML kalkulus - popis sémantiky na straně 395.
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 takhle není definováno (bohužel C není formálně definováno - proto jsem dal jako příklad ML kalkulus).


Greenhorn

Re:Funkcionální programátor
« Odpověď #376 kdy: 08. 07. 2015, 01:22:11 »
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.

:)))
Překvapivě se chová stejně. GTK2hs je přesně 1:1 namapovaná knihovna. Pokud ji používám, kód má strukturu stejnou jako v Cčku, a stejně se i chová. Opět opakuji, stačí přidat do Cčka monády, IO strčit do lamdb, a máme pure C. Nebo alespoň pure C z Vašeho pohledu.

Re:Funkcionální programátor
« Odpověď #377 kdy: 08. 07. 2015, 01:22:44 »
Referenčně transparentní.
Co je referenčně transparentní? Referenčně transparentní může být jenom JAZYK.

Typ "IO Int" je prostě datový typ. Proměnná "a" typu "IO Int" jsou prostě nějaká DATA. Představ si to tak, že ta data je string s instrukcemi pro IO, třeba: "Načti další byte ze souboru f". Pokud bys měl funkci runIO, tak ji zavoláš poprvé:

runIO a = runIO "Načti další byte ze souboru f" = Byte1

...a podruhé:

runIO a = runIO "Načti další byte ze souboru f" = Byte2

Totéž volání fce "runIO" s týmž argumentem "a" ti dalo různý výsledek. A to se v čistém jazyce nesmí stát. Proto runIO v Haskellu nemůže existovat.

Greenhorn

Re:Funkcionální programátor
« Odpověď #378 kdy: 08. 07. 2015, 01:26:55 »
Vaše argumenty lze po mírné modifikaci nasadit na jakýkoli jazyk, a poté tvrdit že je čistý. Stačí jen vytvořit monády. což není problém.

Na jakýkoliv jazyk to nasadit nejde - musel byste změnit definici toho jazyka.

Například jednoduchý jazyk, na nějž to nejde nasadit, je ML kalkulus - popis sémantiky na straně 395.
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 takhle není definováno (bohužel C není formálně definováno - proto jsem dal jako příklad ML kalkulus).
Tak ho tak prostě definujeme, stačí jenom přidat IO monádu, a máme pure C. Nebo si můžeme udělat nový jazyk PureC s vlastní definicí se základem v Cčku. Nejlepší na tom je, že nebudeme muset psát jiný kompiler. Je to jen hra se slovy.

Re:Funkcionální programátor
« Odpověď #379 kdy: 08. 07. 2015, 01:28:45 »
O runIO nejde. Jde o to, že nejde udělat substituci výrazu.
Reagoval jsi na příspěvek, ve kterém jsem říkal, proč runIO v Haskellu nemůže existovat. Proto o něm mluvím.

Jazyk je čistý, pokud mohu, mimo jiné, provádět nahrazení výrazu její hodnotou
Souhlas. Ekvivalentně: pokud každé volání stejné funkce se stejnými parametry dá tentýž výsledek.

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.
Já pořád nějak nechápu, kde vidíš problém. Pokud fce vrací IO Int, tak prostě vrací nějaká data. Pokaždé stejná pro stejné argumenty. A přesně tak to má být. Kde je problém?


Re:Funkcionální programátor
« Odpověď #380 kdy: 08. 07. 2015, 01:31:59 »
Tak ho tak prostě definujeme, stačí jenom přidat IO monádu, a máme pure C. Nebo si můžeme udělat nový jazyk PureC s vlastní definicí se základem v Cčku. Nejlepší na tom je, že nebudeme muset psát jiný kompiler. Je to jen hra se slovy.
Věta "přidáme tam monádu a máme pure X" je stejně nesmyslná jako "přidáme tam <cokoli jinýho> a máme pure X". Purity není dáno tím, jestli jazyk má nebo nemá monády. Monády jsou NÁSTROJ, jak V ČISTÉM JAZYCE něco udělat. V nečistém jazyce tento nástroj

1. nepotřebuješ

2. z nečistého jazyka ti čistý neudělá

Vždyť se všichni shodujeme na definici "v čistém jazyce dvě volání vždy dávají stejný výsledek". Tak jestli chceš dokazovat, že Haskell není čistý, tak ukaž, jaké dvě fce můžou dát se stejnými argumenty jiný výsledek a je to, ne? Proč se babrat v čemkoli jiným, ne?

BoneFlute

  • *****
  • 1 981
    • Zobrazit profil
Re:Funkcionální programátor
« Odpověď #381 kdy: 08. 07. 2015, 01:33:30 »
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.
Já pořád nějak nechápu, kde vidíš problém. Pokud fce vrací IO Int, tak prostě vrací nějaká data. Pokaždé stejná pro stejné argumenty. A přesně tak to má být. Kde je problém?
Myslím, že už tě chápu.

Radek Miček

Re:Funkcionální programátor
« Odpověď #382 kdy: 08. 07. 2015, 01:40:57 »
Vaše argumenty lze po mírné modifikaci nasadit na jakýkoli jazyk, a poté tvrdit že je čistý. Stačí jen vytvořit monády. což není problém.

Na jakýkoliv jazyk to nasadit nejde - musel byste změnit definici toho jazyka.

Například jednoduchý jazyk, na nějž to nejde nasadit, je ML kalkulus - popis sémantiky na straně 395.
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 takhle není definováno (bohužel C není formálně definováno - proto jsem dal jako příklad ML kalkulus).
Tak ho tak prostě definujeme, stačí jenom přidat IO monádu, a máme pure C. Nebo si můžeme udělat nový jazyk PureC s vlastní definicí se základem v Cčku. Nejlepší na tom je, že nebudeme muset psát jiný kompiler.

Nestačí jenom přidat IO monádu. Musíte minimálně odebrat nebo omezit něco, čemu se v tom ML kalkulu říká "store" - například byste musel přístup do "storu" provádět pouze z IO monády.

Citace
Je to jen hra se slovy.

Není to jen hra se slovy. Má to praktické důsledky: Například optimalizace/transformace, jenž může kompilátor provádět, nebo omezení na korektní typový systém (v čistém jazyce například nepotřebujete value restriction).

Re:Funkcionální programátor
« Odpověď #383 kdy: 08. 07. 2015, 01:43:04 »
Myslím, že už tě chápu.
Ono by se to asi dalo říct i tak, že požaduješ nějakou vlastnost, která ale z definice nevyplývá. Nemusíme jít do monády, stačí nám funktor, ten je definovanej takhle:

Kód: [Vybrat]
class Functor (f :: * -> *) where
  fmap :: (a -> b) -> f a -> f b
- tam nikde nemáš řečený, že musí existovat způsob, jak můžeš z toho "boxu" tu hodnotu vytáhnout. To udělá implementace fmap pro konkrétní functor za tebe a opět ti vrátí jenom box, do kterýho se podívat nemůžeš, protože jeho strukturu obecně nemusíš znát. To, že ji u Maybe znáš a tímpádem můžeš tu hodnotu vytáhnout pattern matchingem je nějaká informace navíc, kterou obecně definice Functoru nezaručuje.

...a dá se to říct i ještě abstraktněji: functor nemusí být ani žádný "box na hodnoty", je to prostě endofunctor ;) https://en.wikipedia.org/wiki/Functor

Re:Funkcionální programátor
« Odpověď #384 kdy: 08. 07. 2015, 02:03:44 »
...a dá se to říct i ještě abstraktněji: functor nemusí být ani žádný "box na hodnoty", je to prostě endofunctor ;)
...teď jsem teda mocně zavařoval závity a přemýšlel nad tím, jestli by v Haskellu mohl být i nějaký ne-box functor a nic mě nenapadlo, kromě identity, což je vlastně takový null-box. Takže to asi nebyl úplně dobrý příklad :))

Ale kdybys měl možnost introspekce obecné funkce a mohl nějak přiohnout ji, místo té vstupní a výstupní hodnoty... Možná by to nějak i šlo. Ale asi teda spíš ne :))

ttt

Re:Funkcionální programátor
« Odpověď #385 kdy: 08. 07. 2015, 02:28:56 »
Identita je funkce. O funkcí nemůžu říct, že je functor, to řeknu o typu. Nevím, co si představuješ pod ne-box functorem, ale nemohla by to být třeba funkce?

Kód: [Vybrat]
    instance Functor ((->) r) where 
        fmap f g = (\x -> f (g x)) 

Re:Funkcionální programátor
« Odpověď #386 kdy: 08. 07. 2015, 02:36:08 »
Identita je funkce. O funkcí nemůžu říct, že je functor, to řeknu o typu.
Přesněji o typovém konstruktoru s kindem (jak se to řekně česky?) * -> * :)

Myslel jsem to tak, že by fmap byl identita, jenže to vlastně v Haskellu taky nejde, to je pech :)

Nevím, co si představuješ pod ne-box functorem, ale nemohla by to být třeba funkce?
Kód: [Vybrat]
    instance Functor ((->) r) where 
        fmap f g = (\x -> f (g x)) 
Jo, to by asi mohla :) Hlavně že jsem se na tu kapitolu v LYAH, kde je přesně tohle,  před chvilkou ještě koukal :)) Dík!

xyz

Re:Funkcionální programátor
« Odpověď #387 kdy: 08. 07. 2015, 02:38:36 »
To závisí od toho, či nám tá Cantorova alebo Riemannova funkcia naozaj pripadá divná alebo nie. Ako ukazuje diskusia v tomto vlákne (ale aj na iných fórach), tak čistota Haskellu jednoznačne mnohým ľuďom divná pripadá. Čím, pravdaže, nevylučujem, že niekomu by nemusel pripadať divný ani funkcionálne čistý jazyk "obsahujúci C-čko".
Nebylo by lepší opustit ty mlhavé analogie a napsat to polopaticky? V čem Haskell není čistý? Zatím jsme narazili jenom na to, že forknutí IO je nečisté (což je jasný z principu). Něco dál?

To je skôr otázka pre tých, ktorí tvrdia, že nie je čistý. (O tom, že čistota Haskellu mnohým ľuďom skutočne divná pripadá, ťa snáď presvedčili príspevky z posledných stránok diskusie.)

A v jakém smyslu by měl být čistý "funkcionální jazyk obsahující céčko"?

V zmysle definície čistoty funkcionálneho jazyka.

Jak by měl vypadat?

Na spôsob vyššie spomínaného C/FPP. (Som si vedomý toho, že časť za lomítkom nebola presne špecifikovaná.)

V čem by se od Haskellu lišil?

V princípe by na mieste funkcionálneho predprocesora FPP mohol byť pokojne Haskell, ale účelu príkladu ďaleko lepšie poslúži čo najmenší (a najnepoužiteľnejší) čistý funkcionálny jazyk. Mne tam pre ilustráciu myšlienky vcelku postačoval aj spomínaný CPP, ale tebe vadilo, že nie je turingovsky úplný, preto som vyššie spomenul to doplnenie o SK-kalkulus.

Re:Funkcionální programátor
« Odpověď #388 kdy: 08. 07. 2015, 02:41:38 »
Na spôsob vyššie spomínaného C/FPP. (Som si vedomý toho, že časť za lomítkom nebola presne špecifikovaná.)
Ok, takže máme nějaký čistý funkcionální jazyk, jehož jediným možným výstupem je text - konkrétně syntakticky správný C zdroják. A dál? Co s tím?

xyz

Re:Funkcionální programátor
« Odpověď #389 kdy: 08. 07. 2015, 02:55:11 »
Na spôsob vyššie spomínaného C/FPP. (Som si vedomý toho, že časť za lomítkom nebola presne špecifikovaná.)
Ok, takže máme nějaký čistý funkcionální jazyk, jehož jediným možným výstupem je text - konkrétně syntakticky správný C zdroják. A dál? Co s tím?
Tento zdroják (presnejšie by sme mali povedať: dátová štruktúra jazyka C/FPP) je potom spracovaný v runtime systéme, ktorý môže byť z dôvodov efektívnosti realizovaný prekladom do strojového kódu.

Ináč som si nie istý, či som ťa správne pochopil: tým čistým funkcionálnym jazykom nazývaš len FPP alebo C/FPP?