ZuriHac: øver på funksjonell programmering

I juni i år, i den lille sveitsiske byen Rapperswil, en begivenhet kalt ZuriHac. Denne gangen samlet det mer enn fem hundre Haskell-elskere, fra nybegynnere til språkets grunnleggere. Selv om arrangørene kaller dette arrangementet et hackathon, er det ikke en konferanse eller et hackathon i klassisk forstand. Formatet er forskjellig fra tradisjonelle programmerere. Vi lærte om ZuriHac ved hell, deltok i det, og nå anser vi det som vår plikt å fortelle om det uvanlige funnet!

ZuriHac: øver på funksjonell programmering

om oss

Denne artikkelen ble utarbeidet av to tredjeårsstudenter på programmet "Anvendt matematikk og informatikk" ved National Research University Higher School of Economics - St. Petersburg: Vasily Alferov og Elizaveta Vasilenko. Lidenskapen for funksjonell programmering for oss begge begynte med en serie forelesninger av D. N. Moskvin på 3. året på universitetet. Vasily deltar for tiden i Google Summer of Code-programmet, der han implementerer algebraiske grafer i Haskell under veiledning av prosjektteamet alge. Elizaveta brukte de ervervede funksjonelle programmeringsferdighetene i kursarbeid viet til implementeringen av anti-foreningsalgoritmen med påfølgende anvendelse i typeteori.

Eventformat

Målgruppen er eiere av åpen kildekode-prosjekter, programmerere som ønsker å delta i deres utvikling, funksjonelle programmeringsforskere og folk som rett og slett brenner for Haskell. I år har utviklere fra mer enn femti åpen kildekode Haskell-prosjekter fra hele verden samlet seg på stedet – HSR Hochschule für Technik Rapperswil – for å snakke om produktene deres og få ferske folk interessert i utviklingen deres.

ZuriHac: øver på funksjonell programmering

Bilde fra Twitter ZuriHac

Opplegget er veldig enkelt: du må skrive noen forslag om prosjektet ditt på forhånd og sende dem til arrangørene, som vil legge ut informasjon om prosjektet ditt på arrangementssiden. I tillegg har forfatterne av prosjektene den første dagen tretti sekunder på seg til veldig kort å fortelle fra scenen hva de gjør og hva som må gjøres. Så leter interesserte etter forfatterne og spør i detalj om oppgavene.

Vi har ikke egne åpne prosjekter ennå, men vi ønsker virkelig å bidra til eksisterende, så vi registrerte oss som faste deltakere. I løpet av tre dager jobbet vi med to grupper av utviklere. Det viser seg at felles studie av kode og live kommunikasjon gjør samspillet mellom prosjektforfattere og bidragsytere svært produktivt - på ZuriHac var vi i stand til å forstå områder som var nye for oss og var i stand til å hjelpe to helt forskjellige team, og fullførte en oppgave i hver av prosjektene.

I tillegg til verdifull praksis ble det også gitt flere forelesninger og masterklasser på ZuriHac. Vi husker spesielt to forelesninger. Ved den første av dem snakket Andrey Mokhov fra University of Newcastle om selektive applikative funksjoner – en klasse av typer som skulle bli mellomliggende mellom applikative funksjoner og monader. I et annet foredrag snakket en av grunnleggerne av Haskell, Simon Peyton Jones, om hvordan typeinferens fungerer i GHC-kompilatoren.

ZuriHac: øver på funksjonell programmering

Foredrag av Simon Peyton Jones. Bilde fra Twitter ZuriHac

Mesterklassene som ble holdt under hackathonet ble delt inn i tre kategorier avhengig av treningsnivået til deltakerne. Oppgavene som ble tilbudt deltakere som ble med i utviklingen av prosjekter var også merket med en vanskelighetsgrad. Det lille, men vennlige fellesskapet av funksjonelle programmerere ønsker gladelig nykommere velkommen i sine rekker. For å forstå forelesningene til Andrei Mokhov og Simon Peyton Jones var imidlertid kurset i funksjonell programmering vi tok på universitetet svært nyttig.

Påmelding til arrangementet er gratis for både vanlige deltakere og prosjektforfattere. Vi sendte inn søknader om deltakelse i begynnelsen av juni, deretter ble vi raskt overført fra venteliste til listen over bekreftede deltakere.

Og nå skal vi snakke om prosjektene i utviklingen som vi deltok i.

pandoc

pandoc er en universell omformer av tekstdokumenter, faktisk fra alle formater til alle. For eksempel fra docx til pdf, eller fra Markdown til MediaWiki. Forfatteren, John MacFarlane, er professor i filosofi ved University of California, Berkeley. Generelt er Pandoc ganske kjent, og noen av vennene våre ble overrasket da de fikk vite at Pandoc ble skrevet i Haskell.

ZuriHac: øver på funksjonell programmering

Liste over dokumentformater som støttes av Pandoc. Det er også en hel graf på siden, men dette bildet passer ikke inn i artikkelen.

Selvfølgelig gir ikke Pandoc direkte konvertering for hvert par formater. For å støtte et så bredt utvalg av transformasjoner, brukes en standard arkitektonisk løsning: først blir hele dokumentet oversatt til en spesiell intern mellomrepresentasjon, og deretter genereres et dokument i et annet format fra denne interne representasjonen. Utviklerne kaller den interne representasjonen "AST", som står for abstrakt syntakstre, eller abstrakt syntakstre. Du kan se på mellomrepresentasjonen veldig enkelt: alt du trenger å gjøre er å sette utdataformatet til "native"

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

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

Lesere som i det minste har jobbet litt med Haskell, kan allerede fra dette lille eksemplet anta at Pandoc er skrevet i Haskell: utdataene fra denne kommandoen er en strengrepresentasjon av de interne strukturene til Pandoc, skapt i likhet med hvordan det vanligvis gjøres. i Haskell, for eksempel i standardbiblioteket.

Så her kan du se at den interne representasjonen er en rekursiv struktur, i hver interne node som det er en liste over. For eksempel, på toppnivået er det en liste over ett element - overskriften på første nivå med attributtene "hello-world",[],[]. Skjult inne i denne overskriften er en liste over strengen "Hallo", etterfulgt av et mellomrom og strengen "Verden!".

Som du kan se, er den interne representasjonen ikke mye forskjellig fra HTML. Det er et tre der hver intern node gir litt informasjon om formateringen av dens etterkommere, og bladene inneholder det faktiske innholdet i dokumentet.

Går vi ned til implementeringsnivået, er datatypen for hele dokumentet definert slik:

data Pandoc = Pandoc Meta [Block]

Her er Block nettopp de interne toppunktene nevnt ovenfor, og Meta er metainformasjon om dokumentet, som tittel, opprettelsesdato, forfattere – dette er forskjellig for ulike formater, og Pandoc prøver om mulig å bevare slik informasjon når man oversetter fra format til format.

Nesten alle konstruktører av Block-typen - for eksempel Header eller Paragraph (avsnitt) - tar attributter og en liste over toppunkter på lavere nivå som argumenter - Inline, som regel. For eksempel er Space eller Str konstruktører av Inline-typen, og HTML-taggen blir også til sin egen spesielle Inline. Vi ser ingen vits i å gi en fullstendig definisjon av disse typene, men merk at den finnes her her.

Interessant nok er typen Pandoc en monoid. Dette betyr at det er et slags tomt dokument, og at dokumenter kan stables sammen. Dette er praktisk å bruke når du skriver lesere - du kan dele et dokument i deler ved å bruke vilkårlig logikk, analysere hver enkelt separat og deretter sette alt sammen til ett dokument. I dette tilfellet vil metainformasjon samles inn fra alle deler av dokumentet samtidig.

Når du konverterer for eksempel fra LaTeX til HTML, konverterer først en spesiell modul kalt LaTeXReader inndatadokumentet til AST, deretter konverterer en annen modul kalt HTMLWriter AST til HTML. Takket være denne arkitekturen er det ikke nødvendig å skrive et kvadratisk antall konverteringer - det er nok å skrive Reader og Writer for hvert nytt format, og alle mulige par med konverteringer støttes automatisk.

Det er klart at en slik arkitektur også har sine ulemper, lenge spådd av eksperter innen programvarearkitektur. Det viktigste er kostnadene ved å gjøre endringer i syntakstreet. Hvis endringen er alvorlig nok, må du endre koden i alle lesere og skribenter. For eksempel er en av utfordringene Pandoc-utviklere står overfor å støtte komplekse tabellformater. Nå kan Pandoc bare lage veldig enkle tabeller, med en overskrift, kolonner og en verdi i hver celle. For eksempel vil colspan-attributtet i HTML ganske enkelt bli ignorert. En av grunnene til denne oppførselen er mangelen på et enhetlig opplegg for å representere tabeller i alle eller i det minste mange formater - følgelig er det uklart i hvilken form tabellene skal lagres i den interne representasjonen. Men selv etter å ha valgt en bestemt visning, må du endre absolutt alle lesere og forfattere som støtter arbeid med tabeller.

Haskell-språket ble valgt ikke bare på grunn av forfatternes store kjærlighet til funksjonell programmering. Haskell er kjent for sine omfattende tekstbehandlingsmuligheter. Et eksempel er biblioteket parsec er et bibliotek som aktivt bruker begrepene funksjonell programmering - monoider, monader, applikative og alternative funksjoner - for å skrive vilkårlige parsere. Den fulle kraften til Parsec kan sees i eksempel fra HaskellWiki, der en komplett parser av et enkelt imperativt programmeringsspråk analyseres. Parsec brukes selvfølgelig også aktivt i Pandoc.

Kort beskrevet, monader brukes til sekvensiell parsing, når en ting kommer først, og deretter en annen. For eksempel, i dette eksemplet:

whileParser :: Parser Stmt
whileParser = whiteSpace >> statement

Først må du telle mellomrommet, og deretter setningen - som også har typen Parser Stmt.

Alternative funksjoner brukes til å rulle tilbake hvis parsing mislykkes. For eksempel,

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

Betyr at du enten må prøve å lese setningen i parentes, eller prøve å lese flere setninger sekvensielt.

Applikative funksjoner brukes først og fremst som snarveier for monader. La for eksempel tok-funksjonen lese noen token (dette er en ekte funksjon fra LaTeXReader). La oss se på denne kombinasjonen

const <$> tok <*> tok

Den vil lese to tokens på rad og returnere den første.

For alle disse timene har Haskell vakre symbolske operatorer, som får Reader-programmering til å se ut som ASCII-kunst. Bare beundre denne fantastiske koden.

Våre oppgaver var relatert til LaTeXReader. Vasilys oppgave var å støtte mbox- og hbox-kommandoene, nyttige for å skrive pakker i LaTeX. Elizabeth var ansvarlig for å støtte epigraf-kommandoen, som lar deg lage epigrafer i LaTeX-dokumenter.

Hatrace

UNIX-lignende operativsystemer implementerer ofte ptrace-systemkallet. Det er nyttig i feilsøking og simulering av programmiljøer, slik at du kan spore systemanropene som programmet gjør. For eksempel bruker det svært nyttige strace-verktøyet ptrace internt.

Hatrace er et bibliotek som gir et grensesnitt for ptrace i Haskell. Faktum er at ptrace i seg selv er veldig sofistikert og det er ganske vanskelig å bruke det direkte, spesielt fra funksjonelle språk.

Hatrace kjører som strace ved oppstart og aksepterer lignende argumenter. Det skiller seg fra strace ved at det også er et bibliotek som gir et enklere grensesnitt enn bare ptrace.

Ved hjelp av hatrace har vi allerede fanget en ubehagelig feil i GHC Haskell-kompilatoren - blir drept i feil øyeblikk, genererer den feil objektfiler og kompilerer dem ikke på nytt når den startes på nytt. Skripting ved systemkall gjorde det mulig å reprodusere feilen på en pålitelig måte i én kjøring, mens tilfeldige drep reproduserte feilen på omtrent to timer.

Vi la til systemanropsgrensesnitt til biblioteket - Elizaveta la til brk, og Vasily la til mmap. Basert på resultatene av arbeidet vårt er det mulig å enklere og mer nøyaktig bruke argumentene til disse systemanropene når du bruker biblioteket.

Kilde: www.habr.com

Legg til en kommentar