ZuriHac: praktikojmë programimin funksional

Në qershor të këtij viti, në një qytet të vogël zviceran, Rapperswil, u mbajt aktiviteti i quajtur ZuriHac. Këtë herë, më shumë se pesëqind adhurues të Haskell-it, nga fillestarë deri te baballarët e gjuhës, u mblodhën. Edhe pse organisatorët e quajnë këtë aktivitet një hackathon, mbi të gjitha, ai nuk është një konferencë ose hackathon në kuptimin klasik. Formati i tij është ndryshe nga ato tradicionale për programuesit. Ne mësuam për ZuriHac rastësisht, morëm pjesë në të, dhe tani e konsiderojmë detyrë tonë të tregojmë për këtë gjetje të pazakontë!

ZuriHac: praktikojmë programimin funksional

NĂ« lidhje me ne

Ky artikull u përgatit nga dy studentë të vitit të tretë të programit "Matematika dhe Informatika e Aplikuar" në HSE - Shën Petersburg: Vasily Alfyorov dhe Elizaveta Vasilenko. Shkaku i pasionit për programimin funksional për të dy filloi me ciklin e ligjëratave të D. N. Moskvin në vitin e dytë të universitetit. Aktualisht, Vasily po merr pjesë në programin Google Summer of Code, në kuadër të të cilit po punon në implementimin e grafëve algebraikë në gjuhën Haskell nën drejtimin e ekipit të projektit Alga. Elizaveta ka aplikuar aftësitë e marra në programimin funksional në punimin e saj të kursit, i cili është dedikuar implementimit të algoritmit anti-unifikim me aplikim të mëvonshëm në teorinë e tipave.

Formati i aktivitetit

DĂ«gjuesit e synuar janĂ« pronarĂ«t e projekteve me kod tĂ« hapur, programuesit qĂ« duan tĂ« kontribuojnĂ« nĂ« zhvillimin e tyre, kĂ«rkuesit e programimit funksional dhe thjesht tĂ« apasionuarit pas Haskell-it. KĂ«tĂ« vit nĂ« vendin e zhvillimit – universiteti HSR Hochschule fĂŒr Technik Rapperswil – u mblodhĂ«n zhvillues nga mĂ« shumĂ« se pesĂ«dhjetĂ« projekte tĂ« hapura nĂ« gjuhĂ«n Haskell nga e gjithĂ« bota, pĂ«r tĂ« treguar produktet e tyre dhe pĂ«r tĂ« interesuar persona tĂ« rinj nĂ« zhvillimin e tyre.

ZuriHac: praktikojmë programimin funksional

Foto nga Twitter ZuriHac

Schemi është shumë e thjeshtë: duhet të shkruani disa propozime për projektin tuaj dhe t'i dërgoni ato organizatorëve, të cilët do të publikojnë informacionin mbi projektin tuaj në faqen e aktivitetit. Për më tepër, në ditën e parë, autorët e projekteve kanë tridhjetë sekonda për të treguar shumë shkurt nga skena se me çfarë po merren dhe çfarë duhet bërë. Më pas, ata që kanë interes gjejnë autorët dhe pyesin për detyra.

Aktualisht nuk kemi projekte të hapura të pronësisë tonë, por ne duam shumë të kontribuojmë në ato ekzistuese, prandaj regjistruam si pjesëmarrës të zakonshëm. Gjatë tre ditëve, punuam me dy grupe zhvilluesish. Doli se studimi i bashkuar i kodit dhe komunikimi në kohë reale e bën ndërveprimin midis autorëve të projektit dhe kontribuesve shumë produktiv - në ZuriHac arritëm të kuptojmë fusha të reja për ne dhe arritëm të ndihmojmë dy ekipe të ndryshme, duke mbyllur nga një detyrë në secilin nga projektet.

Përveç praktikës së çmueshme, në ZuriHac u mbajtën disa ligjërata dhe masterklasa. Na kujtohen veçanërisht dy ligjërata. Në të parën, Andrey Mokhov nga Universiteti i Newcastleit foli mbi funktoret aplikativë selektivë - një klasë tipesh që duhet të jetë ndërmjet funktorëve aplikativë dhe monadave. Në ligjëratën tjetër, një nga themeluesit e Haskell, Simon Peyton Jones, fliste për mënyrën se si funksionon nxjerrja e tipave në kompajlerin GHC.

ZuriHac: praktikojmë programimin funksional

Ligjërata e Simon Peyton Jones. Foto nga Twitter ZuriHac

Masterklasat që u mbajtën gjatë hackathonit u ndanë në tre kategori në varësi të nivelit të përgatitjes së pjesëmarrësve. Detyrat që iu ofruan pjesëmarrësve që iu bashkuan zhvillimit të projekteve gjithashtu kishin shenja me nivelin e vështirësisë. Një komunitet i vogël, por i bashkuar i programuesve funksionalë me kënaqësi pranon në radhët e tij fillestarët. Megjithatë, për të kuptuar ligjëratat e Andrey Mokhov dhe Simon Peyton Jones, na ndihmoi shumë kursi i programimit funksional që kaluam në universitet.

Si për pjesëmarrësit e zakonshëm, ashtu edhe për autorët e projekteve, regjistrimi në përcaktimin është falas. Ne dorëzuam aplikimet tona për pjesëmarrje në fillimin e qershorit, pas së cilës u transferuam mjaft shpejt nga lista e pritjes në atë të pjesëmarrësve të konfirmuar.

Tani do të flasim për projektet ku morëm pjesë në zhvillim.

Pandoc

Pandoc është një konvertues universali i dokumenteve tekstuale, në fakt - nga çdo format në çdo format. Për shembull, nga docx në pdf, ose nga Markdown në MediaWiki. Autori i tij, John MacFarlane - profesor filozofie në Universitetin e Kalifornisë në Berkeley. Në përgjithësi, Pandoc është mjaft i njohur, dhe disa nga njohuritë tona u habitën kur mësuan se Pandoc është shkruar në Haskell.

ZuriHac: praktikojmë programimin funksional

Lista e formateve të dokumenteve të mbështetura nga Pandoc. Në faqen e internetit ka gjithashtu një grafik të plotë, por kjo imazh nuk është e përshtatshme për artikullin.

Sigurisht, në Pandoc nuk është realizuar një konvertim i drejtpërdrejtë për çdo çift formatesh. Për të mbështetur një gamë kaq të gjerë shndërrimesh, përdoret një zgjidhje arkitekturore standarde: së pari, i gjithë dokumenti përkthehet në një përfaqësim të brendshëm të veçantë dhe pastaj, mbi këtë përfaqësim të brendshëm, krijohet dokumenti në një format tjetër. Përfaqësimi i brendshëm zhvilluesit e quajnë "AST", që shkurtimisht qëndron për Abstract Syntax Tree, ose përfaqësimi sintaksor abstrakt. Të shikoni përfaqësimin e brendshëm është shumë e thjeshtë: duhet vetëm të caktoni formatin e daljes "native"

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

$ pandoc -f html -t native example.html
[Header 1 ("hello-world",[],[]) [Str "Përshëndetje,",Space,Str "Botë!"]]

Lexuesit që kanë punuar paksa me Haskell-in, tashmë mund të supozojnë nga ky shembull i vogël se Pandoc është shkruar saktësisht në Haskell: rezultati i kësaj komande është përfaqësimi i strukturave të brendshme të Pandoc në formën e një stringu, krijuar mbi modelin e asaj që zakonisht bëhet 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, ku nĂ« çdo nyjĂ« tĂ« brendshme ka njĂ« listĂ«. PĂ«r shembull, nĂ« nivelin mĂ« tĂ« lartĂ« ndodhet njĂ« listĂ« me njĂ« element - njĂ« titull i nivelit tĂ« parĂ« me atributet “hello-world”,[],[]. Brenda kĂ«tij titulli Ă«shtĂ« fshehur njĂ« listĂ« e stringut “Hello,”, njĂ« hapĂ«sirĂ« dhe stringu “World!”.

Siç duket, përfaqësimi i brendshëm nuk ndryshon shumë nga HTML. Ai përfaqëson një pemë, ku çdo nyjë e brendshme informon për ndonjë informacion lidhur me formatimin e pasardhësve të saj, ndërsa në gjethet ndodhet në të vërtetë përmbajtja e dokumentit.

Nëse zbresim në nivelin e realizimit konkret, tipi i të dhënave për të gjithë dokumentin është përcaktuar kështu:

data Pandoc = Pandoc Meta [Block]

Këtu Block është pikërisht çdo njësi e brendshme, për të cilat është folur më lart, dhe Meta është metainformacioni për dokumentin, siç janë titulli, data e krijimit, autorët - për formate të ndryshme kjo është e ndryshme, dhe Pandoc përpiqet të ruajë këtë informacion sa më shumë të jetë e mundur gjatë përkthimit nga një format në tjetrin.

Gati tĂ« gjithĂ« konstruktorĂ«t e tipit Block — pĂ«r shembull, Header ose Para (paragrafi) — pranojnĂ« si argumente atributet dhe njĂ« listĂ« skajsh tĂ« nivelit mĂ« tĂ« ulĂ«t — Inline, nĂ« pĂ«rgjithĂ«si. PĂ«r shembull, Space ose Str janĂ« konstruktorĂ« tĂ« tipit Inline, poashtu HTML-tĂ«, si , shndĂ«rrohen nĂ« Inline tĂ« veçantĂ«. Nuk shohim kuptimin e ndihmĂ«s pĂ«r shpjegimin e plotĂ« tĂ« kĂ«tyre tipave, por do tĂ« nĂ«nvizojmĂ« se mund tĂ« shikohet kĂ«tu kĂ«tu.

ËshtĂ« interesante qĂ« tipi Pandoc Ă«shtĂ« njĂ« monoid. Kjo do tĂ« thotĂ« se ekziston njĂ« dokument i zbrazĂ«t dhe se dokumentet mund tĂ« shtohen me njĂ«ri-tjetrin. Kjo Ă«shtĂ« e dobishme nĂ« shkrimin e Reader’ave — mund tĂ« ndajmĂ« dokumentin nĂ« pjesĂ« me logjikĂ« tĂ« rastit, tĂ« analizojmĂ« çdo pjesĂ« veçmas dhe pastaj ta mbledhim gjithçka sĂ« bashku nĂ« njĂ« dokument. NĂ« kĂ«tĂ« proces, metainformacioni do tĂ« grumbullohet nga tĂ« gjitha pjesĂ«t e dokumentit menjĂ«herĂ«.

Kur konvertojmĂ«, pĂ«r shembull, nga LaTeX nĂ« HTML, sĂ« pari njĂ« modul i veçantĂ«, i quajtur LaTeXReader, e transformon dokumentin hyrĂ«s nĂ« AST, pastaj njĂ« modul tjetĂ«r, i quajtur HTMLWriter, e transformon AST nĂ« HTML. FalĂ« kĂ«saj arkitekture, nuk Ă«shtĂ« e nevojshme tĂ« shkruhet njĂ« numĂ«r katror konvertimesh — Ă«shtĂ« mjaft tĂ« shkruash pĂ«r çdo format tĂ« ri njĂ« Reader dhe njĂ« Writer, dhe tĂ« gjitha çiftet e mundshme tĂ« konvertimeve do tĂ« mbĂ«shteten automatikisht.

E qartĂ«, qĂ« njĂ« arkitekturĂ« e tillĂ« ka edhe disavantazhet e saj, tĂ« cilat janĂ« parashikuar prej kohĂ«sh nga specialistĂ«t nĂ« fushĂ«n e arkitekturĂ«s sĂ« softuerit. Disavantazhi mĂ« i rĂ«ndĂ«sishĂ«m Ă«shtĂ« kostoja e ndryshimeve nĂ« pemĂ«n sintaksore. NĂ«se ndryshimi Ă«shtĂ« mjaft serioz, do tĂ« nevojitet tĂ« modifikohet kodi nĂ« tĂ« gjitha Reader’ate dhe Writer’ate. PĂ«r shembull, njĂ« nga sfidat qĂ« pĂ«rballen zhvilluesit e Pandoc Ă«shtĂ« mbĂ«shtetje pĂ«r formate komplekse tabelash. Tani Pandoc mbĂ«shtet vetĂ«m tabelat mĂ« tĂ« thjeshta, me tituj, kolona dhe vlera nĂ« çdo qelizĂ«. PĂ«r shembull, atributi colspan nĂ« HTML do tĂ« injorohet. NjĂ« nga arsyet pĂ«r kĂ«tĂ« sjellje Ă«shtĂ« mungesa e njĂ« skeme tĂ« vetme tĂ« paraqitjes sĂ« tabelave nĂ« tĂ« gjithĂ« ose tĂ« paktĂ«n shumĂ« formate — pĂ«r rrjedhojĂ«, nuk Ă«shtĂ« e qartĂ« se si duhet tĂ« ruhen tabelat nĂ« pĂ«rfaqĂ«simin e brendshĂ«m. Por edhe pas zgjedhjes sĂ« njĂ« pĂ«rfaqĂ«simi konkret, do tĂ« duhet tĂ« ndryshohen tĂ« gjithĂ« Reader’ate dhe Writer’ate qĂ« mbĂ«shtesin punĂ«n me tabelat.

Gjuha Haskell u zgjodh jo vetĂ«m pĂ«r dashurinĂ« e madhe tĂ« autorĂ«ve ndaj programimit funksional. Haskell njihet pĂ«r mundĂ«sitĂ« e tij tĂ« gjera nĂ« pĂ«rpunimin e teksteve. NjĂ« nga shembujt Ă«shtĂ« biblioteka parsec — njĂ« bibliotekĂ« qĂ« pĂ«rdor aktivisht konceptet e programimit funksional — monoidet, monadat, aplikatorĂ«t dhe funksionalet alternative — pĂ«r tĂ« shkruar parserĂ« tĂ« rastĂ«sishĂ«m. TĂ« gjithĂ« fuqinĂ« e Parsec mund ta shihni nĂ« shembullin HaskellWiki, ku analizohet parser-i i plotĂ« i njĂ« gjuhe programimi imperativ tĂ« thjeshtĂ«. Sigurisht, Parsec pĂ«rdoret gjithashtu nĂ« Pandoc.

Nëse e përshkruajmë shkurtimisht, monadat përdoren për parsingun e radhitur, kur fillimisht vjen një gjë dhe pastaj tjetër. Për shembull, në këtë shembull:

whileParser :: Parser Stmt
whileParser = whiteSpace >> statement

Fillimisht duhet të lexoni hapësirën e bardhë, dhe pastaj statement - që gjithashtu ka tipin Parser Stmt.

Funksionalet alternative përdoren për të rikthyer në rast se parsingu dështon. Për shembull,

statement :: Parser Stmt
statement = parens statement  sequenceOfStmt

Kjo do të thotë se duhet të provoni të lexoni statement në brenda kllapave, ose të provoni në mënyrë sekondare të lexoni disa statement-e.

Aplikatorët përdoren kryesisht si rrugë të shkurtra për monadat. Për shembull, le të themi se funksioni tok lexon ndonjë token (kjo është një funksion real nga LaTeXReader). Le të shohim një kombinim të tillë

const <$ tok  tok

Ajo do të lexojë dy tokene radhazi dhe do të kthejë të parin nga ato.

Për të gjithë këto klasa në Haskell ekzistojnë operatorë simbolikë të bukur, që e bëjnë programimin e Reader-ave të ngjashëm me artin ASCII. Thjesht shikoni këtë kod të mahnitshëm.

Detyrat tona ishin të lidhura me LaTeXReader-in. Detyra e Vasili ishte mbështetja e komandave mbox dhe hbox, të dobishme kur shkruhen paketa në LaTeX. Përgjegjësia e Elizabetës ishte mbështetje e komandës epigraph, që lejon të dizajnoni epigrafët në dokumentet LaTeX.

Hatrace

Në sistemet operative të ngjashme me UNIX, shpesh është e implementuar thirrja sistemike ptrace. Ajo është e dobishme për debugimin dhe simulimin e ambienteve të programeve, duke lejuar të ndjekësh thirrjet sistemike që bën programi. Për shembull, një utilitar shumë i dobishëm strace përdor pikërisht ptrace brenda vetes.

Hatrace është një bibliotekë që ofron një ndërfaqe për ptrace në Haskell. Problemi është se vetë ptrace është shumë i komplikuar dhe ta përdorësh atë direkt është mjaft e vështirë, veçanërisht nga gjuhët funksionale.

Hatrace, kur ekzekutohet, funksionon si strace dhe pranon argumente të ngjashme. Dallimi i tij nga strace është se ai është gjithashtu një bibliotekë që ofron një ndërfaqe më të thjeshtë se vetëm ptrace.

Me ndihmĂ«n e hatrace kemi kapur njĂ« bug tĂ« pakĂ«ndshĂ«m nĂ« kompilatorin Haskell GHC – duke u vrarĂ« nĂ« njĂ« moment tĂ« papĂ«rshtatshĂ«m, ai gjeneron skedarĂ« objektesh tĂ« paqĂ«ndrueshĂ«m dhe nuk i rikompilon ata kur rindez. Skriptimi i thirrjeve tĂ« sistemit lejon qĂ« tĂ« riprodhohet me garanci gabimi me njĂ« herĂ« ekzekutim, kur vrasjet rastĂ«sore e riprodhonin gabimin pĂ«r rreth dy orĂ«.

Ne shtuam në bibliotekë ndërfaqet e thirrjeve të sistemit - Elizabeta shtoi brk, ndërsa Vasili shtoi mmap. Si rezultat i punës sonë mund të përdoren më thjesht dhe saktë argumentet e këtyre thirrjeve të sistemit gjatë përdorimit të bibliotekës.

Burimi: habr.com

Blini hosting tĂ« besueshĂ«m pĂ«r faqe interneti me mbrojtje nga DDoS, serverĂ« VPS VDS đŸ”„ Blini hosting tĂ« besueshĂ«m pĂ«r faqe interneti me mbrojtje nga DDoS, serverĂ« VPS VDS | ProHoster