Haskell a funkcionální programování (2)

9. 10. 2001
Doba čtení: 6 minut

Sdílet

Druhá část seriálu o Haskellu se zabývá (volně) dostupnými překladači a interprety tohoto jazyka. Větší pozornost je pak věnována zejména interpretu Hugs.

V dnešním pokračování se podíváme na zoubek dostupným překladačům (resp. interpretům) jazyka Haskell. Nejdříve bych však rád uvedl jednu opravu týkající se příkladu s algoritmem QuickSort. Soubor qsort.hs obsahuje opravenou a funkční verzi algoritmu. Berte to jako odstrašující příklad toho, jak to může dopadnout, pokud něco vkládáte stylem cut&paste ze dvou bufferů a nakonec si to po sobě ani nepřečtete, protože překopírovaný kód musí být na beton v pořádku … Nyní ale zpátky k tématu. Na stránkách věnovaných Haskellu je zmínka o čtyřech implementacích, všech volně dostupných.

GHC (http://www.has­kell.org/ghc/)

Glasgow Haskell Compiler je úplná implementace standardu Haskell 98, navíc obsahuje četná rozšíření. Samotný překladač je napsán, jak jinak, v Haskellu :-) a zdrojové kódy jsou volně dostupné. Překladač produkuje rychlý (ale relativně velký) cílový kód. Překlad je pomalejší a je zapotřebí více paměti. Podporuje paralelní programovaní (ve spolupráci s PVM) a také multiprocesing. Od verze 5 je součástí také interpret nazvaný GHCI, inspirovaný jiným oblíbeným interpretem Hugs. Binární distribuce jsou dostupné pro Unixy a pro Windows.

nhc98 (http://www.cs­.york.ac.uk/fp/nhc98­/)

Je menší (v porovnání s GHC) překladač Haskellu 98 vybavený několika užitečnými utilitami (jako jsou např. automatizované překládání bez vytváření souborů makefile, pomocí hmake, nebo profilovací nástroje). Je také méně náročný na paměť a diskový prostor, ale výsledné aplikace nedosahují stejné rychlosti jako při použití GHC. Také nhc98 je dostupný jak ve formě zdrojových kódů, tak i jako binární distribuce.

HBI a HBC (http://www.cs­.chalmers.se/~au­gustss/hbc/hbc­.html)

Narozdíl od předchozích, s touto implementací nemám žádné zkušenosti a uvádím ji tady jenom pro úplnost. Interpret (HBI) a překladač (HBC) Haskellu 98 vycházejí z překladače LML. Nedostatkem této implementace je, že již několik let nebyla vydána žádná nová oficiální verze a také dokumentace a webové stránky jsou zastaralé …

Hugs (http://www.has­kell.org/hugs/)

Je malý interpret napsaný v C. Díky tomu je dostupný pro velké množství strojů a systémů (Unixy, Windows, Dos, Macintosh …). Pro vývoj aplikací je vhodný hlavně díky interaktivitě (možnost vybrat si modul, ve kterém je třeba něco změnit, a odladit jen danou část nezávisle na zbytku programu) a velmi rychlému inkrementálnímu překladu (do mezikódu). Jelikož jde o interpret, je provádění programu samozřejmě pomalejší než u GHC a nhc98. Zajímavé je, že autoři GHC i nhc98 se nechali inspirovat prostředím Hugsu a nabízejí podobná interaktivní rozhraní. Nějaký čas se dokonce plánovalo spojení Hugs a GHC do jednoho projektu. Hugs se doporučuje zájemcům o funkcionální programování, kteří ještě nemají s Haskellem zkušenosti.

Všechny uvedené implementace obsahují kromě samotného překladače (interpretu) i řadu užitečných knihoven od standardního modulu Prelude přes podporu vstupně výstupních operací až po práci s GUI (X server, Windows). Navíc lze na síti nalézt velké množství dalších knihoven a utilit ulehčujících práci. Tady je seznam několika vybraných :

Tabulka č. 204
HDoc generátor HTML dokumentace ze zdrojových kódů.

Green Card preprocesor pro FFI (foreign function interface) zjednodušuje použití externího kódu (napsaného v C) v Haskellu.

CGI Library knihovna ulehčující tvorbu CGI programů (zpracování parametrů, generování výstupu).

HaSQL rozhraní k ODBC umožňující programům v Haskellu klást SQL dotazy databázím podporujícím ODBC.

MySQL-HS knihovna pro spolupráci s MySQL.

Haskell GTK+ rozhraní pro práci s GTK+ (pomocí FFI)

TclHaskell knihovna pro práci s GUI založeném na Tcl/Tk.

HOpenGL propojení Haskellu s API OpenGL (GL, GLU, GLUT).

Fran Functional Reactive Animation – knihovna pro interaktivní 2D, 3D animace a zvuk (běží pod Hugs ve Windows).

WASH knihovny kombinátorů (kombinátor = druh funkce) pro programování webových aplikací (generování dynamických HTML dokumentů, CGI skripty, grafika).

HaXML utility pro používání XML v Haskellu.

Happy generátor syntaktických analyzátorů (obdoba yaccu) pro Haskell.

Alex generátor lexikálních analyzátorů (obdoba lexu).

Regular expression library knihovna pro práci s regulárními výrazy.

Delší seznam můžete nalézt na adrese http://www.has­kell.org/libra­ries/

Prozatím ale můžeme na knihovny zapomenout a raději se podrobněji zaměříme na Hugs. Jak už bylo řečeno, je to interpret s interaktivním prostředím (v textovém režimu). To lze spustit napsáním příkazu

hugs

Poté se vypíše nějaký text o verzi a dále hláška o tom, že se načítá modul Prelude a že jestli chcete nápovědu, máte napsat :? Pokud neuděláte nic jiného, funguje hugs jako jednoduchá kalkulačka. Můžete zkusit zadat nějaký matematický výraz a po potvrzení klávesou <enter> vám hugs vrátí výsledek (nebo chybovou hlášku …) Máme-li ale dělat něco užitečného, potřebujeme pracovat s vlastními moduly. Příkazem :l filenames řekneme, že má hugs nahrát a přeložit moduly uložené v souborech daných jako parametry (jednotlivá jména se oddělují mezerou). Zároveň tím nastavíme poslední modul v seznamu jako aktuální. O tom, který modul je aktuální, informuje poslední řádek textu na obrazovce (ihned po startu je to Prelude). Jako příklad nám může opět posloužit starý známý QuickSort. Za předpokladu, že je soubor qsort.hs uložen v adresáři ~/hugs_prg/ , lze jej nahrát zadáním

:l ~/hugs_prg/qsort.hs

Přípona .hs je nepovinná (hugs automaticky hledá soubory s příponou .hs respektive .lhs), ale pro přehlednost je lepší ji používat. Nyní můžeme vyzkoušet, jestli ‚to třídění‘ opravdu funguje. Zadáte-li například

 qsort [4,-2,1,-2,5,77,66]

vypíše hugs na další řádek

 [-2,-2,1,4,5,66,77]

Můžeme si ověřit i to, zda je naše funkce polymorfní – setřídí i seznamy reálných čísel, znaků a řetězců. Příkaz

qsort ["greetings","from","haskell"]

nám dá výsledek

["from","greetings","haskell"]

Jestli potřebujeme více modulů, lze je dodatečně načíst pomocí příkazu :a filenames (souborů může být opět víc). Zadání příkazu :l bez parametrů odstraní z paměti všechny moduly a nahraje znovu Prelude. Příkazem :r můžeme zopakovat poslední volání příkazu :l (včetně argumentů). Hugs nemá vlastní textový editor, ale umožňuje použít (váš oblíbený) externí editor. To, jaký editor chcete, lze určit příkazem :set -E. Například zadáním

:set -E"gvim +%d %s"

nastavíte jako svůj editor gvim. Řetězec %d je při volání editoru nahrazen číslem řádku, na kterém se má začít editovat (výhodné při opravě chyb), a %s je nahrazeno jménem souboru. Bylo by nepraktické nastavovat editor ručně znovu po každém startu hugs, a proto lze nastavit proměnnou prostředí nazvanou EDITOR. Například pokud používáte jako shell bash, stačí přidat do souboru ~/.profile řádek

export EDITOR="gvim +%d %s"

Soubor lze v hugs editovat zadáním příkazu :e filename. Pokud zadáte pouze příkaz :e, otevře se soubor s aktuálním modulem. Aktuální modul lze změnit pomocí příkazu :m modname, kde modname je jméno modulu. Tady je na místě upozornění, že jméno modulu nemusí být totožné se jménem souboru, ve kterém se nachází zdrojový kód daného modulu (jméno se v Haskellu určuje pomocí klíčového slova module – viz. qsort.hs).

Občas se hodí znát obsah aktuálního prostoru jmen (tj. jména dostupných funkcí). K tomu slouží příkaz :n vzorek, kde parametr vzorek je nepovinný zjednodušený regulární výraz. Je ale dobré vzorek použít, jinak vás hugs zahltí desítkami jmen, hlavně z modulu Prelude. Další možností, jak zjistit dostupná jména, je příkaz :b modnames. Parametr modnames je opět nepovinný (implicitně se použije aktuální modul) a tvoří jej seznam jmen modulů. Výstupem tohoto příkazu není jenom jméno, ale signatura typu funkce. Vezmeme-li opět jako příklad funkci qsort, vypadá signatura typu následovně

bitcoin_skoleni

qsort :: Ord a => [a] -> [a]

což by se dalo popsat takto : funkce qsort má jako vstup seznam prvků obecného typu a. Vrací opět seznam prvků typu a. Dále musí platit, že data typu a jsou instancemi třídy Ord. Nejspíš to není příliš jasné, ale o typech a třídách bude řeč někdy příště …

Užitečným příkazem je :! command, který vykoná externí příkaz command a vypíše jeho výstup. Poslední, pro někoho možná nejdůležitější :-), je příkaz :q, který slouží k ukončení prostředí hugs. Pokud vám předchozí výčet příkazů nestačil, zkuste nápovědu (příkaz :?), případně manuálové stránky (man hugs). Do příštího dílu se můžete těšit na něco, co bych nejspíše nazval „Rychlý a koncentrovaný úvod do programování v Haskellu“, aby si případní zájemci konečně mohli sami zkusit napsat něco jednoduchého.

Autor článku