Nos, a Haskell egy programozási nyelv. Egy Haskell Brooks Curry nevű amerikai matematikusról nevezték el, aki Blaise Pascalon kívül valószínűleg az egyetlen valaha élt ember, akinek a kereszt- és vezetéknevéről is neveztek el programozási nyelvet :). Pascal viszont azt nem mondhatja el magáról, hogy mindezek mellett még igét is csináltak a nevéből (currying)… A fenti linken részletes dokumentációt, tutoriálokat, compilereket, interpretereket és mindenféle ilyesmit találhat a komolyabban érdeklődő olvasó.
A Haskell nyelvről általában a következő szavakat szokták mindig megemlíteni: (a következő mondat akkor sajnos angolul lesz :). Haskell is a statically typed, purely functional, lazy programming language; a fícsörök között pedig ilyeneket szoktak emlegetni, hogy: polymorphism, partial application, Algebraic Data Types (ADT), pattern matching, first-class actions, type classes, monadic IO, stb… Ebben a cikkben megpróbálom röviden (sic!) összefoglalni, hogy nagyjából mit jelentenek ezek a szavak, és miért jó hogy vannak ilyenek. A Haskell egyébként nem az egyetlen ilyen jellegű nyelv, sok közelebbi-távolabbi rokona van (az ML nyelvcsalád például, vagy a Miranda, vagy a Clean), de vannak eléggé egyedi megoldásai is.
A szerző nem állítja, hogy profi lenne a témában, mindenestre írt egy demót ezen a nyelven (ami a Function’07 hírhedt democompóján a 2. helyezést érte el, de nem lesz kiadva sohasem, muhaha :).
Vágjunk akkor bele. A “statically typed” egyszerűen azt jelenti, hogy minden objektumnak van típusa, amit már fordítási időben ismerünk (!), és persze a függvényeknek is meg van mondva, hogy milyen típusú objektumokat fogadnak el és adnak vissza. Ilyen a Java, sőt többé-kevésbe a C is, de szöges ellentétben áll az ún. “dinamically typed” nyelvekkel, mint pl. a Python, LISP, PHP vagy a JavaScript. Ennek nyilvánvaló előnye, hogy csomó hibától megóvja a programozót, hiszen nem adhatunk össze véletlenül egy számot egy stringgel (amit mondjuk ha Pythonban követünk el, csak futási időben derül ki; és mi van, ha ez mondjuk csak nagyon ritkán történik, és már release-eltük a szoftvert, amikor feltűnik valakinek, netán esetleg valami kritikus dolgot vezérlünk vele?) Ellenzői szerint a static typing kényelmetlen (pl. mert ki kell írni a típusokat) és túlzottan megszorító; de Haskellben nem muszáj kiírni a típusokat, mert a compiler okos és kitalálja őket magától, a megszorítások alól pedig a nyelv többi része több mint feloldoz.
Az hogy “purely functional”, leginkább két dolgot takar: a “purely” rész azt jelenti, hogy a nyelvben a függvények matematikai értelemben vett függvények, adott bemenetre mindig ugyanazt a kimenetet kell adniuk. Ezt úgy is szokták mondani, hogy nincsenek side-effectek. Vegyük pl. a következő C nyelvű kódrészletet:
int jajj(int x)
{ almafa++;
return (x+almafa);
}
A jajj itt nem teljesíti a fenti feltételt, nem matematikai értelemben vett függvény (hiába hívják C terminológiával “function”-nek). A “side-effect” jelen esetben az, hogy a függvény hívásával megváltozik a világ állapota, pontosabban az almafa változó értéke. Szemfülesebb olvasóinknak feltűnhet ezen a ponton, hogy akkor mégis hogyan lehet input/outputot (a továbbiakban: IO) csinálni, hiszen mondjuk a getchar sem épp egy matematikai értelemben vett függvény. Erre egy nagyon elegáns, ámbár elsőre kissé ijesztő megoldást találtak az évek alatt, amiről majd később írok.
A “purely functional” szóösszetétel második fele pedig arra utal, hogy a függvények ún. first-class objektumok: át lehet őket adni paraméterként, vissza lehet őket adni visszatérési értékként, és általaban bármit lehet velük csinálni, amit a többi dologgal szoktunk. Persze mondhatná az ember, hogy a C is ilyen, mert a függvény címével lehet manipulálni, de azért ez kicsit más.
Ezen ponton akkor talán előkapok egy példát a kalapomból :) . A standard library része a zipWith függvény, aminek típusa Haskell szintaxissal írva
Ezt így praktikus olvasni: a zipWith egy függvény, aminek három paramétere van: az első paraméter egy újabb függvény, aminek két paramétere van, az első az a típusú, a második b típusú, a kimenete pedig c típusú (itt a, b, c helyére bármilyen konkrét típusokat helyettesíthetünk; ezt hívják polimorfizmusnak). A zipWith függvény első paramétere tehát egy függvény; a második és a harmadik két lista, az első az a típusú objektumok listája, a második pedig b típusú objektumok listája. A zipWith végeredménye pedig c típusú objektumok listája.
Nem nehéz kitalálni, hogy mit csinál ez a függvény: a két lista elemeit “párosítja”, majd minden párra alkalmazza a paraméterként kapott függvényt, és végeredményekből alkot egy új listát. Például ennek a függvényhívásnak (Haskellben a függvények paramétereit nem rakják zárójelbe, és nem vesszővel, hanem space-szel választják el őket)
az eredménye [5,12,21,32]. Mint az könnyen kitalálható ebből a példából, a (*) az a szorzásfüggvény: (*) 2 3 = 6, amit egyébként írhatunk hagyományosan is: 2 * 3 = 6.
A zipWith kapcsán felmerülhet a kérdés, hogy mi történik, ha a paraméterként kapott két lista nem egyforma hosszú? Nos, a válasz az, hogy a rövidebb lista végén megáll a folyamat. Ez többek közt azért kényelmes, mert a Haskell akár végtelen hosszú listákat is megenged: pl. cycle [1,2,3,4] az egy végtelen hosszú lista, ami így kezdődik:
Az, hogy a végtelen hosszú listák és hasonló adatstruktúrák nem okoznak gondot, pedig azért van, mert a nyelv lazy: ez azt takarja, hogy mindent csak akkor számol ki, amikor szükség van rá. Ha a végtelen hosszú listának csak egy véges (de mondjuk előre nem ismert hosszúságú) részét használja a program, akkor nincs semmi baj. A nyelv ezen aspektusának más előnyei is vannak, de hátránya is: némi overheadet vezet be ez a design decision, azaz a program adott esetben kicsit lassabb lesz (más esetekben viszont sokkal gyorsabb is lehet, pl. ha a figyelmetlen C programozó feleslegesen sok dolgot számoltat ki a géppel :)
Nos, ez itt talán megfelelő pont arra, hogy ezt a lassan végtelen hosszúra nyúló cikket (pun intended) félbevágjam; igény szerint lesz második rész is.
Addig is előzetesnek a zipWith egy lehetséges definíciója:
zipWith f (x:xs) (y:ys) = (f x y) : (zipWith f xs ys)
zipWith _ [] _ = []
zipWith _ _ [] = []
Slyspy azt mondta, hogy kell összefoglalás a végére, hogy miért jó ez az egész. Nos azért jó, mert visszahozza a programozásba a “fun” részt, amit már-már kiveszni véltem én például. :)
Jó akkor egy miniszótárat mellékelhetnél az összes szakmai kifejezés magyarázatával, kivétel a függvény. :)
Szal egy kukkott sem értettem, de zenész vagyok.
Majd a masodik (harmadik, …) reszben a tobbi szo is el lesz magyarazva, erre a reszre 3 vagy 4 szo jutott :)
Én még mindig nem értem… Mikor lesz a folytatás? :)
Fubazz, Haskellban demot irni, az nem semmi lelkivilagra vall. Ha nem Blala tette volna, komolyan aggodnek az illetoert :)
Na, de hol a folytatas?
Ebben demot irni? :O Az egyetemen anno szoba kerult, de hala az egnek nem eroltettek nagyon :) Respect annak, aki ebben programozik :D
folytatas lesz, csak meg kicsit varok a reakciokra
Nem kívántam meg így elsőre, de sok új dologgal így vagyok, amit nem magam fedezek fel :) De az tetszik, hogy egy kicsit állítani kell a gondolkodásmód fókuszán hozzá :)
Én is akarok örülni! Laikusul vattafak a különbség?
Ennél még a matlab is jobb gyerekek. Blala orvos látott már?:) ugye ez nem ilyen ELTE matek miatt elkapott dolog?:)
Ez a nyelv nagyon nem keresztény…
Maxie: nem, orvos nem latott, es nem, az ELTE-re mar tobb mint 4 eve nem jarok :) A matlab pedig nem jobb (es amugy is tok masra valo)
slyspy: csak neked, csak most, megfogalmazom laikusul :) “jeee, de hat ez fun!” vs. “o bazdmeg mar megint ezzel a szarral kell szopjak!”
Bery: jaja, kell allitani, es ez jo.
FooLman: mert rolam mar reg lemondtal, ugye? :))
A Haskell jött, látott és mindenkit meggyőzött :)
ez fasza, majd beleásom magam.:)
egyszer tettem egy kis ASM kitérőt, de rá kellett jönnöm, hogy teljesen mindegy, hogy millyen nyelvből hívogatom az OpenGL függvényeket :)
nem mindegy hogy mihez irnak C-ben compilert/interpretert? :)
Gargaj: egyreszt nem mindegy :) merthogy nem mindegy mivel toltod az idodet kodolas folyaman. Masreszt, nem mindegy, mert az hogy C-ben irnak egy compilert, nem jelenti azt automatikusan hogy az a compiler C-re is fordit. Harmdreszt, a Haskell compilereket tipikusan Haskellben szoktak irni, esetleg ML-ben :)
az első kompilert a joisten teremtette? :)
az elsot asszem vagy ML-ben vagy LISP-ben irtak, biztos ki lehet deriteni a zinternet segitsegevel. Amugy ez a tyuk vagy tojas kerdes tenyleg van a compilereknel, pl link (miert nem linkesiti automatikusan a linkeket?)
[ módosítva Oct.11. 16:01 ]
Programozzatok brainfuckban, ‘HQ9+’-ban vagy whitespace-ben. Abban van kihívás.
Jimmi: ha ‘szalagutcában’ programozok az nem jó? :Ö
Én azt gondolom, hogy az első compilert és interpretert is – bár ez utóbbi azért nem biztos – gépi kódban (nem tudom, hogy helyes-e az ASM használata arra az eszközre és platformra, ami az első lehetett) írták. Én szintén így tettem kb. 17 éve, amikor írtam játékprogram nyelvet :) Bár inkább script nyelv volt (bár azonnal gépi kódra fordított :)), így utólag, és jófomán alig volt valamire jó :) Ellenben az első disassembler-emet (és egyben az utolsót is :)) BASIC-ben írtam :))))) Jajj, azok a boldog középiskolás évek…
csak gondolod? nem mintha sok mas lehetoseguk lett volna :)
No mar megint egy ertelmetlen nyelv, amire lehet geekturbalni az egesz napos php robot utan… De a cikk azert jo. :D
>> A szerző nem állítja, hogy profi lenne a témában, mindenestre írt egy demót ezen a nyelven (ami a Function’07 hírhedt democompóján a 2. helyezést érte el, de nem lesz kiadva sohasem, muhaha :).
Ezesetben viszont kerem a 2. helyezett ermet, merthogy a release-eles a nevezes feltetele volt, nemde? :)
[ módosítva Oct.11. 22:18 ]
ha nem adja ki, tobbet nem engedjuk be functionre, kb ennyi.
Ki lesz adva, mert bazmeg nem azért írtam bele zenét, hogy ott maradjon Blala fiókjában. :)
Nő a nyomás. :)
valaki toljon már belőle egy 0-day cracket :D
Gargaj ti nem raktátok el a compógépen a MAC-verziót? :P Vagy legalább Te slyspy küldd el a zenét :D
Blala: nem mondtam le rolad, csak az evek alatt bebizonyosodott, hogy nalad ez a normalis :)
-SP-: blala geperol ment a stuff a compon… azt hiszem ezt hivjak tokeletes buntenynek…
no, nem akarok turelmetlennek latszani, de…
HOL A MASODIK RESZ MAR VAZZ?????
A foszerkeszto ur azt mondta, hogy jovo het csutortokon lesz folytatas. Addig szamoljatok hogy meg hanyat kell aludni :)
A demorol pedig, azert mondjuk nem erzem magam felelosnek, hogy a szervezok nem kertek el a demot, barmennyire is koszonjuk, hogy a szabalyoknak nem teljesen megfelelve is engedtek hogy lemenjen. De ne izguljatok, lesz demo – egyszer -, csak ugy gondoltam ez tok jo alkalom hogy akkor mar rogton a final verzio jelenjen meg. De azota kicsit elcsusztam a teendokkel es egyebekkel. Gargaj meg milyen szigoru lett hirtelen, azert kemeny lenne ha sikerulne elernem hogy ne engedjenek be egy magyar partyra :)
hanyatt kell aludni? :)
egyébként ha már itt vannak a készítők, akkor szeretnék kérdezni valamit:
a “we are not supported by computers” arra utal, hogy nem PC-t használtok, hanem mac-et?
[ módosítva Oct.12. 14:32 ]
Nem számítógépet használtak, csak egy MAC-et ;-))))
De a “YOU are not supported by computers” egy másik demoban volt, nem a Blala-SlySpy féle, PC-n le nem fordulós, Haskell-es, de blobbal objekten lyukat vágós, zenével effektet vezérlősben :)
[ módosítva Oct.12. 17:03 ]
Es azon kivul, hogy mindent sokkal bonyolultabban kell megfogalmazni, mi is az ertelme ennek a nyelvnek?
Apropo: hardcore prg nyelv maniasoknak ajanlom Wouter van Oortmerssen professzor ur munkassagat, akinek a prg nyelv fejlesztese a hobbija. Kulonosen vicces a False remekmuve…
De szinten mokas a Brainfuck nevu nyelv is… ;)
[ módosítva Oct.12. 14:55 ]
ez a dude irta a Cubeot is ja
ilyen még kell.
Nos azért jó, mert visszahozza a programozásba a “fun” részt, amit már-már kiveszni véltem én például. :)
Teljesen egyetertek. Amigan ezert alltam neki kockatforgatni, helikoptertkirajzolni es mas borzalmakat muvelni (Bluebox strikes back) a PowerD nevu nyelvben, amirol azt kell tudni, 1db cseh arc csinalja/csinalta, es az AmigaE-vel rokon nyelv. :P Es egyebkent a PD fordito is E-ben van irva. Es van benne swap operator, tehat a:=:b, es nem kell temp valtozot felvenni, meg akar tobb visszateresi erteke is lehet egy fuggvenynek. :) (Megj: es a PowerD-nek nincs sok koze a Digital Mars fele D nyelvhez.)
Ja es egyebkent igy aranylik a Haskell a Free Pascalhoz, peldaul. Egyebkent meg en kerek elnezest.
[ módosítva Oct.13. 13:16 ]
> Es van benne swap operator […]
Az “van” C/C++ben is (igaz, h csak int-jellegűekre…;)
a ^= b ^= a ^= b;
Es van benne swap operator, tehat a:=:b, es nem kell temp valtozot felvenni
Haskellben nincsenek valtozok, igy aztan nem kell swap, meg temp :)
viszont van cserebe olyan ami megforditja egy fuggveny parametereit:
flip :: (a -> b -> c) -> b -> a -> c
flip f y x = f x y
(kivancsi vagyok a bbcode mit csinal ebbol…)
Na hogy erthetobb legyen, kis kiegeszites:
f x y = x - y
g = flip f
proba:
> f 5 7
-2
> g 5 7
2
(nem lehetne hogy a bbcode altal gyartott kodreszletek ne feketek legyenek sotetszurke hatteren?)
((na az most jo hogy nem fekete, de nem is teletype… csoborbol vodorbe :) szerintem mas szinunek es teletype-nak kellene lennie))
(((na mostmar egeszen ultimate jo kezd lenni. a szinekbe most nem kotok bele :)))
[ módosítva Oct.13. 21:38 ]
Na de a Haskell azért a PHP-t lenyomja :) A Free Pascal meg a C++ -t, G++ -t is. Azért az érdekes. Mondjuk de megnéztem volna ezt a táblázatot Object Pascal (Delphi), Visual C++ paraméterekkel is. Mondjuk a latest verziókra.
Bár az is lehet, hogy a benchmark készítője, csak Free Pascal-ban tudott optimális kódot írni, a többi nyelven gyanúsan 3x futott le minden 1 teszt alatt :)
Egyébként meg a Core Quad-on mindegyik elég gyors, csak írd többszálúra ;-)
[ módosítva Oct.13. 16:24 ]
remage: ez olyan mint a “#define NULL (‘-‘-‘-‘)”
[ módosítva Oct.13. 17:29 ]
mosmá teletype is
ilyenkor mindig rájövök,hogy mennyire nem tudok kódolni. :) ha már ennyire belebuzultunk a fögvényekbe, akkor kiváncsi lennék hogy a szorzásfüggvény milyen függvény segítségével szoroz ? :) valahol eljut a dolog egy olyan pontra mint a matek, hogy a pont az pont és lkész ? :) a szorzás meg mul ax,dx és kész ? :)
Oswald: biztos visszavezetik a tobbszoros osszeadashoz (a’la matematikusok), az osszeadast meg akarmelyik szabadon valasztott axiomarendszerrel a termeszetes szamok rakovetkezes axiomajara vezetik vissza. Hatekonysag mindenek felett! :)
(Mondtam mar, hogy a matematikusok hulyek? ;)
[ módosítva Oct.14. 07:02 ]
Egyrészt a szorzás összeadások sorozata :) Egyébként volt olyan 8×86-os proci (286-os, 386-os?), ahol bizonyos esetekben gyorsabb volt ciklusban összeadni, mint MUL-al szorozni :) A MUL sok órajeles művelet volt.
Egy ideje meg inkább mul eax, edx, de még inkább FMUL :)
Illetve az új GPU végrehajtóknál mi a helyzet szorzás terén? :) Borzasztóan le vagyok maradva én is, mindig ezt látom. De hát Delphi-ből, meg PHP-ből élek, nem pixel shader-ből :)
Matekból meg csak emennyi feltétlenül kell, és megtalálható a középiskolás függvénytárban (az gyorsan “indexelhető” :)), vagy az interneten :) Bár ott mi nem? :)
Oswald: a szorzasfuggveny kelloen elemi ahhoz hogy a compiler valami direkt assembly-re forditsa a vegen, szoval az elemi operaciok be vannak epitve a forditokba. De ez asszem a tobbi nyelvnel is igy van :)
Bery, most elszoltad magad, az interneten eleg sok minden megtalalhato. Jovo heten mondjuk
http://en.wikipedia.org/wiki/Sheaf_(mathematics) ebbol vizsgazhatsz, jo lesz? :D
(nem tunik 100-asnak ez a bbcode implementacio…)
[ módosítva Oct.14. 10:11 ]
blala: durva hibákat tudsz találni :)
blala: én annyira szeretnék bármiből is vizsgázni :)
A Free Pascal meg a C++ -t, G++ -t is. Azért az érdekes. Mondjuk de megnéztem volna ezt a táblázatot Object Pascal (Delphi), Visual C++ paraméterekkel is. Mondjuk a latest verziókra.
Ha jol remlik ez egy Linuxos benchmark, ami elegge kizarja a Delphit meg a Visual C-t. Szerintem a Delphi es az FPC kb. egal szinten van most, van amiben ez a gyorsabb, van amiben az. Legalabbis mikor utoljara neztem ez volt, bar azota sokat tuningoltak az FPC kodgeneratoran.
Bár az is lehet, hogy a benchmark készítője, csak Free Pascal-ban tudott optimális kódot írni, a többi nyelven gyanúsan 3x futott le minden 1 teszt alatt :)
Ez egy nyilt benchmark, barki bekuldhet uj forraskodot, az adott benchmarkhoz, ha ugy erzi, hogy az altala preferalt nyelv hatranyt szenvedett a hibas, vagy nem optimalis implementacio miatt. :)
Tadadam! Már csak egyet kell aludni, és jön a Haskell második része!
Addig irjatok meg par hozzaszolast hogy utolerjuk az opengl konyves cikket :)
commentfiller for blala
Mikor írsz 3 könyvet a témában, Blala? ;-)
nem eleg a cikksorozat, rogton konyv kell, meghozza harom is?! :)
najo de a cikkekbol eddig nem derult ki hogy miert jo a Haskell :)
azert sorozat :) Lehet hogy az evad vegere kiderul… de lehet, hogy nem! surprise!
Ahogy téged ismerlek az évad végén se leszünk okosabbak, de lesz valami cliffhanger :)