☰ Menu

Scene.hu

Magyar demoscene portál – grafikusok, zenészek, programozók alkotói közössége

Haskell_Logo_w.pngNos, 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ó.

vagas.png
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 almafa=0;
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

zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]

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)

zipWith (*) [1,2,3,4] [5,6,7,8]

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:

[1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3…]

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 :: (a -> b -> c) -> [a] -> [b] -> [c]
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. :)

Categories: Programozás | Tags

55 Responses so far.

  1. avatar slyspy says:

    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.

  2. avatar blala says:

    Majd a masodik (harmadik, …) reszben a tobbi szo is el lesz magyarazva, erre a reszre 3 vagy 4 szo jutott :)

  3. avatar Murphy says:

    Én még mindig nem értem… Mikor lesz a folytatás? :)

  4. avatar FooLman says:

    Fubazz, Haskellban demot irni, az nem semmi lelkivilagra vall. Ha nem Blala tette volna, komolyan aggodnek az illetoert :)
    Na, de hol a folytatas?

  5. avatar MaNiAc says:

    Ebben demot irni? :O Az egyetemen anno szoba kerult, de hala az egnek nem eroltettek nagyon :) Respect annak, aki ebben programozik :D

  6. avatar blala says:

    folytatas lesz, csak meg kicsit varok a reakciokra

  7. avatar Bery says:

    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á :)

  8. avatar slyspy says:

    Én is akarok örülni! Laikusul vattafak a különbség?

  9. avatar Maxie says:

    Ennél még a matlab is jobb gyerekek. Blala orvos látott már?:) ugye ez nem ilyen ELTE matek miatt elkapott dolog?:)

  10. avatar -SP- says:

    Ez a nyelv nagyon nem keresztény…

  11. avatar blala says:

    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? :))

  12. avatar Murphy says:

    A Haskell jött, látott és mindenkit meggyőzött :)

  13. avatar Georgy says:

    ez fasza, majd beleásom magam.:)

  14. avatar pohar says:

    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 :)

  15. avatar Gargaj says:

    nem mindegy hogy mihez irnak C-ben compilert/interpretert? :)

  16. avatar blala says:

    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 :)

  17. avatar slyspy says:

    az első kompilert a joisten teremtette? :)

  18. avatar blala says:

    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 ]

  19. avatar Jimmi says:

    Programozzatok brainfuckban, ‘HQ9+’-ban vagy whitespace-ben. Abban van kihívás.

  20. avatar pohar says:

    Jimmi: ha ‘szalagutcában’ programozok az nem jó? :Ö

  21. avatar Bery says:

    É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…

  22. avatar blala says:

    csak gondolod? nem mintha sok mas lehetoseguk lett volna :)

  23. avatar reptile says:

    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 ]

  24. avatar Gargaj says:

    ha nem adja ki, tobbet nem engedjuk be functionre, kb ennyi.

  25. avatar slyspy says:

    Ki lesz adva, mert bazmeg nem azért írtam bele zenét, hogy ott maradjon Blala fiókjában. :)

    Nő a nyomás. :)

  26. avatar zoom says:

    valaki toljon már belőle egy 0-day cracket :D

  27. avatar -SP- says:

    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

  28. avatar FooLman says:

    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?????

  29. avatar blala says:

    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 :)

  30. avatar pohar says:

    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 ]

  31. avatar Bery says:

    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 ]

  32. avatar rachy says:

    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 ]

  33. avatar Gargaj says:

    ez a dude irta a Cubeot is ja

  34. avatar SDr says:

    ilyen még kell.

  35. avatar Charlie says:
    wrote
    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 ]

  36. avatar Remage says:

    > Es van benne swap operator […]

    Az “van” C/C++ben is (igaz, h csak int-jellegűekre…;)

    a ^= b ^= a ^= b;

  37. avatar blala says:
    wrote
    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 ]

  38. avatar Bery says:

    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 ]

  39. avatar Gargaj says:

    remage: ez olyan mint a “#define NULL (‘-‘-‘-‘)”
    [ módosítva Oct.13. 17:29 ]

  40. avatar zoom says:

    mosmá teletype is

  41. avatar Oswald says:

    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 ? :)

  42. avatar rachy says:

    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 ]

  43. avatar Bery says:

    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? :)

  44. avatar blala says:

    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 ]

  45. avatar Murphy says:

    blala: durva hibákat tudsz találni :)

  46. avatar Bery says:

    blala: én annyira szeretnék bármiből is vizsgázni :)

  47. avatar Charlie says:
    wrote
    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.

    wrote
    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. :)

  48. avatar Murphy says:

    Tadadam! Már csak egyet kell aludni, és jön a Haskell második része!

  49. avatar blala says:

    Addig irjatok meg par hozzaszolast hogy utolerjuk az opengl konyves cikket :)

  50. avatar pohar says:

    commentfiller for blala

  51. avatar Bery says:

    Mikor írsz 3 könyvet a témában, Blala? ;-)

  52. avatar blala says:

    nem eleg a cikksorozat, rogton konyv kell, meghozza harom is?! :)

  53. avatar Gargaj says:

    najo de a cikkekbol eddig nem derult ki hogy miert jo a Haskell :)

  54. avatar blala says:

    azert sorozat :) Lehet hogy az evad vegere kiderul… de lehet, hogy nem! surprise!

  55. avatar Murphy says:

    Ahogy téged ismerlek az évad végén se leszünk okosabbak, de lesz valami cliffhanger :)

Leave a Reply

You must be logged in to post a comment.

Ugrás a lap tetejére Ugrás a lap aljára