Haskell (programmeertaal)
Haskell | ||||
---|---|---|---|---|
![]() | ||||
Paradigma | puur functioneel | |||
Verschenen | 1990 | |||
Ontwikkeld door | Simon Peyton Jones, Paul Hudak, Philip Wadler en anderen | |||
Huidige versie | Haskell 2010 (juli 2010) | |||
Typesysteem | statisch, sterk, inferred | |||
Implementaties | GHC, Hugs en anderen | |||
Dialecten | Helium, Gofer | |||
Beïnvloed door | Lisp, APL, Hope, Miranda, ML, Id | |||
Invloed op | C#, Curry, F#, LINQ, Perl 6, Python, Scala | |||
Besturingssysteem | Multiplatform | |||
Bestandsextensies | .hs, .lhs | |||
Website | https://haskell.org/ | |||
|
Haskell is een functionele programmeertaal vernoemd naar de wiskundige Haskell Brooks Curry.
Geschiedenis
Aan Haskell wordt voornamelijk gewerkt aan de Universiteit van Glasgow.
Begin
Door het verschijnen van de programmeertaal Miranda in 1985 (uitgebracht door Research Software Ltd.) steeg de interesse in luie functionele talen. Tegen 1987 waren er al een heleboel functionele talen in gebruik. Miranda was de meest verspreide taal, maar was propriëtaire software. Op de Internationale Conferentie over Functionele Talen in 1987 te Portland heerste consensus dat een open standaard voor dergelijke talen opgesteld moest worden. Het doel van de commissie was bestaande functionele consolideren tot een gemeenschappelijke taal die moest dienen als basis voor verder onderzoek naar functionele talen.[1]
Haskell 1.0 tot 1.4
De eerste versie van Haskell, Haskell 1.0, is opgesteld in 1990. Het werk van de commissie resulteerde in reeks taaldefinities (1.0, 1.1, 1.2, 1.3 en 1.4).[2]
Haskell 98
Eind 1997 resulteerde de reeks definities in Haskell 98, met als doel een stabiele, minimale, draagbare versie van de taal en bijhorende standaard te publiceren. De commissie verwachtte en maakte het expliciet mogelijk om extensies toe te voegen aan de taal via experimentele functies.[1]
In februari 1999 werd de standaard voor Haskell 98 gepubliceerd als The Haskell 98 Report. In januari 2003 werd een herziene editie gepubliceerd als Haskell 98 Language and Libraries: The Revised Report.[1] De taal blijft zich sterk ontwikkelen. De Glasgow Haskell Compiler is de facto de standaardimplementatie.[3]
Haskell 2010
Begin 2006 werden de eerste stappen gezet om een opvolger voor Haskell 98 te maken, onder de naam Haskell Prime.[4] Het doel was incrementele updates te produceren, met hoogstens één nieuwe versie per jaar. De eerste revisie, Haskell 2010, is aangekondigd in november 2009 en gepubliceerd in juli 2010.[5]
Haskell 2010 is een incrementele update, die verschillende vaak gebruikte en niet-controversiële functies toevoegt, die voorheen via compilervlaggen aangezet moesten worden:
- Hiërarchische modulenamen., bv.
Data.List
in plaats vanList
. Deze functionaliteit is oorspronkelijk toegevoegd aan Haskell 98 middels een addendum en wordt universeel gebruikt. - Met de foreign function interface is het mogelijk om andere programmeertalen aan te spreken. In de standaard zijn enkel bindingen naar C gedefinieerd, maar het ontwerp laat andere talen toe. Ook deze functie was oorspronkelijk een addendum bij Haskell 98.
- De zogenaamde -patronen zijn niet meer toegelaten.
- De regels omtrent de type-inferentie zijn versoepeld teneinde meer mogelijkheden te geven aan programma's.
- Enkele syntaxisproblemen zijn verholpen.
- De pragma
LANGUAGE
is toegevoegd om beter met extensies te kunnen werken.
Implementaties
Parallel aan de ontwikkeling van de theoretische Haskell-taal is er een aantal werkomgevingen voor Haskell ontwikkeld. De bekendste hiervan zijn de Hugs- en Gofer-systemen en de Glasgow Haskell Compiler, die alle gratis beschikbaar worden gesteld door de universitaire teams die eraan werken. Speciaal voor het leren van Haskell heeft men aan de Universiteit van Utrecht Helium ontwikkeld waarbij men aandacht heeft besteed aan de duidelijkheid van de foutmeldingen.
In Nijmegen is de programmeertaal Clean ontwikkeld, die zeer sterk op Haskell lijkt, maar de programmeur meer controle over de luie evaluatie geeft.
Functionele basis
In tegenstelling tot vele bekende programmeertalen zoals C, C++ en Java is Haskell geen imperatieve taal, maar een functionele taal. Dat wil zeggen dat de taal niet gebaseerd is op het turingmachine-model van berekening, maar op het Lambdacalculusmodel van Alonzo Church waarin het toepassen van functies op termen en termenreductie de basis is van berekening.
Haskell is een luie ("lazy"), puur functionele taal. Puur functioneel zijn wil zeggen dat erin gedefinieerde functies geen neveneffecten kunnen vertonen. Voorbeelden van niet-pure functionele programmeertalen zijn Standaard ML en Scheme. Een luie functionele taal gebruikt luie evaluatie om te voorkomen dat resultaten die niet gebruikt worden, berekend worden. Hoewel het niet door iedereen als een intuïtieve eigenschap wordt aangezien, wordt luie evaluatie beschouwd als een manier om meer modularisatie te kunnen realiseren.
De programmeertaal is sterk en statisch getypeerd (typefouten kunnen tijdens de uitvoering van een programma niet optreden), en steunt sterk op type-inferentie (meestal kunnen de types van functies en variabelen door de compiler ontdekt worden). Het typesysteem is zeer uitgebreid, en ondersteunt het concept van klassen van types, waarbij deze klassen van elkaar afgeleid kunnen worden.
Voorbeelden
Hello world
module Main (main) where -- niet nodig bij interpreter, standaard bij modulebestanden main :: IO () -- optioneel, de compiler kan dit bepalen main = putStrLn "Hello, World!"
Faculteit
De onderstaande functie berekent de faculteit van een getal. De functie is voor negatieve waarden ongedefinieerd. Ze is gedefinieerd op enkele verschillende manieren:
-- Type-annotatie (optioneel, zelfde voor elke implementatie) faculteit :: (Integral a) => a -> a -- Middels recursie (met de "ifthenelse"-expressie) faculteit n = if n < 2 then 1 else n * faculteit (n - 1) -- Met recursie (met patroonvergelijking) faculteit 0 = 1 faculteit n = n * faculteit (n - 1) -- Met recursie (met guards) faculteit n | n < 2 = 1 | otherwise = n * faculteit (n - 1) -- Met een lijst en de "product"-functie faculteit n = product [1..n] -- Met fold (implementeert "product") faculteit n = foldl (*) 1 [1..n] -- In "point-free"-stijl faculteit = foldr (*) 1 . enumFromTo 1
Invoegen in een lijst
De volgende functie voegt een getal in een lijst in, op volgorde van klein naar groot:
insert :: Int -> [Int] -> [Int] insert a [] = [a] insert a list@(x:xs) | a <= x = a : list | a > x = x : insert a xs
Bij het invoegen van een getal zijn er twee gevallen te onderscheiden: het invoegen van een getal in een lege lijst en in een lijst met één of meerdere getallen. Het invoegen in de lege lijst is eenvoudig want dat is een lijst met dat getal. Bij het invoegen van een getal in een gevulde lijst kijken we naar het eerste getal, x, en de rest, xs. Als het in te voegen getal kleiner of gelijk is aan het eerste getal, dan zetten we het getal op kop van de hele lijst. Als het getal groter is dan het eerste getal dan nemen we het eerste element en voegen we het getal in de rest van de lijst in. Op deze manier wordt de lijst doorlopen totdat de plek is gevonden waar het getal neergezet kan worden.
Hogere-ordefuncties en luie evaluatie
In Haskell kan men hogere-ordefuncties gebruiken, dit zijn functies die een of meerdere functie(s) als argument meekrijgen of die een functie opleveren. Voorbeelden hiervan zijn map
, filter
en fold
. De functie filter
krijgt bijvoorbeeld een functie mee (een predicaat) en een lijst. Deze functie levert een lijst op waarin alleen de elementen zitten uit de gegeven lijst die aan het predicaat voldoen. Bijvoorbeeld:
filter even [0..]
Het bovenstaande levert een oneindige lijst op met even getallen (formeler: alle elementen uit de lijst [0, 1, 2, ..] waarvoor de functie even
de waarde True
teruggeeft). Het feit dat deze lijst oneindig is, is geen probleem, want de lijst hoeft, vanwege het feit dat Haskell luie evaluatie toepast, alleen maar opgebouwd te worden indien nodig. Zo kan men schrijven:
take 10 (filter isPriem [1..])
De functie take
levert de eerste n elementen van een lijst op. Als men de functie isPriem
heeft gedefinieerd (die voor een getal bepaalt of het een priemgetal is) dan levert het bovenstaande de eerste 10 priemgetallen op.
Gebruik
Een greep uit de applicaties die geschreven zijn in of gebruik maken van Haskell:
- Darcs, een versiebeheersysteem, is geschreven in Haskell.[6]
- Xmonad is een windowmanager voor het X Window System, geschreven in Haskell.[7]
- git-annex is een hulpmiddel voor git om met grote bestanden te werken.[8]
- Pandoc, een programma om documenten te converteren tussen verschillende formaten.[9]
- Facebook gebruikt Haskell in zijn anti-spamprogramma's.[10]
Kritiek
In 2002 en 2003 bespraken respectievelijk Jan-Willem Maessen en Simon Peyton Jones problemen geassocieerd met luie evaluatie. Naast de praktische overwegingen, zoals betere performantie, maakte luie evaluatie het moeilijker voor programmeurs om over de code te redeneren.[11][12]
Anderen observeerden dat Haskell niet eenvoudig is om te leren voor beginners:[13]
The subtle syntax and sophisticated type system of Haskell are a double edged sword – highly appreciated by experienced programmers but also a source of frustration among beginners, since the generality of Haskell often leads to cryptic error messages.
Dit was ook een van de redenen om Helium te maken.
Gerelateerde talen
Clean is een nauw verwante, maar iets oudere taal van Haskell.
Een reeks talen die geïnspireerd zijn door Haskell, maar met verschillend typesysteem, zijn o.a.:
- Agda, een functionele taal met dependent types.
- Idris, een generieke functionele taal, ontwikkeld aan de universiteit van St Andrews.
- Epigram, een functionele taal, gebruikt voor het bewijzen van eigenschappen van programma's.
- Cayenne, een functionele taal met dependent types.
- Ωmega, een interpreter gelijkaardig aan Hugs.
- Elm, een functionele taal, bedoeld om webapplicaties mee te maken.
Verder lezen
- (nl) Functional Programming (pdf). Dit is het collegedictaat van het vak Functioneel Programmeren aan de Universiteit Utrecht (zie Bachelor Course on Functional Programming voor meer informatie).
Externe links
- (en) De Haskell pagina
- (en) Het Haskell 2010 Language Report - Over de taal zelf en haar bibliotheken
- (en) A History of Haskell: being lazy with class - Geschiedenis van Haskell
- (en) De FAQ van Usenet nieuwsgroep comp.lang.functional
- (en) Why Functional Programming Matters - Een paper door John Hughes die o.a. de voordelen van lazy evaluatie beschrijft.
- ↑ a b c (en) Jones, Simon Peyton (december 2002). Haskell 98 Language and Libraries. Cambridge University Press, "Preface". ISBN 9780521826143. Gearchiveerd op 6 juni 2023.
- ↑ (en) Hudak, Paul, Hughes, John; Jones, Simon Peyton; Wadler, Philip (16 april 2007). A History of Haskell: Being Lazy With Class. Proceedings of the Third ACM SIGPLAN Conference on History of Programming Languages (HOPL III): 12–1–55. DOI: 10.1145/1238844.1238856.
- ↑ (en) Implementations - HaskellWiki (17 februari 2017). Gearchiveerd op 2 juni 2019. Geraadpleegd op 4 augustus 2019.
- ↑ (en) Haskell Prime (29 april 2016). Gearchiveerd op 20 februari 2016. Geraadpleegd op 4 augustus 2019.
- ↑ (en) Marlow, Simon, Announcing Haskell 2010 (24 november 2009). Gearchiveerd op 12 april 2019. Geraadpleegd op 4 augustus 2019.
- ↑ (en) Darcs - FrontPage. Geraadpleegd op 4 augustus 2019.
- ↑ (en) xmonad | the tiling window manager that rocks. Gearchiveerd op 2 september 2019. Geraadpleegd op 4 augustus 2019.
- ↑ (en) git-annex (29 december 2017). Geraadpleegd op 4 augustus 2019.
- ↑ (en) MacFarlane, John, Pandoc (12 juni 2019). Gearchiveerd op 21 september 2019. Geraadpleegd op 4 augustus 2019.
- ↑ (en) Metz, Cade, Facebook's New Spam-Killer Hints at the Future of Coding. Wired (1 september 2019). Gearchiveerd op 16 juli 2019. Geraadpleegd op 4 augustus 2019.
- ↑ (en) Maessen, Jan-Willem (2002). Eager Haskell: Resource-bounded Execution Yields Efficient Iteration. Proceedings of the 2002 ACM SIGPLAN Workshop on Haskell: 38-50 (Association for Computing Machinery). DOI: 10.1145/581690.581694.
- ↑ (en) Jones, Simon Peyton, Wearing the hair shirt: a retrospective on Haskell. Microsoft Research (januari 2003). Gearchiveerd op 4 augustus 2019. Geraadpleegd op 4 augustus 2019.
- ↑ Heeren, Bastiaan, Leijen, Daan; IJzendoorn, Arjan van (augustus 2003). Helium, for Learning Haskell. Proceedings of the 2003 ACM SIGPLAN Workshop on Haskell: 62-71 (Association for Computing Machinery). DOI: 10.1145/871895.871902. Gearchiveerd van origineel op 22 januari 2022.