ZuriHac: pagsasanay ng functional programming

Noong Hunyo ng taong ito, sa maliit na bayan ng Switzerland ng Rapperswil, tinawag ang isang kaganapan ZuriHac. Sa pagkakataong ito, pinagsama-sama nito ang higit sa limang daang Haskell lovers, mula sa mga baguhan hanggang sa mga founding father ng wika. Bagama't tinawag ng mga tagapag-ayos ang kaganapang ito na isang hackathon, hindi ito isang kumperensya o isang hackathon sa klasikal na kahulugan. Ang format nito ay iba sa mga tradisyunal na programmer. Nalaman namin ang tungkol sa ZuriHac sa pamamagitan ng kapalaran, nakibahagi dito, at ngayon ay itinuturing naming tungkulin naming sabihin ang tungkol sa hindi pangkaraniwang paghahanap!

ZuriHac: pagsasanay ng functional programming

Tungkol sa amin

Ang artikulong ito ay inihanda ng dalawang 3rd year na mag-aaral ng programang "Applied Mathematics and Informatics" sa National Research University Higher School of Economics - St. Petersburg: Vasily Alferov at Elizaveta Vasilenko. Ang hilig para sa functional programming para sa aming dalawa ay nagsimula sa isang serye ng mga lektura ni D. N. Moskvin sa ika-2 taon ng unibersidad. Kasalukuyang nakikilahok si Vasily sa Google Summer of Code program, kung saan siya ay nagpapatupad ng mga algebraic graph sa Haskell sa ilalim ng gabay ng pangkat ng proyekto Alga. Inilapat ni Elizaveta ang nakuhang functional na mga kasanayan sa programming sa kursong trabaho na nakatuon sa pagpapatupad ng anti-unification algorithm na may kasunod na aplikasyon sa type theory.

Format ng kaganapan

Ang target na madla ay mga may-ari ng mga open source na proyekto, mga programmer na gustong lumahok sa kanilang pag-unlad, mga functional na mananaliksik sa programming, at mga taong mahilig lang sa Haskell. Sa taong ito, nagtipon ang mga developer mula sa mahigit limampung open source na Haskell na proyekto mula sa buong mundo sa venue - ang HSR Hochschule fΓΌr Technik Rapperswil - upang pag-usapan ang kanilang mga produkto at makakuha ng mga bagong tao na interesado sa kanilang pag-unlad.

ZuriHac: pagsasanay ng functional programming

Larawan mula sa Twitter ZuriHac

Ang pamamaraan ay napaka-simple: kailangan mong magsulat ng ilang mga panukala tungkol sa iyong proyekto nang maaga at ipadala ang mga ito sa mga organizer, na mag-post ng impormasyon tungkol sa iyong proyekto sa pahina ng kaganapan. Bilang karagdagan, sa unang araw, ang mga may-akda ng mga proyekto ay may tatlumpung segundo upang maipahayag nang maikli mula sa entablado kung ano ang kanilang ginagawa at kung ano ang kailangang gawin. Pagkatapos ay hinahanap ng mga interesadong tao ang mga may-akda at nagtanong nang detalyado tungkol sa mga gawain.

Wala pa kaming sariling bukas na mga proyekto, pero gusto talaga naming mag-ambag sa mga umiiral na, kaya nagparehistro kami bilang mga regular na kalahok. Sa loob ng tatlong araw, nakipagtulungan kami sa dalawang grupo ng mga developer. Lumalabas na ang pinagsamang pag-aaral ng code at live na komunikasyon ay gumagawa ng pakikipag-ugnayan sa pagitan ng mga may-akda ng proyekto at mga kontribyutor na napaka-produktibo - sa ZuriHac naunawaan namin ang mga lugar na bago sa amin at nakatulong sa dalawang ganap na magkaibang mga koponan, na nakumpleto ang isang gawain sa bawat isa ng mga proyekto.

Bilang karagdagan sa mahalagang pagsasanay, maraming mga lektura at master class ang ibinigay din sa ZuriHac. Naaalala namin lalo na ang dalawang lektura. Sa una sa kanila, si Andrey Mokhov mula sa Unibersidad ng Newcastle ay nagsalita tungkol sa mga selective applicative functors - isang klase ng mga uri na dapat maging intermediate sa pagitan ng applicative functors at monads. Sa isa pang lecture, isa sa mga tagapagtatag ng Haskell, Simon Peyton Jones, ay nagsalita tungkol sa kung paano gumagana ang uri ng inference sa GHC compiler.

ZuriHac: pagsasanay ng functional programming

Lektura ni Simon Peyton Jones. Larawan mula sa Twitter ZuriHac

Ang mga master class na ginanap sa hackathon ay nahahati sa tatlong kategorya depende sa antas ng pagsasanay ng mga kalahok. Ang mga gawaing inaalok sa mga kalahok na sumali sa pagbuo ng mga proyekto ay minarkahan din ng antas ng kahirapan. Ang maliit ngunit magiliw na komunidad ng mga functional programmer ay masayang tinatanggap ang mga bagong dating sa kanilang hanay. Upang maunawaan ang mga lektura nina Andrei Mokhov at Simon Peyton Jones, gayunpaman, ang kursong functional programming na kinuha namin sa unibersidad ay lubhang kapaki-pakinabang.

Ang pagpaparehistro para sa kaganapan ay libre para sa parehong mga regular na kalahok at mga may-akda ng proyekto. Nagsumite kami ng mga aplikasyon para sa pakikilahok noong unang bahagi ng Hunyo, pagkatapos ay mabilis kaming inilipat mula sa listahan ng naghihintay sa listahan ng mga nakumpirmang kalahok.

At ngayon ay pag-uusapan natin ang tungkol sa mga proyekto sa pagbuo kung saan tayo ay nakibahagi.

Pandoc

Pandoc ay isang unibersal na converter ng mga tekstong dokumento, sa katunayan, mula sa anumang format patungo sa alinman. Halimbawa, mula docx hanggang pdf, o mula Markdown hanggang MediaWiki. Ang may-akda nito, si John MacFarlane, ay isang propesor ng pilosopiya sa Unibersidad ng California, Berkeley. Sa pangkalahatan, sikat ang Pandoc, at nagulat ang ilan sa aming mga kaibigan nang malaman nila na nakasulat ang Pandoc sa Haskell.

ZuriHac: pagsasanay ng functional programming

Listahan ng mga format ng dokumento na sinusuportahan ng Pandoc. Mayroon ding isang buong graph sa site, ngunit ang larawang ito ay hindi magkasya sa artikulo.

Siyempre, hindi nagbibigay ang Pandoc ng direktang conversion para sa bawat pares ng mga format. Upang suportahan ang isang malawak na pagkakaiba-iba ng mga pagbabagong-anyo, isang karaniwang solusyon sa arkitektura ang ginagamit: una, ang buong dokumento ay isinalin sa isang espesyal na panloob na intermediate na representasyon, at pagkatapos ay isang dokumento sa ibang format ay nabuo mula sa panloob na representasyong ito. Tinatawag ng mga developer ang panloob na representasyon na "AST", na nangangahulugang Abstract Syntax Tree, o abstract syntax tree. Maaari mong tingnan ang intermediate na representasyon nang napakasimple: ang kailangan mo lang gawin ay itakda ang format ng output sa "katutubong"

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

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

Ang mga mambabasa na nakipagtulungan sa Haskell kahit kaunti ay maaari nang ipalagay mula sa maliit na halimbawang ito na ang Pandoc ay nakasulat sa Haskell: ang output ng command na ito ay isang string na representasyon ng mga panloob na istruktura ng Pandoc, na nilikha sa pagkakahawig ng kung paano ito karaniwang ginagawa sa Haskell.halimbawa, sa karaniwang aklatan.

Kaya, dito makikita mo na ang panloob na representasyon ay isang recursive na istraktura, sa bawat panloob na node kung saan mayroong isang listahan. Halimbawa, sa pinakamataas na antas mayroong isang listahan ng isang elemento - ang unang antas ng header na may mga katangiang "hello-world",[],[]. Nakatago sa loob ng header na ito ang isang listahan ng string na "Hello," na sinusundan ng isang space at ang string na "World!".

Tulad ng nakikita mo, ang panloob na representasyon ay hindi gaanong naiiba sa HTML. Ito ay isang puno kung saan ang bawat panloob na node ay nagbibigay ng ilang impormasyon tungkol sa pag-format ng mga inapo nito, at ang mga dahon ay naglalaman ng mga aktwal na nilalaman ng dokumento.

Kung pupunta tayo sa antas ng pagpapatupad, ang uri ng data para sa buong dokumento ay tinukoy tulad nito:

data Pandoc = Pandoc Meta [Block]

Narito ang Block ay tiyak ang mga panloob na vertices na binanggit sa itaas, at ang Meta ay metainformation tungkol sa dokumento, tulad ng pamagat, petsa ng paglikha, mga may-akda - ito ay naiiba para sa iba't ibang mga format, at Pandoc ay sumusubok, kung maaari, upang mapanatili ang naturang impormasyon kapag nagsasalin mula sa format patungo sa pormat.

Halos lahat ng mga konstruktor ng uri ng Block - halimbawa, Header o Para (talata) - kumuha ng mga katangian at isang listahan ng mas mababang antas ng vertices bilang mga argumento - Inline, bilang panuntunan. Halimbawa, ang Space o Str ay mga constructor ng Inline na uri, at ang HTML tag ay nagiging sarili nitong espesyal na Inline. Wala kaming nakikitang punto sa pagbibigay ng kumpletong kahulugan ng mga ganitong uri, ngunit tandaan na ito ay matatagpuan dito dito.

Kapansin-pansin, ang uri ng Pandoc ay isang monoid. Nangangahulugan ito na mayroong ilang uri ng walang laman na dokumento, at maaaring pagsama-samahin ang mga dokumento. Maginhawa itong gamitin kapag nagsusulat ng Mga Mambabasa - maaari mong hatiin ang isang dokumento sa mga bahagi gamit ang di-makatwirang lohika, i-parse ang bawat isa nang hiwalay, at pagkatapos ay pagsamahin ang lahat sa isang dokumento. Sa kasong ito, ang metainformation ay kokolektahin mula sa lahat ng bahagi ng dokumento nang sabay-sabay.

Kapag nagko-convert, sabihin nating, mula sa LaTeX patungo sa HTML, unang isang espesyal na module na tinatawag na LaTeXReader ang nagko-convert ng input na dokumento sa AST, pagkatapos ay isa pang module na tinatawag na HTMLWriter ang nagko-convert ng AST sa HTML. Salamat sa arkitektura na ito, hindi na kailangang magsulat ng isang parisukat na bilang ng mga conversion - sapat na ang pagsulat ng Reader at Writer para sa bawat bagong format, at lahat ng posibleng pares ng mga conversion ay awtomatikong susuportahan.

Malinaw na ang ganitong arkitektura ay mayroon ding mga disbentaha, matagal nang hinulaan ng mga eksperto sa larangan ng arkitektura ng software. Ang pinakamahalaga ay ang gastos sa paggawa ng mga pagbabago sa syntax tree. Kung ang pagbabago ay sapat na seryoso, kailangan mong baguhin ang code sa lahat ng Mga Mambabasa at Manunulat. Halimbawa, ang isa sa mga hamon na kinakaharap ng mga developer ng Pandoc ay ang pagsuporta sa mga kumplikadong format ng talahanayan. Ngayon ang Pandoc ay maaari lamang lumikha ng napakasimpleng mga talahanayan, na may isang header, mga haligi at isang halaga sa bawat cell. Halimbawa, ang colspan attribute sa HTML ay babalewalain lang. Ang isa sa mga dahilan para sa pag-uugali na ito ay ang kakulangan ng isang pinag-isang pamamaraan para sa kumakatawan sa mga talahanayan sa lahat o hindi bababa sa maraming mga format - nang naaayon, ito ay hindi malinaw sa kung anong anyo ang mga talahanayan ay dapat na naka-imbak sa panloob na representasyon. Ngunit kahit na pagkatapos pumili ng isang partikular na view, kakailanganin mong ganap na baguhin ang lahat ng Mga Mambabasa at Manunulat na sumusuporta sa pagtatrabaho sa mga talahanayan.

Ang wikang Haskell ay pinili hindi lamang dahil sa malaking pagmamahal ng mga may-akda para sa functional programming. Ang Haskell ay kilala sa malawak nitong kakayahan sa pagpoproseso ng teksto. Isang halimbawa ay ang aklatan parsec ay isang library na aktibong gumagamit ng mga konsepto ng functional programming - monoids, monads, applicative at alternative functors - upang magsulat ng mga arbitrary na parser. Ang buong kapangyarihan ng Parsec ay makikita sa isang halimbawa mula sa HaskellWiki, kung saan na-parse ang isang kumpletong parser ng isang simpleng imperative programming language. Siyempre, ang Parsec ay aktibong ginagamit din sa Pandoc.

Sa madaling sabi, ang mga monad ay ginagamit para sa sunud-sunod na pag-parse, kapag nauna ang isang bagay, at pagkatapos ay isa pa. Halimbawa, sa halimbawang ito:

whileParser :: Parser Stmt
whileParser = whiteSpace >> statement

Una kailangan mong bilangin ang espasyo, at pagkatapos ay ang pahayag - na mayroon ding uri ng Parser Stmt.

Ang mga alternatibong function ay ginagamit upang i-rollback kung mabigo ang pag-parse. Halimbawa,

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

Nangangahulugan na kailangan mong subukang basahin ang pahayag sa mga bracket, o subukang basahin ang ilang mga pahayag nang sunud-sunod.

Pangunahing ginagamit ang mga applicative function bilang mga shortcut para sa mga monad. Halimbawa, hayaan ang tok function na magbasa ng ilang token (ito ay isang tunay na function mula sa LaTeXReader). Tingnan natin ang kumbinasyong ito

const <$> tok <*> tok

Magbabasa ito ng dalawang magkasunod na token at ibabalik ang una.

Para sa lahat ng mga klaseng ito, ang Haskell ay may magagandang simbolikong operator, na ginagawang parang ASCII art ang programming ng Reader. Humanga lang sa napakagandang code na ito.

Ang aming mga gawain ay nauugnay sa LaTeXReader. Ang gawain ni Vasily ay suportahan ang mbox at hbox na mga utos, na kapaki-pakinabang para sa pagsusulat ng mga pakete sa LaTeX. Responsable si Elizabeth sa pagsuporta sa epigraph command, na nagbibigay-daan sa iyong gumawa ng mga epigraph sa mga dokumento ng LaTeX.

Hatrace

Ang mga operating system na tulad ng UNIX ay madalas na nagpapatupad ng ptrace system call. Ito ay kapaki-pakinabang sa pag-debug at pagtulad sa mga kapaligiran ng programa, na nagbibigay-daan sa iyong masubaybayan ang mga tawag sa system na ginagawa ng programa. Halimbawa, ang napaka-kapaki-pakinabang na strace utility ay gumagamit ng ptrace sa loob.

Ang Hatrace ay isang library na nagbibigay ng isang interface upang ptrace sa Haskell. Ang katotohanan ay ang ptrace mismo ay napaka sopistikado at medyo mahirap gamitin ito nang direkta, lalo na mula sa mga functional na wika.

Ang Hatrace ay tumatakbo tulad ng strace sa startup at tumatanggap ng mga katulad na argumento. Naiiba ito sa strace dahil isa rin itong library na nagbibigay ng mas simpleng interface kaysa ptrace lamang.

Sa tulong ng hatrace, nahuli na namin ang isang hindi kanais-nais na bug sa GHC Haskell compiler - pinapatay sa maling sandali, bumubuo ito ng mga maling object file at hindi na muling kino-compile ang mga ito kapag na-restart. Ang pag-script sa pamamagitan ng mga tawag sa system ay naging posible upang mapagkakatiwalaang kopyahin ang error sa isang pagtakbo, habang ang mga random na pagpatay ay muling ginawa ang error sa loob ng halos dalawang oras.

Nagdagdag kami ng mga interface ng system call sa library - Idinagdag ni Elizaveta ang brk, at idinagdag ni Vasily ang mmap. Batay sa mga resulta ng aming trabaho, posibleng mas simple at tumpak na gamitin ang mga argumento ng mga system call na ito kapag ginagamit ang library.

Pinagmulan: www.habr.com

Magdagdag ng komento