ZuriHac: praktikimi i programimit funksional

Në qershor të këtij viti, në qytetin e vogël zviceran Rapperswil, një ngjarje e quajtur ZuriHac. Këtë herë ai mblodhi së bashku më shumë se pesëqind dashamirës Haskell, nga fillestarët deri tek themeluesit e gjuhës. Edhe pse organizatorët e quajnë këtë ngjarje një hackathon, ai nuk është një konferencë apo një hackathon në kuptimin klasik. Formati i tij është i ndryshëm nga programuesit tradicionalë. Mësuam për ZuriHac me fat, morëm pjesë në të dhe tani e konsiderojmë si detyrë të tregojmë për gjetjen e pazakontë!

ZuriHac: praktikimi i programimit funksional

Rreth nesh

Ky artikull u përgatit nga dy studentë të vitit të 3-të të programit "Matematika e Aplikuar dhe Informatikë" në Shkollën e Lartë Ekonomike të Universitetit Kombëtar të Kërkimeve - Shën Petersburg: Vasily Alferov dhe Elizaveta Vasilenko. Pasioni për programimin funksional për ne të dy filloi me një sërë leksionesh nga D. N. Moskvin në vitin e 2-të të universitetit. Vasily aktualisht po merr pjesë në programin Google Summer of Code, në kuadër të të cilit ai po zbaton grafikët algjebrikë në Haskell nën drejtimin e ekipit të projektit algë. Elizaveta zbatoi aftësitë e fituara të programimit funksional në punën e kursit kushtuar zbatimit të algoritmit anti-unifikimi me aplikimin e mëvonshëm në teorinë e tipit.

Formati i ngjarjes

Audienca e synuar janë pronarë të projekteve me burim të hapur, programues që duan të marrin pjesë në zhvillimin e tyre, studiues të programimit funksional dhe njerëz thjesht të apasionuar pas Haskell. Këtë vit, zhvillues nga më shumë se pesëdhjetë projekte Haskell me burim të hapur nga e gjithë bota u mblodhën në vendin e ngjarjes - HSR Hochschule für Technik Rapperswil - për të folur për produktet e tyre dhe për të tërhequr njerëz të rinj të interesuar për zhvillimin e tyre.

ZuriHac: praktikimi i programimit funksional

Foto nga Twitter ZuriHac

Skema është shumë e thjeshtë: duhet të shkruani paraprakisht disa propozime për projektin tuaj dhe t'i dërgoni ato organizatorëve, të cilët do të postojnë informacione rreth projektit tuaj në faqen e ngjarjes. Përveç kësaj, në ditën e parë, autorët e projekteve kanë tridhjetë sekonda kohë për të treguar shumë shkurt nga skena se çfarë po bëjnë dhe çfarë duhet bërë. Më pas të interesuarit kërkojnë autorët dhe pyesin në detaje për detyrat.

Ne nuk kemi ende projekte tona të hapura, por me të vërtetë duam të kontribuojmë në ato ekzistuese, ndaj u regjistruam si pjesëmarrës të rregullt. Gjatë tre ditëve, ne punuam me dy grupe zhvilluesish. Rezulton se studimi i përbashkët i kodit dhe komunikimit të drejtpërdrejtë e bën ndërveprimin midis autorëve të projektit dhe kontribuesve shumë produktiv - në ZuriHac ne ishim në gjendje të kuptonim fushat që ishin të reja për ne dhe ishim në gjendje të ndihmonim dy ekipe krejtësisht të ndryshme, duke përfunduar një detyrë në secilën të projekteve.

Krahas praktikës së vlefshme, në ZuriHac u mbajtën edhe disa ligjërata dhe master-klase. Kujtojmë veçanërisht dy leksione. Në të parën prej tyre, Andrey Mokhov nga Universiteti i Newcastle foli për funksionorët aplikativë selektivë - një klasë llojesh që duhet të bëhen ndërmjetëse midis funksionuesve aplikativë dhe monadave. Në një leksion tjetër, një nga themeluesit e Haskell, Simon Peyton Jones, foli për mënyrën se si funksionon konkluzioni i tipit në përpiluesin GHC.

ZuriHac: praktikimi i programimit funksional

Leksion nga Simon Peyton Jones. Foto nga Twitter ZuriHac

Master-klasat e mbajtura gjatë hackathon-it u ndanë në tre kategori në varësi të nivelit të trajnimit të pjesëmarrësve. Detyrat e ofruara për pjesëmarrësit që iu bashkuan zhvillimit të projekteve u shënuan gjithashtu me një nivel vështirësie. Komuniteti i vogël por miqësor i programuesve funksionalë mirëpret me kënaqësi të sapoardhurit në radhët e tij. Megjithatë, për të kuptuar leksionet e Andrei Mokhov dhe Simon Peyton Jones, kursi i programimit funksional që morëm në universitet ishte shumë i dobishëm.

Regjistrimi për këtë ngjarje është falas si për pjesëmarrësit e rregullt ashtu edhe për autorët e projektit. Kemi dorëzuar aplikacione për pjesëmarrje në fillim të qershorit, pas së cilës u transferuam shpejt nga lista e pritjes në listën e pjesëmarrësve të konfirmuar.

Dhe tani do të flasim për projektet në zhvillimin e të cilave kemi marrë pjesë.

Pandok

Pandok është një konvertues universal i dokumenteve tekstuale, në fakt, nga çdo format në cilindo. Për shembull, nga docx në pdf, ose nga Markdown në MediaWiki. Autori i tij, John MacFarlane, është profesor i filozofisë në Universitetin e Kalifornisë, Berkeley. Në përgjithësi, Pandoc është mjaft i famshëm dhe disa nga miqtë tanë u habitën kur mësuan se Pandoc ishte shkruar në Haskell.

ZuriHac: praktikimi i programimit funksional

Lista e formateve të dokumenteve të mbështetura nga Pandoc. Ekziston edhe një grafik i tërë në faqe, por kjo foto nuk përshtatet në artikull.

Sigurisht, Pandoc nuk ofron konvertim të drejtpërdrejtë për çdo palë formatesh. Për të mbështetur një larmi kaq të gjerë transformimesh, përdoret një zgjidhje standarde arkitekturore: së pari, i gjithë dokumenti përkthehet në një paraqitje të veçantë të ndërmjetme të brendshme dhe më pas krijohet një dokument në një format tjetër nga ky përfaqësim i brendshëm. Zhvilluesit e quajnë përfaqësimin e brendshëm "AST", që qëndron për Pemë Abstract Syntax, ose pema e sintaksës abstrakte. Ju mund ta shikoni paraqitjen e ndërmjetme shumë thjesht: gjithçka që duhet të bëni është të vendosni formatin e daljes në "amtare"

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

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

Lexuesit që kanë punuar me Haskell të paktën pak mund të supozojnë tashmë nga ky shembull i vogël se Pandoc është shkruar në Haskell: prodhimi i kësaj komande është një paraqitje e vargut të strukturave të brendshme të Pandoc, e krijuar në ngjashmërinë se si bëhet zakonisht. në Haskell, për shembull, në bibliotekën standarde.

Pra, këtu mund të shihni se përfaqësimi i brendshëm është një strukturë rekursive, në secilën nyje të brendshme të së cilës ka një listë. Për shembull, në nivelin e lartë ekziston një listë e një elementi - titulli i nivelit të parë me atributet "hello-world",[],[]. E fshehur brenda këtij titulli është një listë e vargut "Përshëndetje", e ndjekur nga një hapësirë ​​dhe vargu "Bota!".

Siç mund ta shihni, përfaqësimi i brendshëm nuk është shumë i ndryshëm nga HTML. Është një pemë ku çdo nyje e brendshme ofron disa informacione në lidhje me formatimin e pasardhësve të saj, dhe gjethet përmbajnë përmbajtjen aktuale të dokumentit.

Nëse zbresim në nivelin e zbatimit, lloji i të dhënave për të gjithë dokumentin përcaktohet si kjo:

data Pandoc = Pandoc Meta [Block]

Këtu Blloku janë pikërisht kulmet e brendshme të përmendura më lart, dhe Meta është metainformacion për dokumentin, si titulli, data e krijimit, autorët - kjo është e ndryshme për formate të ndryshme dhe Pandoc përpiqet, nëse është e mundur, të ruajë një informacion të tillë kur përkthen nga formati në format.

Pothuajse të gjithë konstruktorët e llojit Blloku - për shembull, Header ose Para (paragraf) - marrin si argument atribute dhe një listë të kulmeve të nivelit më të ulët - Inline, si rregull. Për shembull, Space ose Str janë konstruktorë të llojit Inline, dhe etiketa HTML gjithashtu shndërrohet në Inline të veçantë. Ne nuk shohim asnjë pikë në ofrimin e një përkufizimi të plotë të këtyre llojeve, por vini re se ai mund të gjendet këtu këtu.

Është interesante se lloji Pandoc është një monoid. Kjo do të thotë se ekziston një lloj dokumenti bosh dhe se dokumentet mund të grumbullohen së bashku. Kjo është e përshtatshme për t'u përdorur kur shkruani Readers - mund ta ndani një dokument në pjesë duke përdorur logjikë arbitrare, të analizoni secilën veçmas dhe më pas t'i bashkoni gjithçka në një dokument. Në këtë rast, metainformacioni do të mblidhet nga të gjitha pjesët e dokumentit menjëherë.

Kur konvertohet, le të themi, nga LaTeX në HTML, fillimisht një modul special i quajtur LaTeXReader konverton dokumentin hyrës në AST, më pas një modul tjetër i quajtur HTMLWriter konverton AST në HTML. Falë kësaj arkitekture, nuk ka nevojë të shkruani një numër kuadratik të konvertimeve - mjafton të shkruani Reader dhe Writer për çdo format të ri dhe të gjitha çiftet e mundshme të konvertimeve do të mbështeten automatikisht.

Është e qartë se një arkitekturë e tillë ka edhe të metat e saj, të parashikuara prej kohësh nga ekspertët e fushës së arkitekturës së softuerit. Më e rëndësishmja është kostoja e bërjes së ndryshimeve në pemën sintaksore. Nëse ndryshimi është mjaft serioz, do të duhet të ndryshoni kodin në të gjithë Readers dhe Writers. Për shembull, një nga sfidat me të cilat përballen zhvilluesit e Pandoc është mbështetja e formateve komplekse të tabelave. Tani Pandoc mund të krijojë vetëm tabela shumë të thjeshta, me një kokë, kolona dhe një vlerë në secilën qelizë. Për shembull, atributi colspan në HTML thjesht do të injorohet. Një nga arsyet për këtë sjellje është mungesa e një skeme të unifikuar për paraqitjen e tabelave në të gjitha ose të paktën shumë formate - në përputhje me rrethanat, është e paqartë se në çfarë forme duhet të ruhen tabelat në paraqitjen e brendshme. Por edhe pasi të zgjidhni një pamje specifike, do t'ju duhet të ndryshoni absolutisht të gjithë lexuesit dhe shkrimtarët që mbështesin punën me tabela.

Gjuha Haskell u zgjodh jo vetëm për shkak të dashurisë së madhe të autorëve për programimin funksional. Haskell është i njohur për aftësitë e tij të gjera të përpunimit të tekstit. Një shembull është biblioteka Parsec është një bibliotekë që përdor në mënyrë aktive konceptet e programimit funksional - monoide, monada, funksionorë aplikativë dhe alternativë - për të shkruar analizues arbitrar. Fuqia e plotë e Parsec mund të shihet në shembull nga HaskellWiki, ku analizohet një analizues i plotë i një gjuhe programimi të thjeshtë imperativ. Sigurisht, Parsec përdoret gjithashtu në mënyrë aktive në Pandoc.

Përshkruar shkurtimisht, monadat përdoren për analizë sekuenciale, kur një gjë vjen së pari dhe më pas një tjetër. Për shembull, në këtë shembull:

whileParser :: Parser Stmt
whileParser = whiteSpace >> statement

Së pari ju duhet të numëroni hapësirën, dhe më pas deklaratën - e cila gjithashtu ka llojin Parser Stmt.

Funktorët alternativë përdoren për të rikthyer nëse analizimi dështon. Për shembull,

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

Kjo do të thotë që ju ose duhet të përpiqeni të lexoni deklaratën në kllapa, ose të përpiqeni të lexoni disa deklarata me radhë.

Funktorët aplikativë përdoren kryesisht si shkurtore për monadat. Për shembull, lëreni funksionin tok të lexojë disa shenja (ky është një funksion real nga LaTeXReader). Le të shohim këtë kombinim

const <$> tok <*> tok

Do të lexojë dy shenja me radhë dhe do të kthejë të parën.

Për të gjitha këto klasa, Haskell ka operatorë të bukur simbolikë, gjë që e bën programimin Reader të duket si arti ASCII. Thjesht admironi këtë kod të mrekullueshëm.

Detyrat tona ishin të lidhura me LaTeXReader. Detyra e Vasily ishte të mbështeste komandat mbox dhe hbox, të dobishme për të shkruar paketa në LaTeX. Elizabeth ishte përgjegjëse për mbështetjen e komandës së epigrafit, e cila ju lejon të krijoni epigrafë në dokumentet LaTeX.

Hatrace

Sistemet operative të ngjashme me UNIX shpesh zbatojnë thirrjen e sistemit ptrace. Është i dobishëm në korrigjimin dhe simulimin e mjediseve të programit, duke ju lejuar të gjurmoni thirrjet e sistemit që bën programi. Për shembull, mjeti shumë i dobishëm strace përdor ptrace brenda.

Hatrace është një bibliotekë që ofron një ndërfaqe për ptrace në Haskell. Fakti është se vetë ptrace është shumë e sofistikuar dhe është mjaft e vështirë të përdoret drejtpërdrejt, veçanërisht nga gjuhët funksionale.

Hatrace funksionon si strace në fillim dhe pranon argumente të ngjashme. Ai ndryshon nga strace në atë që është gjithashtu një bibliotekë që ofron një ndërfaqe më të thjeshtë sesa thjesht ptrace.

Me ndihmën e hatrace, ne kemi kapur tashmë një gabim të pakëndshëm në përpiluesin GHC Haskell - duke u vrarë në momentin e gabuar, ai gjeneron skedarë të pasaktë të objekteve dhe nuk i ripërpilon ato kur riniset. Skriptimi nga thirrjet e sistemit bëri të mundur riprodhimin e besueshëm të gabimit në një ekzekutim, ndërsa vrasjet e rastësishme riprodhuan gabimin në rreth dy orë.

Ne shtuam ndërfaqet e thirrjeve të sistemit në bibliotekë - Elizaveta shtoi brk dhe Vasily shtoi mmap. Bazuar në rezultatet e punës sonë, është e mundur të përdoren më thjesht dhe më saktë argumentet e këtyre thirrjeve të sistemit gjatë përdorimit të bibliotekës.

Burimi: www.habr.com

Shto një koment