1906
Studium a uplatnění / Re:Funkcionální programátor
« kdy: 05. 07. 2015, 01:28:37 »Myslím, že se na to díváme podobně. Já jen tak explicitně neodděluji předpis od jeho vykonání.Teď ti nerozumím. Nebo nevím, čemu říkáš "pure funkce". Pokud pod "pure funkce" myslíš "matematická funkce", tak ta opravdu podle mě nemůže vykonávat žádnou činnost. Jak už jsem říkal, matematická funkce je relace.Protoze vykonava nejakou cinnost.Protože nic nezaručuje? (Pure funkce je schopná zaručit, že nebudou porušeny principy FP, zatímco IOMonáda toto zaručit nemůže.)
Např. můžeš mít funkci {{1,2},{2,3},{3,4},{4,5},...} - tahle funkce NEpřičítá jedničku. Jenom říká, že symboly "1" a "2" jsou v relaci "přičtení jedničky" (chceme-li "relace následník").
K tomu, aby byla vykonávána nějaká činnost, musí existovat nějaký stroj, "výkonný mechanismus" apod., který něco od někud načte, něco někam zapíše apod. Jasně, může to dělat podle nějakého popisu, postupu, klidně i té relace, ale potřebuje mít k tomu popisu nějakou sémantiku, nějak ten popis interpretovat.
...takže třeba ta otázka, jestli tenhle celý cirkus "umožňuje souběhy" je podle mýho (možná špatnýho) dojmu otázka po vlastnostech toho "stroje", ne toho statického popisu ("relace").
Jak jsem už psal, na Prologu je to vidět imho líp - představ si, že bys měl nějaký čistě deklarativní logický jazyk ve stylu Prologu a dva různé inferenční enginy ("runtimy"), které by oba šly směrem k řešení jinou cestou - "funkce" v programu by pak byly stejné, ale běh programu by byl v těch dvou případech jiný. Tohle je u deklarativních jazyků v principu možný. Samozřejmě je to nežádoucí, takže se jazyk vymyslí tak, aby měl sémantiku jednoznačnou - což je podobný jako princip té monády, která je takový trik, který ti umožňuje zafixovat něco, co by jinak zafixované nebylo.
(Nevylučuju, že jsem ti jenom špatně rozuměl, nebo se v něčem mýlím. Za doplnění/upřesnění budu rád.)
Jak jsem psal na jiném místě, beru to tak, že Haskell jako jazyk/předpis, je funkcionálně čistý. A to dokonce včetně IOMonád. Je to předpis, jak něco nějak vykonat atd... přesně jak jsi to pěkně popsal.
A pak máš engine, ať už interpret, nebo kompilátor, který se snaží ten předpis zpracovat. A ideální by bylo, aby se ten engine choval přesně podle toho předpisu. Takže:
1. Mám funkci sum :: Int -> Int -> Int, která mi sečte dvě čísla. A já logicky očekávám, že ten engine mi pro sum 1 1 vrátí 2ku. Ať si to vevnitř spočítá jak chce. Ať tam používá sdílenou paměť, ať ji mění, ať se třeba ptá google, to je mi fuk. Ale nesmí se stát, že mi vyhodí chybu. To prostě nejde.
2. Když budu mět funkci parseXml :: String -> Either String Xml tak já tam na první pohled mám možnost vyhodit chybu, jenže už na druhý je jasné, že pokud uvedu parseXml "<empty/>", tak mi to vždycky hodí Right Xml. Takže tam není nic na výběr. Ten výběr je jen pro programátora, aby se mu s tím lépe pracovalo.
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.
Ano, uvědomuji si, že to nejsou úplně skvělé příklady, ale až mě napadne lepší, tak ho sem strčím.


