Typový system versus unittesty

JSH

Re:Typový system versus unittesty
« Odpověď #735 kdy: 21. 08. 2018, 16:32:12 »
IMHO je důležité, aby s těmi hodnotami v typech šla dělat aritmetika a podobné “výpočty”. Jak to je v C++ nevím, ale tam to bude asi dost omezené.
Šablony jsou výpočetně úplné. Jen syntaxe je hnusná.
Citace
V jazycích jako zmíněný Idris (nebo třeba Coq, ten ale blíže neznám) je typový systém v podstatě dokazovač, kde jde napsat libovolná logická formule s proměnnými.
Napsat jo. Ale porovnat dvě formule je obecně nerozhodnutelný problém, jestli se nepletu. Nebo je to minimálně NP-úplné.


Bacsa

Re:Typový system versus unittesty
« Odpověď #736 kdy: 21. 08. 2018, 16:38:28 »
IMHO je důležité, aby s těmi hodnotami v typech šla dělat aritmetika a podobné “výpočty”. Jak to je v C++ nevím, ale tam to bude asi dost omezené.
Šablony jsou výpočetně úplné. Jen syntaxe je hnusná.
To ano, právě o to jde, aby v těch typech (šablonách) šly psát výrazy a používat operátory nad typy. V C++ by to asi šlo s variantem taky, ale vidět bych si to nepřál.

Bacsa

Re:Typový system versus unittesty
« Odpověď #737 kdy: 21. 08. 2018, 16:42:24 »
Citace
V jazycích jako zmíněný Idris (nebo třeba Coq, ten ale blíže neznám) je typový systém v podstatě dokazovač, kde jde napsat libovolná logická formule s proměnnými.
Napsat jo. Ale porovnat dvě formule je obecně nerozhodnutelný problém, jestli se nepletu. Nebo je to minimálně NP-úplné.
O tom se v té knížce píše taky. Logika je sice jen semirozhodnutelná, ale ve většině praktických případů je typová kontrola rozhodnutelná. Ostatně i v C++ se dají napsat šablony, které překladač zacyklí, ale u běžných programů k tomu nedochází.

JSH

Re:Typový system versus unittesty
« Odpověď #738 kdy: 21. 08. 2018, 17:12:20 »
O tom se v té knížce píše taky. Logika je sice jen semirozhodnutelná, ale ve většině praktických případů je typová kontrola rozhodnutelná. Ostatně i v C++ se dají napsat šablony, které překladač zacyklí, ale u běžných programů k tomu nedochází.
Jop, tady souhlasím.

Pořád ale netuším, jak tímhle typovým systémem nahradím (takhle to tu totiž BoneFlute celou dobu propaguje) ty zmiňované unittesty. Jo, něco to pochopitelně zkontroluje a ulehčí práci. S tím nemám problém. Ale pořád vidím dva zásadní problémy :
1) Data pocházejí zvenku. Už jsem psal, že já se svým hraním skončil na rozhraní, kde bylo třeba ta data konvertovat. A na něco podobného se tu ptal i ava.
2) A i ty samotné typy přestávají být triviální. Místo testování kódu abych napsal testy na typy.

Bacsa

Re:Typový system versus unittesty
« Odpověď #739 kdy: 21. 08. 2018, 19:30:47 »
A i ty samotné typy přestávají být triviální. Místo testování kódu abych napsal testy na typy.
:D

Na tom něco, ve vší vážnosti, bude. Já to vždy chápal tak, že závislostní typy jsou něco jako asserty, akorát v době překladu. Tzn. deklarativní vyjádření nutně splněných podmínek. Ještě bych dodal, že záv. typy dávají smysl jen ve funkcionálních jazycích.


v

Re:Typový system versus unittesty
« Odpověď #740 kdy: 21. 08. 2018, 20:01:47 »
Já to vždy chápal tak, že závislostní typy jsou něco jako asserty, akorát v době překladu. Tzn. deklarativní vyjádření nutně splněných podmínek.
to mi připomělo tohle:
Citace
A recurring method in dependently typed programming is to program with data structures that enforce coherence of their indices, even though they contain no bits themselves...leaving said data-bearing indices entirely implicit.
(McBride na twitteru)

v

Re:Typový system versus unittesty
« Odpověď #741 kdy: 21. 08. 2018, 20:09:04 »
Hezké, ale teď mě zajímá klíčová otázka: jak se to použije když budu chtít udělat prográmek, který přečte ze stdin p, zavolá na to mysubstr p 2 [10,20,30,40] , a výsledek vytiskne? Programy bez IO moc užitečné nebývají, že.. Poprosil bych přímo zdroják, je už to jen krůček... ?
předpokládám, že jste to zkusil napsat a nefunguje vám to, postněte tady váš kód a zkusíme to odladit :)

Nezkusil, a ani nevím jak na to. Opravdu prosím, obětujte 10 minut svého času, napište to a postněte to (přeložitelnou a spustitelnou verzi).
dostat ze stdin Nat by mělo být triviální, potom je třeba "dokázat" že hodnota pasuje k danému vektoru, to by mělo být relativně snadné (vím jak bych to dělal v haskellu), ale v idrisu to zatím neumím (možná overLength?), zatím jsem v něm programoval cca deset minut, pokud se to pokusíte naprogramovat a postnete sem kód, budu se tím zabývat dál

Bacsa

Re:Typový system versus unittesty
« Odpověď #742 kdy: 21. 08. 2018, 22:05:32 »
dostat ze stdin Nat by mělo být triviální
Jak se to dělá?

v

Re:Typový system versus unittesty
« Odpověď #743 kdy: 21. 08. 2018, 22:45:51 »
dostat ze stdin Nat by mělo být triviální
Jak se to dělá?
načte se řetězec a pak se z něj udělá Nat
Kód: [Vybrat]
*Data/String> the (Maybe Nat) (parsePositive "1")
Just 1 : Maybe Nat

Bacsa

Re:Typový system versus unittesty
« Odpověď #744 kdy: 21. 08. 2018, 23:00:37 »
dostat ze stdin Nat by mělo být triviální
Jak se to dělá?
načte se řetězec a pak se z něj udělá Nat
Kód: [Vybrat]
*Data/String> the (Maybe Nat) (parsePositive "1")
Just 1 : Maybe Nat
Jde o to, jak načtu Nat po kompilaci. Nat je typ s teorií následník/nula, ne? To bych musel nejdřív načíst číslo a pak program přeložit se vstupem jako konstantou.

JSH

Re:Typový system versus unittesty
« Odpověď #745 kdy: 22. 08. 2018, 08:10:48 »
A i ty samotné typy přestávají být triviální. Místo testování kódu abych napsal testy na typy.
:D

Na tom něco, ve vší vážnosti, bude.
A to je navíc testování toho, že se něco opravdu nepřeloží, strašný opruz. Ručně je to ok, ale jak to chce člověk trochu zautomatizovat, aby si omylem něco nerozbil, tak aby si na to psal scripty. A ještě nějak zkontrolovat, jestli se to nepřeložilo ze správného důvodu. :D
Citace
Já to vždy chápal tak, že závislostní typy jsou něco jako asserty, akorát v době překladu. Tzn. deklarativní vyjádření nutně splněných podmínek. Ještě bych dodal, že záv. typy dávají smysl jen ve funkcionálních jazycích.
Ona hranice funkcionálního jazyka není úplně ostrá. Třeba na novém C++ je vliv Haskellu a podobných jazyků hodně vidět.

v

Re:Typový system versus unittesty
« Odpověď #746 kdy: 22. 08. 2018, 08:22:47 »
dostat ze stdin Nat by mělo být triviální
Jak se to dělá?
načte se řetězec a pak se z něj udělá Nat
Kód: [Vybrat]
*Data/String> the (Maybe Nat) (parsePositive "1")
Just 1 : Maybe Nat
Jde o to, jak načtu Nat po kompilaci. Nat je typ s teorií následník/nula, ne? To bych musel nejdřív načíst číslo a pak program přeložit se vstupem jako konstantou.
hm, to by bylo blbé

Bacsa

Re:Typový system versus unittesty
« Odpověď #747 kdy: 22. 08. 2018, 08:44:52 »
dostat ze stdin Nat by mělo být triviální
Jak se to dělá?
načte se řetězec a pak se z něj udělá Nat
Kód: [Vybrat]
*Data/String> the (Maybe Nat) (parsePositive "1")
Just 1 : Maybe Nat
Jde o to, jak načtu Nat po kompilaci. Nat je typ s teorií následník/nula, ne? To bych musel nejdřív načíst číslo a pak program přeložit se vstupem jako konstantou.
hm, to by bylo blbé
  Měl jsem za to, že tento problém každý vidí.

ava

Re:Typový system versus unittesty
« Odpověď #748 kdy: 22. 08. 2018, 10:27:05 »
dostat ze stdin Nat by mělo být triviální
Jak se to dělá?
načte se řetězec a pak se z něj udělá Nat
Kód: [Vybrat]
*Data/String> the (Maybe Nat) (parsePositive "1")
Just 1 : Maybe Nat
Jde o to, jak načtu Nat po kompilaci. Nat je typ s teorií následník/nula, ne? To bych musel nejdřív načíst číslo a pak program přeložit se vstupem jako konstantou.
hm, to by bylo blbé
  Měl jsem za to, že tento problém každý vidí.

No pro mě právě tohle taky bylo záhadou. Trochu mi pomohly následující články:

https://stackoverflow.com/questions/48128884/
https://news.ycombinator.com/item?id=12349899

tedy pomohly spíš tak, že už vidím, že na konci tunelu může být světlo, než že by se mi vysloveně rozsvítilo.

Každopádně co se týče (abych trochu poskočil v tématu) původního dotazu BoneFluteho, mám dost podobný dojem jako Jirsák, že BoneFlute našel novou modlu, o které téměř nic neví, ale o to více ji chválí. Tím dependent typy nechci shazovat, je možné že se v budoucnu ukáží užitečné a rozšíří se. Abych ovšem byl také trochu konstruktivní a vyjádřil se k původnímu dotazu, podle mě dependent typy nemohou nahradit unit testy v následujícím:

Dependent typy z principu nemohou dokázat korektnost např. převodu stringu na číslo. Jak by se v typu fce convert: String -> Maybe Nat vyjádřilo, zda se očekává stringový vstup v desítkové nebo šestnáctkové soustavě? Podle mě je to principiálně nemožné, a stejně tak není možné ani vyjádřit korektnost implementace převodu. V Idris se asi dá vyjádřit, že funkce doběhne, a že nezpanikaří, ale to je málo.

Unit testy slouží jako vždy up-to-date dokumentace. U jednoduchých věcí se dá samozřejmě hodně věcí vyčíst z typů (hezký příklad je tady: http://funkcionalne.cz/2014/08/types-will-carry-you-over-the-monads/), ale u složitějších je prostě hezké mít chování zdokumentované na příkladech, místo potřeby rozjímat nad důsledky komplikované typové signatury. Navíc je slušnost mít knihovny zdokumentované, tak proč to rovnou nedělat unit testy? (podívejte např. sem: https://doc.rust-lang.org/std/iter/trait.Iterator.html), všechny Examples jsou rovnou spustitelné unittesty zapsané do docstringů funkcí.

Unit testy jednoduchým způsobem ověřují chování v krajních a nečekaných případech. Když jsem psal implementaci funkce testující, zda je bod uvnitř polygonu, rovnou napíšu test, jak se chová bod na hraně, jak se chová v polygonu, který není uzavřený, jak se chová v polygonu který protíná sám sebe. Nedovedu si představit, jak by mohlo být takové chování zřejmé z typu funkce. Možná, až BoneFlute přestane "být stále student", nějak pěkně to vyřeší, to by mě pak docela zajímalo.

Unit testy jsou šablony funkčního kódu, který používá knihovnu kanonickým způsobem. Kód mohu copy'n'pastnout do vlastního projektu a upravit podle potřeby. Typy tohle neumí.

Na závěr: Typy a unit testy se doplňují, líbí se mi tahle asi minuta a půl: https://www.youtube.com/watch?v=pMgmKJyWKn8&feature=youtu.be&t=317

Bacsa

Re:Typový system versus unittesty
« Odpověď #749 kdy: 22. 08. 2018, 12:31:46 »
dostat ze stdin Nat by mělo být triviální
Jak se to dělá?
načte se řetězec a pak se z něj udělá Nat
Kód: [Vybrat]
*Data/String> the (Maybe Nat) (parsePositive "1")
Just 1 : Maybe Nat
Jde o to, jak načtu Nat po kompilaci. Nat je typ s teorií následník/nula, ne? To bych musel nejdřív načíst číslo a pak program přeložit se vstupem jako konstantou.
hm, to by bylo blbé
  Měl jsem za to, že tento problém každý vidí.

No pro mě právě tohle taky bylo záhadou. Trochu mi pomohly následující články:

https://stackoverflow.com/questions/48128884/
https://news.ycombinator.com/item?id=12349899

tedy pomohly spíš tak, že už vidím, že na konci tunelu může být světlo, než že by se mi vysloveně rozsvítilo.

Každopádně co se týče (abych trochu poskočil v tématu) původního dotazu BoneFluteho, mám dost podobný dojem jako Jirsák, že BoneFlute našel novou modlu, o které téměř nic neví, ale o to více ji chválí. Tím dependent typy nechci shazovat, je možné že se v budoucnu ukáží užitečné a rozšíří se. Abych ovšem byl také trochu konstruktivní a vyjádřil se k původnímu dotazu, podle mě dependent typy nemohou nahradit unit testy v následujícím:

Dependent typy z principu nemohou dokázat korektnost např. převodu stringu na číslo. Jak by se v typu fce convert: String -> Maybe Nat vyjádřilo, zda se očekává stringový vstup v desítkové nebo šestnáctkové soustavě? Podle mě je to principiálně nemožné, a stejně tak není možné ani vyjádřit korektnost implementace převodu. V Idris se asi dá vyjádřit, že funkce doběhne, a že nezpanikaří, ale to je málo.

Unit testy slouží jako vždy up-to-date dokumentace. U jednoduchých věcí se dá samozřejmě hodně věcí vyčíst z typů (hezký příklad je tady: http://funkcionalne.cz/2014/08/types-will-carry-you-over-the-monads/), ale u složitějších je prostě hezké mít chování zdokumentované na příkladech, místo potřeby rozjímat nad důsledky komplikované typové signatury. Navíc je slušnost mít knihovny zdokumentované, tak proč to rovnou nedělat unit testy? (podívejte např. sem: https://doc.rust-lang.org/std/iter/trait.Iterator.html), všechny Examples jsou rovnou spustitelné unittesty zapsané do docstringů funkcí.

Unit testy jednoduchým způsobem ověřují chování v krajních a nečekaných případech. Když jsem psal implementaci funkce testující, zda je bod uvnitř polygonu, rovnou napíšu test, jak se chová bod na hraně, jak se chová v polygonu, který není uzavřený, jak se chová v polygonu který protíná sám sebe. Nedovedu si představit, jak by mohlo být takové chování zřejmé z typu funkce. Možná, až BoneFlute přestane "být stále student", nějak pěkně to vyřeší, to by mě pak docela zajímalo.

Unit testy jsou šablony funkčního kódu, který používá knihovnu kanonickým způsobem. Kód mohu copy'n'pastnout do vlastního projektu a upravit podle potřeby. Typy tohle neumí.

Na závěr: Typy a unit testy se doplňují, líbí se mi tahle asi minuta a půl: https://www.youtube.com/watch?v=pMgmKJyWKn8&feature=youtu.be&t=317
Jak tak čtu tu Bradyho knihu podrobněji, docházím k názoru, že psaní kódu se záv. typy je prostě jiné paradigma a vyžaduje úplně jiné myšlení u než třeba Haskell (ten v porovnání s Idrisem vůbec není abstraktní).