ZuriHac: vježbanje funkcionalnog programiranja

U lipnju ove godine u malom švicarskom gradiću Rapperswilu održana je manifestacija tzv ZuriHac. Ovaj put okupio je više od pet stotina ljubitelja Haskell-a, od početnika do utemeljitelja jezika. Iako organizatori ovaj događaj nazivaju hackathonom, on nije konferencija niti hackathon u klasičnom smislu. Njegov se format razlikuje od tradicionalnih programera. Srećom smo saznali za ZuriHac, sudjelovali u tome, a sada smatramo našom dužnošću ispričati o neobičnom pronalasku!

ZuriHac: vježbanje funkcionalnog programiranja

O nama

Ovaj članak pripremila su dva studenta 3. godine programa “Primijenjena matematika i informatika” na Nacionalnom istraživačkom sveučilištu Visoka škola ekonomije - St. Petersburg: Vasily Alferov i Elizaveta Vasilenko. Strast prema funkcionalnom programiranju za nas oboje započela je nizom predavanja D. N. Moskvina na 2. godini sveučilišta. Vasily trenutno sudjeluje u programu Google Summer of Code u sklopu kojeg implementira algebarske grafove u Haskell-u pod vodstvom projektnog tima Alga. Elizaveta je primijenila stečene vještine funkcionalnog programiranja u radu na kolegiju posvećenom implementaciji algoritma protiv unifikacije s naknadnom primjenom u teoriji tipova.

Format događaja

Ciljana publika su vlasnici projekata otvorenog koda, programeri koji žele sudjelovati u njihovom razvoju, istraživači funkcionalnog programiranja i ljudi jednostavno zaljubljeni u Haskell. Ove godine, programeri iz više od pedeset Haskell projekata otvorenog koda iz cijelog svijeta okupili su se na mjestu događaja - HSR Hochschule für Technik Rapperswil - kako bi razgovarali o svojim proizvodima i zainteresirali nove ljude za njihov razvoj.

ZuriHac: vježbanje funkcionalnog programiranja

Fotografija s Twittera ZuriHac

Shema je vrlo jednostavna: morate unaprijed napisati nekoliko prijedloga o svom projektu i poslati ih organizatorima koji će objaviti informacije o vašem projektu na stranici događaja. Uz to, prvog dana autori projekata imaju tridesetak sekundi da vrlo kratko s pozornice kažu što rade i što treba učiniti. Zatim zainteresirani traže autore i detaljno se raspituju o zadacima.

Još uvijek nemamo svoje otvorene projekte, ali jako želimo doprinijeti postojećima, pa smo se prijavili kao redovni sudionici. Tijekom tri dana radili smo s dvije grupe programera. Ispostavilo se da zajedničko proučavanje koda i živa komunikacija čini interakciju između autora projekta i suradnika vrlo produktivnom - u ZuriHacu smo mogli razumjeti područja koja su nam bila nova i mogli smo pomoći dvama potpuno različitim timovima, ispunjavajući po jedan zadatak u svakom projekata.

Osim vrijedne prakse, u ZuriHacu je održano i nekoliko predavanja i majstorskih tečajeva. Posebno pamtimo dva predavanja. Na prvom od njih Andrey Mokhov sa Sveučilišta u Newcastleu govorio je o selektivnim aplikativnim funktorima - klasi tipova koji bi trebali postati posrednik između aplikativnih funktora i monada. U drugom predavanju, jedan od osnivača Haskella, Simon Peyton Jones, govorio je o tome kako zaključivanje tipa funkcionira u GHC kompajleru.

ZuriHac: vježbanje funkcionalnog programiranja

Predavanje Simona Peytona Jonesa. Fotografija s Twittera ZuriHac

Majstorski tečajevi održani tijekom hackathona podijeljeni su u tri kategorije ovisno o stupnju obučenosti sudionika. Zadaci ponuđeni sudionicima koji su se uključili u izradu projekata također su označeni stupnjem težine. Mala, ali prijateljska zajednica funkcionalnih programera s radošću dočekuje pridošlice u svoje redove. Međutim, za razumijevanje predavanja Andreja Mokhova i Simona Peytona Jonesa, tečaj funkcionalnog programiranja koji smo slušali na sveučilištu bio je vrlo koristan.

Registracija za događaj je besplatna kako za stalne sudionike tako i za autore projekata. Prijave za sudjelovanje predali smo početkom lipnja, nakon čega smo vrlo brzo s liste čekanja prebačeni na listu potvrđenih polaznika.

A sada ćemo govoriti o projektima u čijem smo razvoju sudjelovali.

pandoc

pandoc je univerzalni pretvarač tekstualnih dokumenata, zapravo, iz bilo kojeg formata u bilo koji. Na primjer, iz docx u pdf ili iz Markdown u MediaWiki. Njegov autor, John MacFarlane, profesor je filozofije na kalifornijskom sveučilištu Berkeley. Općenito, Pandoc je prilično poznat, a neki od naših prijatelja bili su iznenađeni kada su saznali da je Pandoc napisan na Haskell-u.

ZuriHac: vježbanje funkcionalnog programiranja

Popis formata dokumenata koje podržava Pandoc. Na stranici postoji i cijeli grafikon, ali ova slika ne stane u članak.

Naravno, Pandoc ne omogućuje izravnu konverziju za svaki par formata. Kako bi se podržao tako veliki izbor transformacija, koristi se standardno arhitektonsko rješenje: prvo se cijeli dokument prevodi u poseban intermedijarni prikaz, a zatim se iz tog internog prikaza generira dokument u drugom formatu. Programeri nazivaju interni prikaz "AST", što je skraćenica za Abstract Syntax Tree, ili stablo apstraktne sintakse. Srednji prikaz možete pogledati vrlo jednostavno: sve što trebate učiniti je postaviti izlazni format na "nativni"

$ cat example.html
<h1>Hello, World!</h1>

$ pandoc -f html -t native example.html
[Header 1 ("hello-world",[],[]) [Str "Hello,",Space,Str "World!"]]

Čitatelji koji su barem malo radili s Haskell-om već mogu pretpostaviti iz ovog malog primjera da je Pandoc napisan u Haskell-u: izlaz ove naredbe je prikaz niza internih struktura Pandoc-a, stvoren na sličan način kako se to obično radi u Haskell-u, na primjer, u standardnoj knjižnici.

Dakle, ovdje možete vidjeti da je interna reprezentacija rekurzivna struktura, u čijem svakom internom čvoru postoji lista. Na primjer, na najvišoj razini nalazi se popis jednog elementa - zaglavlje prve razine s atributima "hello-world",[],[]. Unutar ovog zaglavlja skriven je popis niza "Hello", nakon kojeg slijedi razmak i niz "World!".

Kao što vidite, interni prikaz se ne razlikuje puno od HTML-a. To je stablo u kojem svaki unutarnji čvor pruža neke informacije o oblikovanju svojih potomaka, a listovi sadrže stvarni sadržaj dokumenta.

Ako se spustimo na razinu implementacije, tip podataka za cijeli dokument je definiran ovako:

data Pandoc = Pandoc Meta [Block]

Ovdje su Block upravo gore spomenuti interni vrhovi, a Meta metainformacije o dokumentu, poput naslova, datuma izrade, autora - to je različito za različite formate, a Pandoc pokušava, ako je moguće, sačuvati takve informacije prilikom prevođenja iz formata u format.

Gotovo svi konstruktori tipa Block - na primjer, Header ili Para (paragraph) - uzimaju atribute i popis vrhova niže razine kao argumente - Inline, u pravilu. Na primjer, Space ili Str su konstruktori tipa Inline, a HTML oznaka također se pretvara u svoj poseban Inline. Ne vidimo smisla pružati potpunu definiciju ovih tipova, ali imajte na umu da se ona može pronaći ovdje здесь.

Zanimljivo je da je tip Pandoc monoid. To znači da postoji nekakav prazan dokument i da se dokumenti mogu slagati zajedno. Ovo je zgodno koristiti kada pišete Readers - dokument možete rastaviti na dijelove proizvoljnom logikom, analizirati svaki zasebno, a zatim sve zajedno staviti u jedan dokument. U tom će slučaju metainformacije biti prikupljene iz svih dijelova dokumenta odjednom.

Prilikom pretvorbe, recimo, iz LaTeX-a u HTML, prvo poseban modul nazvan LaTeXReader pretvara ulazni dokument u AST, zatim drugi modul nazvan HTMLWriter pretvara AST u HTML. Zahvaljujući ovoj arhitekturi, nema potrebe pisati kvadratni broj konverzija - dovoljno je napisati Reader i Writer za svaki novi format i svi mogući parovi konverzija bit će automatski podržani.

Jasno je da ovakva arhitektura ima i svoje nedostatke, koje stručnjaci u području softverske arhitekture odavno predviđaju. Najznačajniji je trošak izmjena u stablu sintakse. Ako je promjena dovoljno ozbiljna, morat ćete promijeniti kod u svim čitateljima i piscima. Na primjer, jedan od izazova s ​​kojima se suočavaju programeri Pandoca je podrška složenim formatima tablica. Sada Pandoc može stvarati samo vrlo jednostavne tablice, sa zaglavljem, stupcima i vrijednošću u svakoj ćeliji. Na primjer, atribut colspan u HTML-u jednostavno će biti zanemaren. Jedan od razloga ovakvog ponašanja je nepostojanje jedinstvene sheme za predstavljanje tablica u svim ili barem mnogim formatima - sukladno tome, nejasno je u kojem bi obliku tablice trebale biti pohranjene u internom prikazu. Ali čak i nakon odabira određenog prikaza, morat ćete promijeniti apsolutno sve čitače i pisce koji podržavaju rad s tablicama.

Jezik Haskell nije odabran samo zbog velike ljubavi autora prema funkcionalnom programiranju. Haskell je poznat po svojim opsežnim mogućnostima obrade teksta. Jedan primjer je knjižnica parsek je biblioteka koja aktivno koristi koncepte funkcionalnog programiranja - monoide, monade, aplikativne i alternativne funktore - za pisanje proizvoljnih parsera. Puna snaga Parseca može se vidjeti u primjer iz HaskellWikija, gdje se analizira potpuni parser jednostavnog imperativnog programskog jezika. Naravno, Parsec se također aktivno koristi u Pandocu.

Ukratko opisano, monade se koriste za sekvencijalno raščlanjivanje, kada jedna stvar dolazi prvo, a zatim druga. Na primjer, u ovom primjeru:

whileParser :: Parser Stmt
whileParser = whiteSpace >> statement

Prvo treba prebrojati razmak, a zatim iskaz - koji također ima tip Parser Stmt.

Alternativni funktori koriste se za vraćanje unatrag ako raščlanjivanje ne uspije. Na primjer,

statement :: Parser Stmt
statement = parens statement <|> sequenceOfStmt

Znači da trebate pokušati pročitati izjavu u zagradama ili pokušati pročitati nekoliko izjava uzastopno.

Aplikativni funktori se prvenstveno koriste kao prečaci za monade. Na primjer, neka funkcija tok pročita neki token (ovo je prava funkcija iz LaTeXReader-a). Pogledajmo ovu kombinaciju

const <$> tok <*> tok

Pročitat će dva žetona u nizu i vratiti prvi.

Za sve te klase, Haskell ima prekrasne simboličke operatore, zbog čega programiranje Readera izgleda poput ASCII umjetnosti. Samo se divite ovom prekrasnom kodu.

Naši su zadaci bili vezani uz LaTeXReader. Vasilyjev zadatak bio je podržavati naredbe mbox i hbox, korisne za pisanje paketa u LaTeX-u. Elizabeth je bila odgovorna za podršku naredbi epigrafa, koja vam omogućuje stvaranje epigrafa u LaTeX dokumentima.

Hatrace

Operativni sustavi slični UNIX-u često implementiraju sistemski poziv ptrace. Koristan je u otklanjanju pogrešaka i simulaciji programskih okruženja, omogućujući vam praćenje sistemskih poziva koje program upućuje. Na primjer, vrlo koristan uslužni program strace koristi ptrace interno.

Hatrace je biblioteka koja pruža sučelje za ptrace u Haskell-u. Činjenica je da je ptrace sam po sebi vrlo sofisticiran i prilično ga je teško izravno koristiti, posebno iz funkcionalnih jezika.

Hatrace radi kao strace pri pokretanju i prihvaća slične argumente. Razlikuje se od strace po tome što je također knjižnica koja pruža jednostavnije sučelje nego samo ptrace.

Uz pomoć hatrace-a, već smo uhvatili jednu neugodnu grešku u GHC Haskell kompajleru - budući da se ugasio u krivom trenutku, generira netočne objektne datoteke i ne kompajlira ih ponovno kada se ponovno pokrene. Skriptiranje pomoću sistemskih poziva omogućilo je pouzdano reproduciranje pogreške u jednom pokretanju, dok je nasumično ubijanje reproduciralo pogrešku za otprilike dva sata.

Knjižnici smo dodali sučelja sistemskih poziva - Elizaveta je dodala brk, a Vasily mmap. Na temelju rezultata našeg rada moguće je jednostavnije i točnije koristiti argumente ovih sistemskih poziva prilikom korištenja biblioteke.

Izvor: www.habr.com

Dodajte komentar