Úvod

V tomto kurzu se budeme zabývat funkcionálním programovacím jazykem Haskell, se kterým jste měli možnost pracovat již v předmětu IB015 (Úvod do funkcionálního programování).

Historie Haskellu a jeho verze

Nejdůležitější body historie Haskellu:

My budeme pracovat s překladačem GHC (The Glorious Glasgow Haskell Compilation System) a jeho interaktivní variantou GHCi. Ten podporuje rozšíření definovaná Haskellem' a je považován za průmyslový standard.

GHC

Tři základní příkazy:

Překladač GHC

Vstupem překladače je zdrojový soubor obsahující funkci main :: IO (). Tato funkce je zavolána jako první po spuštění přeloženého programu. Výstupem je binární soubor, případně kód v C či assembleru. V překladači je kód interně reprezentován v jazyce C−−. Při překladu se můžeme setkat se soubory s těmito příponami:

Parametry překladače GHC se v mnohém podobají céčkovému překladači GCC. Standardně můžeme přeložit program příkazem ghc soubor.hs -o výstup, pokud ale používáme nějakou knihovnu, tento příkaz se nevypořádá se závislostmi. Naštěstí má ale překladač parametr --make, který se o závislosti postará. Doporučuje se tedy překlad programu pomocí příkazu ghc --make soubor.hs. V tomto případě můžeme dokonce příponu souboru vynechat, tedy stačí napsat pouze ghc --make soubor.

Bývá zvykem soubory ve větším projektu pojmenovávat s počátečním velkým písmenem a jejich obsah rozčleňovat do modulů. Jak takové moduly fungují, si představíme na třetím cvičení. Pro více informací o překladu nahlédněte do manuálové stránky (man ghc) nebo do dokumentace překladače.

Interpret GHCi

Pro většinu operací nám bude stačit interpret Haskellu ghci. Podobně jako v Hugsu do něj vlastní kód můžeme načíst pomocí příkazu :l soubor a obnovit ho pomocí :r. Rozdíl je však v načítání modulů. Příkaz pro přidávání dalších modulů je :m + Modul, pro odebírání :m - Modul. Při načtení většího množství modulů přestane být zadávání příkazu přehledné, v tom případě můžeme přenastavit prompt pomocí příkazu :set prompt "> ". Tabulátor doplňuje názvy funkcí. Všechny dostupné příkazy lze zobrazit pomocí :h.

Stejně jako v Hugsu zobrazíme typ výrazu příkazem :t. Pro vypsání podrobnějších informací o funkci (či datovém typu) slouží příkaz :i. Příjemnou změnou oproti Hugsu je možnost si definovat funkci přímo v interpretu pomocí příkazu let. Speciálním případem tohoto přiřazení je funkce it znázorňující výsledek posledního napsaného příkazu. V případě potřeby si můžeme všechna tato přiřazení vypsat pomocí příkazu :show bindings.

> let pi = 3.14
> let perimeter r = 2 * pi * r
> perimeter 5
31.400000000000002
> :show bindings
it :: Double = 31.400000000000002
perimeter :: Double -> Double = _
pi :: Double = 3.14
> 1 + 1
2
> it
2
> it * 10
20

Skriptování

Typické použití: chceme spustit soubor se zdrojovým kódem, ale nepotřebujeme ho mít v binární formě ani nechceme využívat možnosti interpretu. Po napsání příkazu runhaskell soubor.hs se zavolá funkce main v souboru soubor.hs. Ve skutečnosti se využívá programu runghc, příkaz runhaskell je jen symbolický odkaz na něj.

Balíčkovací systém Haskellu

Haskell má relativně velkou komunitu, jejíž členové vytvářejí velké množství knihoven a různých nástrojů pro práci v Haskellu. Proto byl v roce 2004 spuštěn repozitář Hackage spolu s balíčkovacím systémem Cabal. Z tohoto repozitáře lze jednoduše stahovat a instalovat knihovny Haskellu pomocí cabalových balíčků. Asi nejjednodušší způsob pro získání přístupu k těmto balíčkům je nainstalovat si aplikaci Haskell Platform, jež obsahuje všechny důležité nástroje pro vývoj v Haskellu.

Hackage

Balíčky v repozitáři Hackage můžeme procházet přímo, nebo je prohledávat pomocí dvou vyhledávačů:

Hoogle

Vyhledávač Hoogle (název je odvozen od Google) je starší ze dvou vyhledávačů. Umožňuje vyhledávání pomocí názvu funkce či jejího typu, bohužel však prohledává pouze několik základních knihoven. Vyniká svou jednoduchostí a přesnými výsledky vyhledávání.

Hayoo

Vyhledávač Hayoo (název je odvozen od Yahoo!) umožňuje v podstatě totéž co Hoogle, jenom prohledává celý repozitář Hackage, navíc přes moderní AJAXové rozhraní.

Cabal

Tento pokročilý balíčkovací systém nám umožňuje přes nástroj cabal-install instalovat balíčky z Hackage přímo z příkazové řádky. Nemusíme se tak zabývat závislostmi ani nic sestavovat ručně. Veškerý instalovaný obsah se ukládá do adresáře ~/.cabal, případné spouštěcí soubory lze nalézt v adresáři ~/.cabal/bin. (Nastavte si proto vhodně proměnnou $PATH ve svém shellu, například přidáním řádku export PATH=$PATH:$HOME/.cabal/bin do souboru ~/.bashrc.) Seznam instalovaných balíčků je ukrytý v adresáři ~/.ghc, proto v případě odinstalování balíčku nestačí pouze smazat soubory, je nutné použít i příkaz ghc-pkg unregister. Příklad instalace balíčku:

$ cabal update
Downloading the latest package list from hackage.haskell.org
$ cabal install pureMD5
Resolving dependencies...
Downloading pureMD5-2.1.0.3...
Configuring pureMD5-2.1.0.3...
Preprocessing library pureMD5-2.1.0.3...
Preprocessing executables for pureMD5-2.1.0.3...
Building pureMD5-2.1.0.3...
[1 of 1] Compiling Data.Digest.Pure.MD5 ( Data/Digest/Pure/MD5.hs, dist/build/Data/Digest/Pure/MD5.o )
Registering pureMD5-2.1.0.3...
Installing library in /home/xdvor/.cabal/lib/pureMD5-2.1.0.3/ghc-6.12.1
Registering pureMD5-2.1.0.3...

Příkaz cabal update stáhne aktuální seznam balíčků, příkaz cabal install balíček nainstaluje požadovaný balíček. Poskytnutý modul pak můžeme použít v našem programu:

$ cat md5-test.hs
import Data.Digest.Pure.MD5
import Data.ByteString.Lazy.Char8

main :: IO ()
main = print . md5 $ pack "test"
$ ghc --make md5-test
[1 of 1] Compiling Main             ( md5-test.hs, md5-test.o )
Linking md5-test ...
$ ./md5-test
098f6bcd4621d373cade4e832627b4f6

V tomto příkladu je použita funkce md5 z knihovny Data.Digest.Pure.MD5, která slouží ke generování MD5 hašů. Jako vstup požaduje řetězec typu ByteString, jenž je vytvořen převodem z „obyčejného“ řetězce typu String pomocí funkce pack z knihovny Data.ByteString.Lazy.Char8.

Pro více informací o balíčkovacím systému Cabal se podívejte do jeho dokumentace.

Ruční sestavení

Může se stát, že automatická instalace nebude z nějakého důvodu fungovat. V tom případě si můžete balíček stáhnout, rozbalit, přejít vytvořeného adresáře a napsat následující příkazy:

$ cabal configure
$ cabal build
$ cabal copy
$ cabal register

Pokud nemáme cabal k dispozici, můžeme se pokusit balíček sestavit ručně. K tomu nám slouží tato trojice příkazů:

$ runhaskell Setup configure
$ runhaskell Setup build
$ runhaskell Setup install

Poslední příkaz musí být spuštěn pod administrátorským účtem. Pokud nemáme tuto možnost, lze balíček nainstalovat do domovského adresáře. V tomto případě bychom první příkaz nahradili za příkaz runhaskell Setup configure --user --prefix=$HOME.

Další zajímavé projekty

Leksah

Leksah je vývojové prostředí Haskellu. Lze ho používat na psaní domácích úkolů do tohoto předmětu. Instaluje se napsáním příkazu cabal install gtk2hs-buildtools && cabal install leksah (pozor, pro jeho provoz potřebujete zhruba 500 MB volného místa v domovském adresáři; aktuální stav na školních počítačích zjistíte pomocí příkazu quota -s). Ovládání této aplikace není přímočaré, pro více informací si pročtěte manuál k Leksahu.

Darcs

Darcs je distribuovaný verzovací systém napsaný v Haskellu a používaný pro správu mnoha haskellových projektů. Svými vlastnostmi se podobá verzovacímu systému Git.

Lambdabot

Lambdabot je užitečný pomocník při programování v Haskellu. Umí vyhodnocovat výrazy, určovat jejich typ, vyhledávat pomocí Hoogle, převádět na pointfree (pointless) tvar, zabrazovat zdrojový kód funkcí, generovat kód k daným typům, ověřovat platnost zadaných výrazů a mnoho dalších věcí. V základním nastavení se chová jako IRC bot.

Xmonad

Xmonad je minimalistický okenní správce, který spolu s lištou Xmobar tvoří tak trochu netradiční, avšak efektivní rozhraní pro ovládání osobního počítače běžícího na unixovém systému.

← IB016