Rychlost Haskell vs. C++

andy

Re:Rychlost Haskell vs. C++
« Odpověď #210 kdy: 31. 08. 2018, 00:09:58 »
IO akce není "expression evaluation".
A?
Že jsi schopen detekovat crash IO akce není v rozporu s tím, že "Errors during expression evaluation, denoted by ⊥ (“bottom”), are indistinguishable by a Haskell program from non-termination.."


lopata

Re:Rychlost Haskell vs. C++
« Odpověď #211 kdy: 31. 08. 2018, 00:14:13 »
Že jsi schopen detekovat crash IO akce není v rozporu s tím, že "Errors during expression evaluation, denoted by ⊥ (“bottom”), are indistinguishable by a Haskell program from non-termination.."
Ale já nedetekuju crash IO akce, já detekuju crash v dělení. Kde a jak to udělám je jedno, protože to co je v main včetně IO také spadá do definice "Haskell program".

andy

Re:Rychlost Haskell vs. C++
« Odpověď #212 kdy: 31. 08. 2018, 00:18:56 »
Že jsi schopen detekovat crash IO akce není v rozporu s tím, že "Errors during expression evaluation, denoted by ⊥ (“bottom”), are indistinguishable by a Haskell program from non-termination.."
Ale já nedetekuju crash IO akce, já detekuju crash v dělení. Kde a jak to udělám je jedno, protože to co je v main včetně IO také spadá do definice "Haskell program".
To nejde. Podívej se na signature metody catch. To umí pouze detekovat výjimku, kterou vyvolá IO akce.

lopata

Re:Rychlost Haskell vs. C++
« Odpověď #213 kdy: 31. 08. 2018, 00:28:02 »
Ale já nedetekuju crash IO akce, já detekuju crash v dělení. Kde a jak to udělám je jedno, protože to co je v main včetně IO také spadá do definice "Haskell program".
To nejde. Podívej se na signature metody catch. To umí pouze detekovat výjimku, kterou vyvolá IO akce.
Myslím, že slovíčkaříme. Expression evaluation (volání div) se děje uvnitř IO akce, nicméně ta věta: "Errors during expression evaluation, denoted by ⊥ (“bottom”), are indistinguishable by a Haskell program from non-termination" nic o IO akci neříká. Je úplně jedno, kde se expression evaluation děje.

andy

Re:Rychlost Haskell vs. C++
« Odpověď #214 kdy: 31. 08. 2018, 00:29:16 »
Já myslím, že ti není jasný, co se stane. Při vyhodnocování se celý ten do block v tom catch nejdřív vyhodnotí jako
Kód: [Vybrat]
undefined :: IO (). Tato akce se pokusí spustit, načež to celý crashne (v C bychom byli na úrovni SIGSEGV, pokus o spuštění kódu na adrese 0 apod.). Haskell ti teda umožní tohle chytit (signal handler na SIGSEGV v C taky existuje) a případně se podívat na nějaké informace, proč to crashlo (v C by sis mohl prohledat stack a zkusit odhadnout, co se asi tak stalo).
Jako jestli ti tohle připadá "jenom prasárna", tak bych tě nechtěl mít blízko svého kódu. Ty si doopravdy myslíš, že v jakémkoliv jazyce lze od překladač očekávat, že pro takovýhle kód bude cokoliv garantovat?


lopata

Re:Rychlost Haskell vs. C++
« Odpověď #215 kdy: 31. 08. 2018, 00:35:53 »
Já myslím, že ti není jasný, co se stane. Při vyhodnocování se celý ten do block v tom catch nejdřív vyhodnotí jako
Kód: [Vybrat]
undefined :: IO ()
Která verze? Ta s error nebo nebo bez něj? Verze bez erroru vyhodí ArithException. Ale ono je to celkem jedno, nejde to srovnávat se SIGSEGV, protože SIGSEGV je undefined behavior a chytání SIGSEGV je implementation depended. Zpracování výjimek v Haskellu není implementation dependent, tam je jasně garantované, co se stane.

andy

Re:Rychlost Haskell vs. C++
« Odpověď #216 kdy: 31. 08. 2018, 00:40:50 »
Já myslím, že ti není jasný, co se stane. Při vyhodnocování se celý ten do block v tom catch nejdřív vyhodnotí jako
Kód: [Vybrat]
undefined :: IO ()
Která verze? Ta s error nebo nebo bez něj? Verze bez erroru vyhodí ArithException. Ale ono je to celkem jedno, nejde to srovnávat se SIGSEGV, protože SIGSEGV je undefined behavior a chytání SIGSEGV je implementation depended. Zpracování výjimek v Haskellu není implementation dependent, tam je jasně garantované, co se stane.
To je jedno, která. Tohle:
Kód: [Vybrat]
do
  let a = 6 /0
  putStrLn "Jde delit nulou"
[code]
znamená:
[code]
 let a = 6 /0
 in a `seq` putStrLn "Jde delit nulou

6/0 se vyhodnotí jako bottom, tím pádem a se vyhodnotí na bottom, bottom `seq` x = bottom, takže celý tenhle blok vyjde jako:

undefined :: IO ()
No a to se následně pokusíš spustit. Prostě takové:
Kód: [Vybrat]
NULL();

Citace
Ale ono je to celkem jedno, nejde to srovnávat se SIGSEGV, protože SIGSEGV je undefined behavior a chytání SIGSEGV je implementation depended.
Chceš tím naznačit, že kdyby chytání SIGSEGV bylo standardizované, že by to byl korektní způsob programování a samozřejmě bys očekával veškeré garance překladače....??

lopata

Re:Rychlost Haskell vs. C++
« Odpověď #217 kdy: 31. 08. 2018, 00:50:40 »
Chceš tím naznačit, že kdyby chytání SIGSEGV bylo standardizované, že by to byl korektní způsob programování a samozřejmě bys očekával veškeré garance překladače....??
Já tu otázku s dovolením otočím. Chceš snad naznačit, že překladač Haskellu nic negarantuje a nezpracuje správně kód, který není unsafe a nezávisí na undefined behavior? To je úplně stejná demagogie, jakou jsi předvedl. Takže bych sem znovu s dovolením dal kód a rád bych od tebe věděl, jesti je v rozporu s něčím v Haskell language report a jestli bude dávat deterministický výstup ve strict i v lazy variantě:
Kód: [Vybrat]
{-# LANGUAGE ScopedTypeVariables #-}

import Control.Exception

main = catch
        (do
            putStrLn "Tento program zjišťuje, zda lze zadaným číslem dělit. Zadejte číslo"
            input <- getLine
            let n = (read input :: Int)
            let a = div 1 n
            putStrLn "Tímto číslem lze dělit"
        )
        (\(err :: ArithException) -> putStrLn "Tímto číslem nelze dělit")

andy

Re:Rychlost Haskell vs. C++
« Odpověď #218 kdy: 31. 08. 2018, 01:03:19 »
Chceš tím naznačit, že kdyby chytání SIGSEGV bylo standardizované, že by to byl korektní způsob programování a samozřejmě bys očekával veškeré garance překladače....??
Já tu otázku s dovolením otočím. Chceš snad naznačit, že překladač Haskellu nic negarantuje a nezpracuje správně kód, který není unsafe a nezávisí na undefined behavior? To je úplně stejná demagogie, jakou jsi předvedl.
Tak to mi budeš muset vysvětlit. Řekl jsi:
Citace
Ale ono je to celkem jedno, nejde to srovnávat se SIGSEGV, protože SIGSEGV je undefined behavior a chytání SIGSEGV je implementation depended.
Takže pokud ti rozumím dobře, pokud by SIGSEGV bylo standardizované a chovalo se všude stejně, tak by to srovnávat šlo. Vzhledem k tomu, že požaduješ po haskellu v dané situaci, aby něco garantoval, tak když je to srovnatelné, tak bych očekával, že budeš to samé očekávat od C(++). Vzhledem k tomu, že volání "undefined" a chytání výjimky považuješ za normální, očekával bych, že budeš volání funkce na adrese 0 a chytání SIGSEGV považovat za normální.
Pokud tomu tak není, tak mi asi budeš muset vysvětlit, jak definuješ slovo "protože".

Citace
Takže bych sem znovu s dovolením dal kód a rád bych od tebe věděl, jesti je v rozporu s něčím v Haskell language report a jestli bude dávat deterministický výstup ve strict i v lazy variantě:
On ti dávat deterministický výstup bude, protože počítače jsou poněkud deterministické a pravidla pro vykonávání jsou celkem jasná. Bude ti dávat jiný výstup ve strict a lazy variantě. (nejsem si tím úplně 100% jistý, protože mi přijde, že by čistě teoreticky mohl optimalizátor ten let vyhodit, ale předpokládejme, že nemůže).

Tak. A původní otázka zněla, zda Strict->Lazy přechod může rozbít korektní haskellový program. Nikoliv, jestli je deterministický. Deterministický program může být pěkně nekorektní - viz tvůj příklad.

andy

Re:Rychlost Haskell vs. C++
« Odpověď #219 kdy: 31. 08. 2018, 01:13:57 »
A abych ti odpověděl na otázku, co je na tom programu nekorektní: při vstupu "0" se pokusí spustit IO akci "undefined". Což je paradoxně té adrese 0 dost podobné, protože tam taky "nic" není.

lopata

Re:Rychlost Haskell vs. C++
« Odpověď #220 kdy: 31. 08. 2018, 01:22:23 »
Tak to mi budeš muset vysvětlit. Řekl jsi:
Citace
Ale ono je to celkem jedno, nejde to srovnávat se SIGSEGV, protože SIGSEGV je undefined behavior a chytání SIGSEGV je implementation depended.
Takže pokud ti rozumím dobře, pokud by SIGSEGV bylo standardizované a chovalo se všude stejně, tak by to srovnávat šlo. Vzhledem k tomu, že požaduješ po haskellu v dané situaci, aby něco garantoval, tak když je to srovnatelné, tak bych očekával, že budeš to samé očekávat od C(++). Vzhledem k tomu, že volání "undefined" a chytání výjimky považuješ za normální, očekával bych, že budeš volání funkce na adrese 0 a chytání SIGSEGV považovat za normální.
Pokud tomu tak není, tak mi asi budeš muset vysvětlit, jak definuješ slovo "protože".
Vysvětlím ti to. Vycházím z toho, co je ve standardu daného jazyka. Standard C SIGSEGV neřeší, je to undefined behavior. Haskell zpracování výjimek řeší, není to undefined behavior.

TL;DR
K tvojí otázce, jestli bych považoval chytání SIGSEGV za normální, tak ne. C je natolik nízkoúrovňové, že SIGSEGV v podstatě ani chytit nelze. Existují architektury, kde nemáš MMU a SIGSEGV nikdy nedostaneš. Program v C může do paměti přistupovat nekorektně a stejně SIGSEGV nedostane i na architekturách s MMU, pokud se zrovna trefí do svého paměťového rozsahu. Prakticky to prostě nejde udělat správně. SIGSEGV znamená pouze "teď už se to fakt posralo", ale neznamená to "předtím bylo všechno dobře a paměť je konzistentní". Takže když dostaneš SIGSEGV, nelze se spoléhat na to, že je paměť v konzistentním stavu (i když to v C vlastně nikdy...) a nelze se z toho nijak rozumně zotavit. Reálně se po SIGSEGV dají udělat jen dvě věci, uložit core dump pro pozdější analýzu nebo program rovnou ukončit, nic jiného nedává smysl.

On ti dávat deterministický výstup bude, protože počítače jsou poněkud deterministické a pravidla pro vykonávání jsou celkem jasná. Bude ti dávat jiný výstup ve strict a lazy variantě. (nejsem si tím úplně 100% jistý, protože mi přijde, že by čistě teoreticky mohl optimalizátor ten let vyhodit, ale předpokládejme, že nemůže).

Tak. A původní otázka zněla, zda Strict->Lazy přechod může rozbít korektní haskellový program. Nikoliv, jestli je deterministický. Deterministický program může být pěkně nekorektní - viz tvůj příklad.
Jestli je ten program korektní z hlediska výstupu, o tom nerozhoduješ ty, ale uživatel. Pokud uživatel potřebuje zjišťovat, zda lze zadaným číslem dělit, tak strict varianta mu dává korektní výsledky a lazy varianta nekorektní. Je to samozřejmě jen elementární příklad, takhle se je potřeba na něj dívat. Udělat v Haskellu podobně (uznávám podivně) řešení i jiných problémů, než dělení čísel, aby byly závislé na strict vyhodnocení, samozřejmě lze.

lopata

Re:Rychlost Haskell vs. C++
« Odpověď #221 kdy: 31. 08. 2018, 01:26:25 »
A abych ti odpověděl na otázku, co je na tom programu nekorektní: při vstupu "0" se pokusí spustit IO akci "undefined". Což je paradoxně té adrese 0 dost podobné, protože tam taky "nic" není.
To je v rozporu s něčím v Haskell language report? Říká se tam, že se to nesmí dělat? Neříkám, že je to best practice, ale reálně to lidi (minimálně začátečníci) dělají: https://stackoverflow.com/questions/20822365/how-to-catch-a-divide-by-zero-error-in-haskell?answertab=votes#tab-top

andy

Re:Rychlost Haskell vs. C++
« Odpověď #222 kdy: 31. 08. 2018, 01:49:59 »
Jestli je ten program korektní z hlediska výstupu, o tom nerozhoduješ ty, ale uživatel.
Tak to bude problém, protože my se tu nebavíme, zda je korektní z hlediska výstupů. Bavíme se o tom, jestli ten program jako takový dává smysl. Vrátím se k důkazu, že 0=1. Když vezmeš výsledek, vynásobíš obě strany 0 a přičteš 5, vyjde ti "5=5". A to je "korektní výstup". Ale celý ten důkaz je blbě.

Ty pořád přemýšlíš na úrovni "operational semantics" - mám tady interpret/překladač, a pokud program, který jsem do něj dal, používá pouze funkce dle specifikace a dává správné výsledky, pak je "korektní". Takže ten důkaz "5=5" by byl korektní.

Tenhle přístup se v haskellu vůbec nepoužívá. Je to funkcionální programování, celý program je zápis nějaké funkce, které vyjadřuje nějakou transformaci světa z jednoho stavu do jiného. A korektní program je takový, který je ekvivalentní specifikaci toho problému, který řešíš. V momentě, kdy se ti tam vyskytne "undefined", tak to není korektní. Ne, že by se občas takové programy nepsaly, ale prostě to není korektní a můžeš očekávat, že ti prostě jazyk v ten moment toho bude garantovat výrazně méně. Třeba ti přestane garantovat, že Strict -> Lazy transformace je ekvivalentní.

Mně celkem pobavilo, jak se strašně snažíš tvrdit, že to je "akademický jazyk" - ale pokud bys chtěl haskell mít v tomhle  akademický, tak bys tam měl typy bez bottom (přitom by to bylo lazy) a ty tvoje programy by tím vůbec neprošly. Jenomže takovéhle jazyky jsou strašně těžko použitelné (protože programátor musí dokazovat, že jsou všechny funkce totální). Takže v Haskellu to dokazovat nemusíš, typy obsahují bottom, ale když se ti tam nějaký bottom dostane, tak neseš následky. Deterministické následky, ale ten tvůj program pak prostě není korektní.

Citace
To je v rozporu s něčím v Haskell language report? Říká se tam, že se to nesmí dělat? Neříkám, že je to best practice, ale reálně to lidi (minimálně začátečníci) dělají: https://stackoverflow.com/questions/20822365/how-to-catch-a-divide-by-zero-error-in-haskell?answertab=votes#tab-top
V rozporu? Ne. Jenom to není korektní program. Ten příklad ze stackoverflow je v pohodě - něco zkusil provést a slítlo to. Rozbitý program, informujeme uživatele, že to celý upadlo a proč. Nikdo se netváří, že to funguje korektně. Pro některé typy programů je to zcela dostačující, nevadí, že to crashne na vadném vstupu. Ale nikdo se taky netváří, že v takovém případě program pracuje korektně. Což je to, co tvrdíš ty.

lopata

Re:Rychlost Haskell vs. C++
« Odpověď #223 kdy: 31. 08. 2018, 02:17:37 »
Citace
To je v rozporu s něčím v Haskell language report? Říká se tam, že se to nesmí dělat? Neříkám, že je to best practice, ale reálně to lidi (minimálně začátečníci) dělají: https://stackoverflow.com/questions/20822365/how-to-catch-a-divide-by-zero-error-in-haskell?answertab=votes#tab-top
V rozporu? Ne. Jenom to není korektní program. Ten příklad ze stackoverflow je v pohodě - něco zkusil provést a slítlo to. Rozbitý program, informujeme uživatele, že to celý upadlo a proč. Nikdo se netváří, že to funguje korektně. Pro některé typy programů je to zcela dostačující, nevadí, že to crashne na vadném vstupu. Ale nikdo se taky netváří, že v takovém případě program pracuje korektně. Což je to, co tvrdíš ty.
Já už tomu rozumím. Ten program nesplňuje zásadní podmínku, není korektní podle TEBE. Nestačí, že splňuje všechno co splňovat má, odpovídá Haskell language report, nedělá nic unsafe, nezávisí na undefined nebo implementation behavior a funguje dle očekávání. To je málo. Navíc musí být korektní podle TEBE. Tak bohužel, program korektní podle TEBE si budeš muset napsat sám.

A jen pro inspiraci, abys nežil v představě, že řešíme nějaké silně nepravděpodobné a okrajové případy a v Haskellu se to "tak prostě nedělá a nikoho by to ani nenapadlo": https://stackoverflow.com/questions/4243117/how-to-catch-and-ignore-a-call-to-the-error-function

andy

Re:Rychlost Haskell vs. C++
« Odpověď #224 kdy: 31. 08. 2018, 07:39:12 »
Citace
To je v rozporu s něčím v Haskell language report? Říká se tam, že se to nesmí dělat? Neříkám, že je to best practice, ale reálně to lidi (minimálně začátečníci) dělají: https://stackoverflow.com/questions/20822365/how-to-catch-a-divide-by-zero-error-in-haskell?answertab=votes#tab-top
V rozporu? Ne. Jenom to není korektní program. Ten příklad ze stackoverflow je v pohodě - něco zkusil provést a slítlo to. Rozbitý program, informujeme uživatele, že to celý upadlo a proč. Nikdo se netváří, že to funguje korektně. Pro některé typy programů je to zcela dostačující, nevadí, že to crashne na vadném vstupu. Ale nikdo se taky netváří, že v takovém případě program pracuje korektně. Což je to, co tvrdíš ty.
Já už tomu rozumím. Ten program nesplňuje zásadní podmínku, není korektní podle TEBE. Nestačí, že splňuje všechno co splňovat má, odpovídá Haskell language report, nedělá nic unsafe, nezávisí na undefined nebo implementation behavior a funguje dle očekávání. To je málo. Navíc musí být korektní podle TEBE. Tak bohužel, program korektní podle TEBE si budeš muset napsat sám.
Ten důkaz 0=1 nesplňuje základní podmínku: Není korektní podle MĚ. Fakt?

Citace
A jen pro inspiraci, abys nežil v představě, že řešíme nějaké silně nepravděpodobné a okrajové případy a v Haskellu se to "tak prostě nedělá a nikoho by to ani nenapadlo": https://stackoverflow.com/questions/4243117/how-to-catch-and-ignore-a-call-to-the-error-function
A odpověd:
Citace
error is supposed to be as observable as an infinite loop. You can only catch error in IO, which is like saying "yeah you can if you know magic". But from the really nice part of Haskell, pure code, it is unrecoverable, and thus it is strongly advised not to use in your code, only as much as you would ever use an infinite loop as an error code