Fylla en funktion

När jag för några år sedan letade efter ett verktyg för att enkelt generera HTML med automatiska källförteckningar stötte jag på Pandoc, som jag använt flitigt sedan dess, bl.a. för denna blogg, och som jag diskuterade i min uppsats i arkivvetenskap om hållbara filformat, som jag skrev om här den 2 juni. Genom detta fick jag höra talas om Haskell, det språk i vilket Pandoc är utvecklat. Det är ett språk som skiljer sig ganska markant från de flesta väletablerade programmeringsspråk genom att det är rent funktionellt. De funktioner som finns i vanliga programmeringsspråk kan ha s.k. sidoeffekter som inte är kopplade till deras returvärde: de modifierar variabler, läser och skriver filer och skriver till skärmen. Detta gör funktionernas beteende svårförutsägbart och skiljer dem från funktioner i matematisk mening, som alltid ger bestämda utdata för en viss uppsättning indata. Haskell eliminerar sådana sidoeffekter: vill jag komma åt filsystemet eller ta emot data från användaren (annars blir det svårt att konstruera några användbara program) får jag definiera en funktion som returnerar en s.k. I/O-handling.

Språket är uppkallat efter logikern Haskell Curry (1900–1982), och har en specifik koppling till honom. Han bidrog till utvecklingen av currying, en teknik som innebär att en funktion med flera argument omvandlas till en kedja av enställiga funktioner: har vi t.ex. en tvåställig funktion \(x-y\), kan vi för \(x=2\) definiera en ny enställig funktion \(2-y\). Currying är centralt i Haskell eftersom alla funktioner är enställiga.

För ett par månader sedan uppmärksammades i Wired att Facebook numera använder Haskell för att utveckla sitt antispamsystem (Metz 2015). Olika fördelar med språket när det gäller sådana tillämpningar diskuteras, men programmeraren Mathias Biilmann liknar det vid ett språk från en alternativ framtid som aldrig kommer att infalla och säger att det är så annorlunda jämfört med etablerade språk att det inte finns en chans att det kommer att bli vanligt.

Jag undrar om inte barriären när det gäller ökad användning av Haskell handlar mycket om bristen på färdiga väldokumenterade bibliotek. Det är t.ex. en tilltalande tanke att använda funktionella språk för analys och visualisering av data (vanliga kalkylblad är, som påpekas av HaskellWiki (2015), bara en specialiserad form av funktionell programmering), men om det inte finns verktyg för att hantera datatabeller och generera diagram utifrån dessa kräver det mycket arbete från grunden, och det är nog få som är motiverade att göra detta när de har tillgång till språk som Python (med Pandas), R och Julia.

Situationen har dock förbättrats de senaste åren. Nu i somras laddades t.ex. paketet Frames upp till Haskells stora paketförråd Hackage (Cowley 2015a). Detta paket kan användas för att läsa in CSV-filer (eller textfiler separerade med andra tecken) i en tabellstruktur, och paketet har ett överskådligt tutorial (Cowley 2015b). Jag provade att göra ett enkelt program för att generera diagram utifrån Socialstyrelsens matriser över incidens i cancer i Sverige, som jag skrivit om i de senaste inläggen, och det finns tillgängligt via GitHub. Om programmet kompileras och textfilen IncWebR2011.txt finns tillgänglig kan nedanstående diagram över utvecklingen av incidensen (åldersstandardiserad till 2000 års svenska befolkning) i akut myeloisk leukemi (ICD 2050) i Sverige 1960–2011 sparas till aml.svg genom att ./secanc 2050 1960 2011 bef2000 aml.svg anges i en terminal. Själva diagrammen genereras med hjälp av paketet Chart (Docker 2014).

Incidens akut myeloisk leukemi Sverige 1960--2011 Diagrammet visar åldersstandardiserad incidens i akut myeloisk leukemi i Sverige 1960–2011. Rådata tillgängliga via Socialstyrelsen (2015).

Haskells krav på typsäkerhet gör att datatabeller är litet mer komplicerade att hantera än i språk som Python, vilket kan vara en bidragande orsak till att utvecklingen av verktyg som Frames hållits tillbaka. Frames använder sig av s.k. Template Haskell för att med hjälp av källfilen för en tabell baka in kod som definierar tabellstrukturen i programmet vid kompileringen. När jag försökte göra det med hela IncWebR2011.txt identifierades inte alla kolumntyper korrekt: vissa kolumner med flyttal kom t.ex. att definieras som booleska värden, vilket fick till följd att kanske 95 procent av raderna ignorerades. Jag löste det genom att klippa ut de tre första raderna i filen och använda dem för att läsa in strukturen.

Sedan är det inte riktigt praktiskt att ha 24 olika typer för de olika incidenskolumnerna; det vore mer hanterligt att ha tabellen i ”långt” format, med en incidenskolumn och sedan en textkolumn för att ange åldersgrupp eller standardbefolkning. Det finns en funktion melt för att ”smälta” tabeller och göra just detta (liknande funktioner finns tillgängliga för de ovannämnda etablerade språken). Dessvärre äter funktionen upp minnet i datorn när jag försöker använda den på den aktuella tabellen; vet inte om jag gör något dumt eller om det är en bugg (eller kanske båda delarna).

Referenser

Cowley, Anthony. 2015a. ”Frames”. https://hackage.haskell.org/package/Frames.

———. 2015b. ”Frames tutorial”. http://acowley.github.io/Frames/.

Docker, Tim. 2014. ”Chart”. https://hackage.haskell.org/package/Chart.

HaskellWiki. 2015. ”Introduction”. https://wiki.haskell.org/Introduction.

Metz, Cade. 2015. ”Facebook’s new spam-killer hints at the future of coding”. Wired (1 september). http://www.wired.com/2015/09/facebooks-new-anti-spam-system-hints-future-coding/.

Socialstyrelsen. 2015. ”Cancerstatistik”. http://www.socialstyrelsen.se/statistik/statistikefteramne/cancer.

Kommentera

E-postadressen publiceras inte. Obligatoriska fält är märkta *