Přejít k navigační liště

Zdroják » Různé » Happstack: část první

Happstack: část první

Články Různé

Webový framework Happstack je postaven na funkcionálním jazyce Haskell. Vývoj webových aplikací pomocí jazyka deklarativního paradigmatu je pro běžného vývojáře něčím těžko představitelným. V tomto miniseriálu si proto společně ukážeme základní koncepty a naučíme se vytvářet jednoduché aplikace.

Většina webových aplikací je napsána v nějakém z imperativních jazyků. Nezáleží na tom, zda-li se jedná o PHP, Javu, či cokoliv jiného, tyto jazyky fungují na principu vykonávání sekvence příkazů (imperativů). Kód takového jazyka se tak podobá receptu: přiřaď tuhle hodnotu sem, pokud se rovná jiné hodnotě, vynásob ji a výsledek ulož tam, jinak udělej něco jiného. Oproti tomu deklarativní jazyky pouze zavádí (deklarují) určitá tvrzení, kterými se překladač při vyhodnocování řídí. Kód funkcionálních jazyků se tak často podobá matematickému předpisu: faktoriál přirozeného čísla většího než nula se rovná násobku faktoriálu čísla o jedno menší, jinak se rovná jedničce.

Současným trendem je přejímání některých funkcionálních prvků do imperativních jazyků, protože mohou výrazně zkrátit a zpřehlednit kód. Možná používáte anonymní funkce v JavaScriptu, generátory seznamů v Pythonu, nebo funkce vyššího řádu v Ruby, aniž byste tušili, že pochází z funkcionálního světa. Proto znalost funkcionálního programování rozhodně není na škodu a může vám pomoci stát se lepším programátorem v konvenčnějších jazycích. Kromě toho existuje nejeden úspěšný webový projekt, jenž byl napsán v nějakém z funkcionálních jazyků, což popisuje kupříkladu Paul Graham ve svém článku Beating the Averages.

Seznamte se, Haskell

Haskell je čistě funkcionální jazyk, který je staticky typovaný, referenčně transparentní a jeho kód se vyhodnocuje líně. Při programování ve frameworku Happstack se bez jeho znalosti neobejdeme. Jako lehký úvod do tohoto jazyka může sloužit seriál Petera Almásyho Haskell a funkcionalní programování, pro bezbolestné pochopení základů doporučuji tutoriál Naučte se Haskell! a praktičtější příklady přináší kniha Real World Haskell, která je k dispozici zdarma online.

Nemáte-li s funkcionálním programováním zatím žádné zkušenosti, nevadí. Nahlédnutí do tohoto seriálu může být užitečné i z hlediska popisu principů, na nichž framework stojí.

Pokud jste, stejně jako já, spíše praktičtěji zaměření, určitě vás bude zajímat, jak je na tom Haskell s rychlostí, stabilitou a rozšířeností. Mnoho zajímavých jazyků je v praxi obtížně nasaditelných, protože nepodávají dostatečný výkon, jejich implementace jsou neúplné či chybové, případně pro ně vůbec neexistuje použitelný překladač pro požadovanou platformu. Haskell prošel již poměrně dlouhým vývojem (jeho počátky sahají do konce osmdesátých let), jeho překladač GHC je stabilní, podporuje nativní překlad jak pro systémy založené na Unixu, tak pro Windows, a výkonnostně je na tom velice dobře (viz např. The Computer Language Benchmarks Game).

Alternativy k Happstacku

Happstack není jediným zástupcem svého druhu. V Haskellu je napsáno několik dalších knihoven pro vývoj webových aplikací. Příkladem může být framework Turbinado, který se v lecčem podobá Ruby on Rails či Djangu, jenže ten byl nedávno opuštěn hlavním vývojářem a tím pádem se přestal vyvíjet. I samotný Happstack měl podobný osud — jeho kód vychází z frameworku HAppS, jenž byl taktéž zanechán svému osudu. Autoři nejspíše psaní frameworku brali jako výzvu a po dotažení do použitelné podoby ztratili zájem o další rozšiřování. Kromě těchto dvou frameworků existuje spousta dalších, jejichž nekompletní seznam lze nalézt, spolu s popisem haskellových webových serverů a dalších užitečných knihoven, na HaskellWiki.

Instalace

Haskell má vlastní instalační systém Cabal. Ten umožňuje jednoduchou instalaci bez nutnosti programy překládat ručně. Ovládá se přes rozhraní Cabal-install. Pro zprovoznění tohoto systému je třeba mít nainstalovaný překladač GHC (nejlépe nejnovější verze) společně s Haskell Platform, což je sada nejčastěji používaných rozšiřujících knihoven Haskellu, mezi nimiž se nachází i Cabal.

Veškerá data instalačního systému se ukládají do adresáře ~/.cabal/. Nachází se tam i adresář bin, který je třeba přidat do proměnné prostředí PATH, kupříkladu připsáním řádku export PATH="$PATH:$HOME/.cabal/bin" na konec souboru  ~/.bashrc.

Jakmile máme Cabal funkční, stačí nám zadat do příkazové řádky tyto příkazy:

$ cabal update
Downloading the latest package list from hackage.haskell.org
$ cabal install happstack
Resolving dependencies...
... 

Příkaz cabal update získá aktuální seznam balíčku z repozitáře Hackage, příkaz cabal install happstack automaticky stáhne a nainstaluje balíček happstack včetně jeho závislostí. Pokud z nějakého důvodu automatická instalace přes Cabal nefunguje, musíme si stáhnout balíčky ručně, rozbalit je, a pomocí této trojice příkazů nakonfigurovat a přeložit:

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

Tento postup je zdlouhavý a nedoporučuje se, protože Happstack závisí na mnoha jiných balíčcích. Ať už jsme nainstalovali modul Happstack jakýmkoliv způsobem, jeho funkčnost ověříme napsáním příkazu  happstack:

$ happstack
Usage: happstack <command>
Possible commands:
  build auto <buildCmd> <binPath> <binArgs>...: invoke the auto-builder
  new project <dir>: create a new happstack project 

Pomocný příkaz happstack slouží k ulehčení zakládání a sestavování projektů Happstacku, což jsou vlastně jenom adresáře s předpřipravenými daty. My si vytvoříme svůj vlastní adresář, kam umístíme svůj první program.

Náš první program

Konvence stanovuje hlavní soubor projektu pojmenovávat jako Main.hs. Do tohoto souboru napíšeme tento jednoduchý kód:

module Main where

import Happstack.Server

main :: IO ()
main = simpleHTTP nullConf $ return "Ahoj světe!"

V kódu importujeme modul Happstack.Server obsahující funkci simpleHTTP, jenž spouští webový server na výchozím portu 8000. První parametr této funkce je konfigurační struktura (datový typ Conf), druhý parametr je samotný aplikační kód (typu ServerPartT IO). Tato ukázka vrací na každý dotaz text Ahoj světe!, a protože je to parametr typu IO, používá funkci return. Happstack se standardně dodává s vlastní implementací webového serveru.

Když soubor uložíme, spustíme v příkazovém řádku příkaz runhaskell Main a zadáme do prohlížeče adresu http://localhos­t:8000/, zobrazí se nám v něm text. Stisknutím klávesové zkratky Ctrl + C můžeme spuštěný server ukončit a program si přeložit do binárního kódu:

$ ghc --make Main
[1 of 1] Compiling Main             ( Main.hs, Main.o )
Linking Main ... 

Vytvoří se nám soubor Main, který spustíme pomocí příkazu ./Main. Pro vývoj a testování je lepší nečekat, než se kód přeloží, ale spouštět si zdrojový kód příkazem runhaskell, kdežto pro nasazení je lepší mít kód již přeložený.

Nasazení pomocí FastCGI

Vestavěný webový server je poměrně rychlý, ale nepoužívá vlákna. Jestliže na náš server míří velké množství HTTP požadavků, jejich obsloužení nemůže probíhat paralelně a tím pádem narůstá doba odezvy. V reálném světě by tedy těžko obstál. Pomocí balíčku happstack-fastcgi máme možnost Happstack propojit s knihovnou FastCGI, která běží pod Apache či pod jiným webovým serverem. Před napsáním příkazu cabal install happstack-fastcgi je nutné nainstalovat vývojové soubory FastCGI (v Debianu se jedná o balíček libfcgi-dev). Poté v našem programu provedeme několik změn:

module Main where

import Happstack.Server
import Happstack.Server.FastCGI

main :: IO ()
main = runFastCGIConcurrent 8 . serverPartToCGI $ return "Ahoj světe!"

Kombinace funkcí runFastCGIConcurrent a serverPartToCGI spustí server s osmi vlákny, přičemž aplikační kód zůstane stejný. Tento program musíme následně přeložit s parametrem pro zapnutí podpory vláken:

$ ghc -threaded --make Main.hs -o main.fcgi
[1 of 1] Compiling Main             ( Main.hs, Main.o )
Linking main.fcgi ... 

Pomocí parametru -o si stanovíme název výsledného binárního kódu. Dále tuto binárku musíme propojit se serverem. Do konfigurace serveru (např. u Apache 2 to je soubor /etc/apache2/httpd.conf) připíšeme tento kód:

<VirtualHost *:80>
  FastCGIExternalServer example.cz/main.fcgi -socket example.cz/main.sock
  RewriteEngine On
  RewriteRule ^/(.*)$ /example.cz/main.fcgi/$1 [QSA,L]

  ServerName example.cz
  ServerAlias www.example.cz
  DocumentRoot /var/www/
</VirtualHost> 

Konfigurace nám zajistí, aby se pro doménu example.cz, která má veškeré soubory uloženy v adresáři /var/www/example.cz/, použil soubor main.fcgi. Přepisování pomocí mod_rewrite nám obstarává „hezká“ URL. Po překopírování naší binárky do tohoto adresáře a restartu serveru (příkaz /etc/init.d/apache2 restart) uvidíme na adrese http://example­.cz/ opět náš text. Tedy za předpokladu, že na náš server směřuje DNS záznam  example.cz.

Související odkazy

Příště si vytvoříme obsáhlejší příklad, který bude zpracovávat data.

Komentáře

Subscribe
Upozornit na
guest
13 Komentářů
Nejstarší
Nejnovější Most Voted
Inline Feedbacks
View all comments
Trm

Rikat, ze haskel je deklarativni jazyk, je teda opravdu trochu mimo. ,,Ciste funkcionalni“ by mozna bylo lepsi.

binary_runner

Popis v prvim odstavci spis odpovida jazykum logickym (napr. Prolog).
Deklarativni je taky SQL. Funkcionalni jazyky funguji jinak, napr. lambda vyrazy mi moc deklarativni neprijdou. A vubec … http://en.wikipedia.org/wiki/Programming_language_theory

stilett

Vzhledem k tomu, že funkcionální (zejména čistě funkcionální) jazyky patří mezi deklarativní jazyky, tak mimo není ani trochu.

iyo

Podarilo sa niekomu nainštalovať happstack pomocou cabal na Ubuntu 9.10? Samotná inštalácia zlyhá kvôli (mimo iné) balíčku trhsx:
> cabal install trhsx
Resolving dependencies…
Configuring trhsx-0.2.2…
Preprocessing library trhsx-0.2.2…
Building trhsx-0.2.2…
[1 of 1] Compiling Trhsx ( Trhsx.hs, dist/build/Trhsx.o )
Trhsx.hs:1:0:
Failed to load interface for `Prelude‘:
it is a member of the hidden package `base-3.0.3.1′
it is a member of the hidden package `base‘
Use -v to see a list of the files searched for.
cabal: Error: some packages failed to install:
trhsx-0.2.2 failed during the building phase. The exception was:
exit: ExitFailure 1
Dostal sa niekto ďalej?

jirtos

Možná je to mnou, ale v článku mi, kromě tématu „výzvy“, chybý nějaký adekvátní důvod proč vůbec vyvíjet web aplikaci pod tímhle frameworkem, resp. ned haskelem obecně. Kromě informace, že překlad a stabilita je ok tam nevidím nic. Díky

Radek Miček

Protože si procvičíte Haskell nebo protože se naučíte něco nového.

Radek Miček

Kromě toho existuje nejeden úspěšný webový projekt, jenž byl napsán v nějakém z funkcionálních jazyků, což popisuje kupříkladu…
Docela by mě zajímalo, co si představujete pod pojmem funkcionální jazyk. IMO funkcionální jazyky kladou důraz na neměnitelnost dat, což se o většině Lispů říct nedá (vyjma Clojure).

Radek Miček

Já jsem právě napsal „klade důraz“, čímž jsem chtěl říci, že data je sice možné měnit, ale jazyk včetně základních knihoven je uzpůsoben tak, že to ve většině případů není nutné.

Enum a statická analýza kódu

Mám jednu univerzální radu pro začínající programátorty. V učení sice neexistují rychlé zkratky, ovšem tuhle radu můžete snadno začít používat a zrychlit tak tempo učení. Tou tajemnou ingrediencí je statická analýza kódu. Ukážeme si to na příkladu enum.