In welk jaar is haskell verschenen. 'En wie heeft het gemaakt?' Kenmerken van functionele talen

De syntaxis voor twee opeenvolgende identifiers betekent het toepassen van de functie foo op de argumentbalk:

In Haskell zijn voor het aanroepen van een functie geen haakjes rond het argument nodig.

Haakjes worden gebruikt om argumenten te groeperen:

acos (cos pi)

Meerdere argumentfunctie:

maximaal 5 42

De werking van het toepassen van een functie is links associatief:

(max. 5) 42

Functie max wordt achtereenvolgens toegepast op twee argumenten.
De compiler begrijpt de constructie f x y hoe (fx) ja, en niet omgekeerd f (xj).

Uitdrukking (maximaal 5) dit is de zogenaamde partiële functietoepassing. V algemeen beeld het kan als volgt worden geformuleerd: als we een functie van N variabelen hebben en we bekijken het als een functie van N variabelen, dan kunnen we het van de andere kant bekijken en zeggen dat het een functie is van één variabele die ons teruggeeft een functie van N - 1 variabelen.

3 + zonde 42

3 + (max. 5) 42

Syntaxis voor declaratie van aangepaste functies

Een functie die de kwadraten van de twee doorgegeven argumenten optelt:

SomVierkanten x y = x ^ 2 + y ^ 2 rock "n" roll = 42


De functienaam en formele parameternamen moeten beginnen met een kleine letter. En hoofdletters worden gebruikt om gegevenstypen te definiëren.

Een functie met drie argumenten die de lengte van een 3D-vector berekent:

LenVec3 x y z = sqrt (x ^ 2 + y ^ 2 + z ^ 2)


Om een ​​functie in de GHci-interpreter te definiëren, moeten we het sleutelwoord let gebruiken.

Laat somKwadraten x y = x ^ 2 + y ^ 2

Functie zuiverheid eigenschap:

Een belangrijk kenmerk dat functionele talen onderscheidt van imperatieve talen is de eigenschap van zuiverheid van functies. Alle functies in Haskell zijn puur. Dit betekent dat de waarde van de functie volledig wordt bepaald door de waarden van de argumenten die eraan worden doorgegeven. Geen enkele andere gegevensbron kan het resultaat dat door de functie wordt geretourneerd, beïnvloeden. Als je een functie nodig hebt om ergens data vandaan te halen, dan moet je deze databron er als argument aan doorgeven.

Een functie waarvoor geen argumenten nodig zijn, is een constante. Zo'n functie retourneert altijd dezelfde waarde, ongeacht de omstandigheden.

Prelude> laat veertigTwo = 39 + 3 Prelude> veertigTwo 42

In Haskell kun je geen functie definiëren die geen argumenten nodig heeft en verschillende waarden retourneert voor verschillende aanroepen.

Mechanisme voor het definiëren van functies met behulp van gedeeltelijke toepassing

We kunnen elke functie bekijken als een functie van één argument dat een functie retourneert.

Prelude> laat max5 x = max 5 x Prelude> max5 4 5 Prelude> max5 42 42


Alternatieve syntaxis voor het definiëren van een functie:

Prelude> laat max5 "= max 5 Prelude> max5" 4 5 Prelude> max5 "42 42

We hebben het extra argument x links en rechts ingekort. En ze schreven dat de functie max5 "slechts een gedeeltelijk toegepaste functie max is. Je kunt dus een functie definiëren zonder alle argumenten op te geven. De bijbehorende programmeerstijl wordt zinloos genoemd.

Vaak is het ontwerp van functies in Haskell zo afgestemd dat gedeeltelijke toepassing handig is;

Prelude> laat kortingslimiet proc sum = if sum> = limit then sum * (100 - proc) / 100 else sum Prelude> laat standaardKorting = korting 1000 5 Prelude> standaardKorting 2000 1900.0 Prelude> standaardKorting 900 900,0

De limiet- en proc-parameters worden zelden gewijzigd. De somparameter verandert echter regelmatig. In feite elke keer dat deze functie wordt aangeroepen.

Stel dat we in Haskell een interface voor een vertaalsysteem voor natuurlijke talen ontwikkelen. Het moet een vertaalfunctie bevatten met tekst, languageFrom en languageTo parameters. Om het gemakkelijk te maken om de volgende functies te implementeren:

  • vertalenVanSpaansNaarRussisch,
  • vertalenVanEngelsNaarRussisch
  • en vertalenNaarRussisch
u moet de parameters in de volgende volgorde rangschikken: vertaal taalNaar taalVan tekst.

Typ operator ->

Om het type van een functie te schrijven, moet je het type van zijn argument en het type van het resultaat van deze functie schrijven. In Haskell, om het type functie te beschrijven, is de operator -> een binaire operator waarin de linker operand het type argument is en de rechter operand het type resultaat. De pijl bevindt zich tussen de linker en rechter operand t, k, dit is een tussenvoegseloperator.

Prelude>: t niet niet :: Bool -> Bool Prelude> (&&) False True False Prelude> ((&&) False) True False

Het type van de laatste uitdrukking kan als volgt worden geschreven:
Bool -> (Bool -> Bool)
De type-operator wordt als rechts-associatief beschouwd. Daarom kan Bool -> (Bool -> Bool) worden herschreven als Bool -> Bool -> Bool

Prelude>: t (&&) (&&) :: Bool -> Bool -> Bool

Laten we de kortingsfunctie onthouden, die terugkwam totale hoeveelheid aankopen met eventuele korting. Als parameter werd het bedrag doorgegeven zonder de kortingssom, het percentage van de kortingsprocedure en de korting werd in rekening gebracht als het overgedragen bedrag de limietdrempel overschrijdt. Al deze parameters, evenals de retourwaarde, kunnen worden opgeslagen in het type Double. Het functietype kan samen met de definitie in het bronbestand worden gespecificeerd:

korting :: Dubbel -> Dubbel -> Dubbel -> Dubbele kortingslimiet proc sum = if sum> = limit then sum * (100 - proc) / 100 else sum

Merk op dat de typedeclaratie optioneel is, hoewel het vaak wordt aanbevolen voor documentatiedoeleinden. Het wordt meestal vóór de functiedefinitie geplaatst, hoewel deze verklaring top niveau kan zich overal in het bronbestand bevinden.

Standaardkorting :: Dubbel -> Dubbel standaardKorting = korting 1000 5

Beschouw de functie twoDigits2Int, die twee tekens nodig heeft en een getal retourneert dat uit die tekens bestaat als beide tekens numeriek zijn en 100 is anders... (Het eerste teken wordt behandeld als het aantal tientallen, het tweede als het aantal eenheden.)

Gegevens importeren.Char twoDigits2Int :: Char -> Char -> Int twoDigits2Int x y = if isDigit x && isDigit y then digitToInt x * 10 + digitToInt y else 100


GHCi> twoDigits2Int "4" "2" 42

Herhaling

In imperatieve talen is een lus het belangrijkste element van repetitieve berekeningen. In functionele talen zijn lussen niet erg zinvol. Omdat functionele talen het concept van een veranderlijke variabele missen, is er geen manier om de ene lus-iteratie van de andere te onderscheiden. Om repetitieve berekeningen in functionele talen uit te voeren, wordt recursie gebruikt. Om te voorkomen dat een recursieve functie in een lus gaat, moet deze aan de volgende vereisten voldoen:
  • functie-aanroepen aan de rechterkant moeten worden uitgevoerd op andere parameterwaarden dan formele parameter functies;
  • recursieve oproepen moeten ergens worden onderbroken (er moet een zogenaamde terminerende voorwaarde zijn).

faculteit

Faculteit n = als n == 0 dan 1 else n * faculteit (n - 1)


Implementatie van het berekenen van de faculteit met behulp van de accumulerende parameter:

Faculteit5 n | n> = 0 = helper 1 n | anders = fout "arg must be> = 0" helper acc 0 = acc helper acc n = helper (acc * n) (n - 1)

Een dergelijke implementatie in het geval van een faculteit brengt geen extra voordelen met zich mee, maar heel vaak kunnen dergelijke implementaties de efficiëntie van recursieve functies verbeteren. In veel gevallen kan men in recursieve functies, door een directe definitie van een recursieve functie in termen van zichzelf te geven, kwadratische of hogere polynomiale asymptotica verkrijgen. En in het geval van het gebruik van hulpfuncties, is het heel vaak mogelijk om de asymptotiek te corrigeren door deze te reduceren tot lineair.

dubbele faculteit

Beschouw een functie die een dubbele faculteit berekent, dat wil zeggen, het product van natuurlijke getallen die een bepaald getal niet overschrijden en dezelfde pariteit hebben. Bijvoorbeeld: 7 !! = 7⋅5⋅3⋅1, 8 !! = 8⋅6⋅4⋅2. Er wordt aangenomen dat het functieargument alleen niet-negatieve waarden kan aannemen.

DoubleFact :: Integer -> Integer doubleFact n = if n<= 0 then 1 else n * doubleFact (n - 2 )

Fibonacci-nummerreeks

In Haskell wordt deze definitie gegeven door de volgende functie:

Fibonacci :: Integer -> Integer fibonacci n | n == 0 = 0 | n == 1 = 1 | n> 1 = fibonacci (n - 1) + fibonacci (n - 2) | N< 0 = fibonacci (n + 2 ) - fibonacci (n + 1 ) | otherwise = undefined

De implementatie van een functie voor het berekenen van het Fibonacci-getal, gebaseerd op een directe recursieve definitie, is uiterst inefficiënt - het aantal functieaanroepen groeit exponentieel met een toename van de waarde van het argument. Met GHCi kunt u het geheugengebruik en de tijd die is besteed aan het evalueren van een uitdrukking volgen door het commando uit te voeren: set + s:

* Fibonacci>: set + s * Fibonacci> fibonacci 30 832040 (16,78 sec, 409, 318, 904 bytes)

Met behulp van het accumulatormechanisme kunt u een efficiëntere implementatie schrijven die lineaire complexiteit heeft (door het aantal recursieve aanroepen):

Fibonacci ":: Integer -> Integer fibonacci" n = helper n 0 1 helper n a b | n == 0 = een | n> 0 = helper (n - 1) b (a + b) | N< 0 = helper (n + 1 ) b (a - b) | otherwise = undefined


Functies van hogere orde

Een functie van hogere orde is een functie die een andere functie als argument heeft. Functies van hogere orde zijn zeldzaam in imperatieve talen. Een voorbeeld is de sorteerfunctie uit de C Standard Library. Als eerste argument wordt een binair vergelijkingspredikaat doorgegeven aan de sorteerfunctie met behulp waarvan een array als tweede argument wordt doorgegeven en gesorteerd. In functionele talen en in Haskell-functies hogere orden worden heel vaak gebruikt.

Prelude>: t ($) ($) :: (a -> b) -> a -> b

Het is een polymorf type. De dollar-operator is een functie van twee argumenten. De linker operand of eerste argument (a -> b) is een functie. De rechter operand a is een willekeurige waarde. De dollaroperator past eenvoudig zijn eerste argument (a -> b) toe op zijn tweede argument a. Daarom is het hier noodzakelijk dat de typen consistent zijn. Het type van het tweede argument aan de dollaroperator moet overeenkomen met het type parameter van de functie die in het eerste argument wordt doorgegeven. Bovendien is het resultaat van het uitvoeren van de dollar-operator het resultaat van de functie die als eerste argument is doorgegeven. Aangezien het type resultaat b is, is het resultaat van het dollarstatement type b.

Het volgende gebruik is alleen geldig als a en b hetzelfde zijn.

Prelude> laten toepassen2 fx = f (fx) Prelude>: t toepassen2 toepassen2 :: (t -> t) -> t -> t Prelude> toepassen2 (+ 5) 22 32 Prelude> toepassen2 (++ "AB") " CD "" CDABAB "

Het eerste argument is inderdaad een functie, maar het argument en de retourwaarde zijn van hetzelfde type. En het tweede argument is de waarde van dit type, en de retourwaarde is ook de waarde van dit type. De functie Apply2 kan dus worden toegepast op een beperktere reeks functies dan de dollar. Als dollar polymorf is in argument en retourwaarde, dan is apply2 polymorf in slechts één parameter.

De flip-functie uit de standaardbibliotheek is als volgt gedefinieerd: flip f y x = f x y.

Prelude> flip (/) 4 2 0.5 Prelude> (/) 4 2 2.0 Prelude> flip const 5 True True Prelude>: t flip flip :: (a -> b -> c) -> b -> a -> c Prelude>: t flip const flip const :: b -> c -> c

(- Een nuttige functie is gedefinieerd in de Data.Function-module hogere orde -} op :: (b -> b -> c) -> (a -> b) -> a -> a -> c op op f x y = f x `op` f y (- Er zijn vier argumenten nodig: 1) binaire operator met hetzelfde type argumenten (type b), 2) een functie f :: a -> b die een waarde van het type b retourneert, 3,4) en twee waarden van type a. De functie aan past f twee keer toe op twee waarden van het type a en geeft het resultaat door aan een binaire operator. Met on kun je bijvoorbeeld de functie van het optellen van de kwadraten van de argumenten als volgt schrijven :-) sumSquares = (+) `aan` (^ 2) (- De functie multSecond, die de tweede elementen van paren vermenigvuldigt, wordt als volgt geïmplementeerd -) multSecond = g `aan` h g = (*) h = snd

Anonieme functies

In Haskell, net als in de wiskunde, worden functies meestal benoemd. Wanneer we een functie moeten aanroepen, verwijzen we ernaar bij naam. Er is echter een alternatieve benadering die anonieme functies wordt genoemd.

Prelude> (\ x -> 2 * x + 7) 10 27 Prelude> let f "= (\ x -> 2 * x + 7) Prelude> f" 10 27

Deze anonieme functie of een lambdafunctie.

Er is syntactische suiker om de notatie te vereenvoudigen.

Prelude> laat lenVec xy = sqrt $ x ^ 2 + y ^ 2 Prelude> laat lenVec x = \ y -> sqrt $ x ^ 2 + y ^ 2 Prelude> laat lenVec = \ x -> \ y -> sqrt $ x ^ 2 + y ^ 2 Prelude> lenVec 3 4 5.0 Prelude> let lenVec = \ xy -> sqrt $ x ^ 2 + y ^ 2 Prelude> lenVec 3 4 5.0


Anonieme functies worden gebruikt bij het gebruik van functies van een hogere orde.

(- Functie on3, heeft dezelfde semantiek als aan, maar heeft een drie-positiefunctie als eerste argument -) on3 :: (b -> b -> b -> c) -> (a -> b) -> a -> a -> a -> c on3 op f x y z = op (f x) (f y) (f z) (- De som van de kwadraten van drie getallen kan worden geschreven met on3 zoals zo -) sum3squares = (\ x y z -> x + y + z) `on3` (^ 2)

Curried en uncurried functies

Met de syntaxis voor het aanroepen van functies in Haskell, kunt u niet alle argumenten weergeven, maar slechts een deel ervan. De eerste paar argumenten voor een functie kunnen worden opgegeven en de rest kan worden weggegooid. Dit idee van gedeeltelijke toepassing van functies is uitgevonden door Haskell Curry en ter ere van hem worden dergelijke functies met één voor één doorgegeven argumenten curried genoemd. In Haskell zijn niet alle functies gecurryd. In Haskell kun je functies op tupels definiëren. In dit geval ziet de syntaxis voor het aanroepen van functies er hetzelfde uit als in gewone talen:
functienaam (eerste_argument, tweede_argument)

Prelude> fst (1, 2) 1


Currying is de procedure om van niet-gecurryde functies naar functies te gaan die argumenten één voor één aannemen. Stel je voor dat we een functie van hogere orde hebben, zoals de on combinator, hij verwacht dat 2 van zijn 4 argumenten een functie zijn. Het eerste argument is een functie met twee argumenten die gecurryd is. Haskell heeft een speciale curry-combinator die overgaat van een niet-gecurryde functie naar een gecurryde. In het volgende voorbeeld verandert curry de functie die op een paar is gespecificeerd in een standaardcurry-functie van twee argumenten.

* Demo>: t op op :: (b -> b -> c) -> (a -> b) -> a -> a -> c * Demo>: t curry fst `on` (^ 2) curry fst `aan` (^ 2) :: Num b => b -> b -> b


Een ander voorbeeld, een niet-gecurreerde gemiddelde functie:

Gem :: (Dubbel, Dubbel) -> Dubbel gem p = (fst p + snd p) / 2

De curry avg `on` (^ 2) functie is een functie die het gemiddelde berekent van de kwadraten van de twee waarden die eraan zijn doorgegeven.

De curryfunctie is:

Prelude> let cur fxy = f (x, y) Prelude>: t cur cur :: ((t1, t2) -> t) -> t1 -> t2 -> t Prelude>: t curry curry :: ((a , b) -> c) -> a -> b -> c

Het heeft een niet-gecurreerde functie als eerste argument, d.w.z. functie over een paar, maar verandert het als een retourwaarde in een curried-functie waarin de argumenten opeenvolgend worden doorgegeven.

Er is omgekeerde functie uncurry:

Prelude>: t uncurry uncurry :: (a -> Prelude>: t uncurry (flip const) uncurry (flip const) :: (b, c) -> c Prelude>: t snd snd :: (a, b) - > b

De Data.Tuple-module van de standaardbibliotheek definieert de functie swap :: (a, b) -> (b, a) die de elementen van een paar verwisselt:

GHCi> verwisselen (1, "A") ("A", 1)

Deze functie kan worden uitgedrukt als:

Prelude> laat swap = uncurry (flip (,)) Prelude> swap (1, "A") ("A", 1)

Strikte en lakse functies

Luie evaluatie leidt ertoe dat het in veel situaties mogelijk is om onvolledigheden van het programma te elimineren.

Const42 :: a -> Int const42 = const 42

De functie const42 negeert de waarde van het argument volledig, daarom, binnen het kader van het luie rekenmodel, als u er een complexe berekening aan doorgeeft als argument, zal deze berekening nooit plaatsvinden. Dit betekent dat elk programma, inclusief een niet-beëindigend programma, als argument aan const42 kan worden doorgegeven.

* Demo> const42 True 42 * Demo> const42 123 42 * Demo> const42 (1 + 3) 42 * Demo> const42 undefined 42

Functies zoals const42 worden lax-functies genoemd. Als een divergente berekening als argument aan een functie wordt doorgegeven, en het resultaat is een waarde die niet divergent is, wordt zo'n functie niet-strikt genoemd. Een functie wordt strikt genoemd, zodat als we er een afwijkend argument aan doorgeven, de waarde van deze functie noodzakelijkerwijs divergent is. Een functie met twee argumenten kan strikt of niet-streng zijn voor het tweede argument, afhankelijk van de waarde van het eerste argument. Er is een ernstanalyse nodig om een ​​Haskell-programma zeer efficiënt te maken.

Ik denk dat alle vaste lezers van mijn blog weten dat ik een matig fervent volger ben. Het is niet dat ik niets over al het andere wil horen - nee, het is gewoon dat ik altijd pleit voor mogelijkheden voor keuze, discussie en constant zoeken best, wat uiteindelijk betekent voor een soort evolutie van ontwikkelingsmethodologieën. De persoonlijkheidscultus is voor mij net zo onaangenaam als de cultus van een aparte programmeermethodiek, omdat het op de lange termijn een eenduidig ​​pad is naar stagnatie en waanzin.

Voortzetting van dit educatieve werk, zou ik me vandaag willen concentreren op - een prachtige functionele programmeertaal. Ik heb al drie keer dezelfde vraag gekregen: waar moet ik beginnen (doorgaan) om Haskell te leren?

Misschien is het tijd om een ​​kort antwoord, advies te geven. Hier algemeen algoritme: inbreng in dit onderwerp van mij.

Fase 0 - Introductie. Haskel? Hoezo?

Een bekende paradox onder recruiters van programmeurs, vaak aangeduid als "", en het is ongeveer als volgt geformuleerd:

Als een bedrijf een minder gebruikelijke esoterische programmeertaal als belangrijkste programmeertaal kiest, dan heeft zo'n bedrijf de grootste kans om de beste programmeurs op de markt te krijgen. Waarom? Feit is dat die programmeurs voor wie het leren van nieuwe dingen geen probleem is, in zo'n "vreemd bedrijf" aangenomen willen worden; degenen voor wie weinig bekend en moeilijk te bereiken geen obstakel is; en, ten slotte, degenen die een hoog genoeg gevoel van eigenwaarde hebben om zichzelf in zulke notoir barre omstandigheden aan te bieden.

En het belangrijkste is dat er twee soorten programmeurs zijn: degenen die leren krijgen Goed werk en ze kiezen altijd mainstream omdat het hun kansen op het vinden van een baan aanzienlijk vergroot; en degenen - die gewoon graag iets nieuws willen leren, zich willen ontwikkelen, en ze kiezen er altijd voor het beste, wat vaak verre van is de meest winstgevende zoals hun collega-carrièremakers doen. Dus, De python-paradox beweert dat door te beginnen met ontwikkelen op het geavanceerde exotische, je, net als een stofzuiger, de tweede categorie programmeurs zult aantrekken (het tegenovergestelde is waar als het gaat om bedrijven die banen aanbieden).

Ik kan een abstract voorbeeld noemen van een volledig vergelijkbare verkapte targeting van focusgroepen met: gegeven eigenschappen, een verhaal uit zijn recente jeugd. Toen ik nog studeerde, hadden we een "rare" houding, die demonstratief bij het presenteren matanalyse nooit op gelet rechter zijde publiek. Dat wil zeggen, er waren twee rijen in het publiek - links en rechts - en nu geeft hij een lezing, legt hij iets uit, maar tegelijkertijd kijkt hij NOOIT naar de rechterrij - alle aandacht is alleen voor de studenten van de linkerrij . Ook met de antwoorden op de vragen - de juiste rij bestond voor hem niet. Vanaf daar hoort hij niets.

Als gevolg hiervan merkte ik in de loop van een lange tijd iets interessants op: in onze groep was er een automatische zelfidentificatie en fragmentatie in degenen die calculus noodzakelijk en interessant (en ze namen onmiddellijk plaats op de linkerbaan, nadat ze de regels van dit vreemde spel hadden geaccepteerd), en degenen die het niet nodig hebben, en ze haastten zich om plaatsen aan de rechterkant in te nemen, omdat ze hier aan zichzelf werden overgelaten . Dit sorteren gebeurde vanzelf, zonder extra buitengewone inspanningen van buitenaf. Voor de leraar, zoals ik zijn motivatie begreep, was het erg handig - hij verspilde zijn energie niet aan in wezen buitenstaanders, maar creëerde onmiddellijk de voorwaarden om zijn kracht en aandacht te concentreren op degenen die zijn kennis nodig hadden. Voor C-klasse studenten was dit ook een winnende situatie.

3. Stage - zoeken naar diepte en gevoel van een nieuwe taal

De derde fase graaft al dieper. Hier stel ik voor om de traditionele patronen een beetje te doorbreken (en oh, wat doe ik dit graag) en over te schakelen naar een fundamenteel ander formaat voor het presenteren van informatie: dit diversifieert niet alleen de taak van het leren van een taal, maar omvat ook nieuwe, tot nu toe niet geactiveerde gebieden van je hersenen (we zullen vooral je linkerhersenhelft van je programmering belasten). Ik bedoel een uitstekende videolezing over Haskell van een heel slimme man met Engelse roots.

Hier is haar uitvoer:

De cursus Functioneel programmeren met Haskell
(Taal Engels)
35 uur | 1280 × 720 | XviD - 1326Kbps
25,00 fps | Mp3 - 96Kbps | 20,06 GB

Je kunt deze geweldige videocollege downloaden. Ik raad je aan om op te schieten totdat de verontwaardigde copyrighthouders aan komen rennen en dit zeldzame archief van nafig ( bijwerken:ja, het is gelukt: amen. Ik nodig alle geïnteresseerden uit om deze megalink te gebruiken).

4. De laatste fase - oefenen

Het vinden van de meest geschikte en inspirerende praktische taak voor jou is het onderwerp van een aparte post, waar ik enkele levendige voorbeelden wil geven uit het leven van beroemde goner programmeurs, dus voorlopig stellen we mijn uitleg hierover uit de laatste fase even terzijde.

Hier, zoiets als dit, voor velen gedeeltelijk duidelijk, wilde ik geven aan iedereen die Haskell wil leren, en niet alleen. Ga ervoor!

En tot slot, voor aanhangers van andere programmeertalen:

Haskell is een heilige programmeertaal geschonken aan sjamanen Bubenland hun opperste godheid Komonada hoe universele remedie voor communicatie en spirituele reiniging, geschikt voor zowel goddelijke entiteiten als (sommige) gewone stervelingen die zijn hersteld van ernstige stadia van het intellect. Door zijn oorsprong is de taal altijd functioneel zuiver geweest. Gemiddeld begint het leren van Haskell op de leeftijd van 10-12 jaar. Door op tijd aan de slag te gaan, weet je zeker dat je op 75-jarige leeftijd het derde niveau van Power bereikt. Je moet niet uitstellen voor het volgende leven wat je kunt doen minstens begin bij deze.

Matthew Griffin

Na een lange tijd Haskell gestudeerd te hebben, heb ik genoeg ervaring opgedaan om je nu een paar tips te geven. Ik zou ook graag enkele principes voor mezelf willen leren voordat ik verder ga.

En hoewel ik soms mijn toevlucht neem tot Python-hulp, wordt het meeste van mijn werk op het web nu gedaan in Haskell.

Gegevens eerst

Ik dacht erover om van een dynamische taal naar een statische taal te gaan, en in Haskell wordt de datastructuur waarmee je werkt duidelijk beschreven in de verklaring. In Python voert code deze taak meestal uit.

Toen ik voor het eerst functies in Haskell zag, vroeg ik me af: "Wat is data? Neemt deze functie iets aan de ingang en geeft iets aan de uitgang?" En toen ik met Python werkte, had ik een vraag: "WAT ZEGT DE CODE?"

De Haskell-datastructuur heeft mijn manier van denken gevormd, die ik heb meegenomen naar mijn werk in Python. Mijn code is merkbaar beter. En hoewel het mij heel vaak leek dat de vorm van de gegevens die ik beschreef zonder reden veranderde, werd in feite alles duidelijk met een beetje studie van de kwestie. Beperkingen op de vrijheid om gegevens te wijzigen, maken de code ook minder complex en gemakkelijker te begrijpen.

Leesbaarheid van de code

Python trok me aan met het vermogen om echt te schrijven leesbare code... De voorbeelden van de Haskell-code zagen er gewoon verschrikkelijk uit, met uitzondering van enkele fragmenten die met opzet leken te zijn geplukt om nieuwelingen niet bang te maken. En hoewel sommige stukjes code er erg mooi uitzagen, was de meeste broncode gevuld met iets engs. En achter dit "verschrikkelijke" ging alle kracht van de taal schuil.

Ik wilde absoluut geen "slimme" code schrijven - een code die de indrukwekkende mogelijkheden van de taal kan demonstreren, maar volledig onhandig is.

Ik heb echter de leesbaarheid van Haskell geëvalueerd in vergelijking met andere populaire programmeertalen. Het was alsof ik aan het evalueren was Chinese moedertaalspreker van het Engels zijn.

Ik realiseerde me dat Haskell geen "slimme" taal is, maar een sluwe taal. Het is zeker mogelijk om "slimme" code te schrijven in Haskell, maar dit is niet gebruikelijk. Tegelijkertijd is de kracht van slimme code beperkt tot krachtig typen. Als de functie Int zou moeten retourneren, zal deze Int teruggeven. Nou, of een compilatiefout gooit als laatste redmiddel.

En de krachtigere abstracties in Haskell doen denken aan een soort magie die ik probeerde te vermijden toen ik met Python werkte.

Ik ben serieus over leesbaarheid

Geloof en overtuig uzelf eerst dat mensen inderdaad aanbiedingen in deze nieuwe taal voor u lezen, en dat ze dit snel en regelmatig doen. Nadat ik eindelijk de meeste bekende nuances had behandeld, begon ik me kalm te verhouden tot de code in Haskell.

Opmerkingen. ze lenen bovenste regel in een van de hoofdstukken van ons "boek".

Dit hoofdstuk beschrijft hoe Tommy naar de winkel ging en een eend kocht.

hoofdstuk :: Tommy -> Markt -> Eend

Functies van een andere, gereduceerde functie, in het grote geheel, de code tot het maximum reduceren.

Beknoptheid. Je hebt niet veel code nodig om je ideeën uit te laten komen.

Symbolen invoegen

Ik wilde ook de plug-infuncties noemen die gebruikelijk zijn in de Haskell-taal. Functies invoegen (of operators) zijn die functies die gebruik maken van tussen voor twee argumenten in plaats van voordat. Een eenvoudig voorbeeld is "+".

In Haskell hebben we een paar standaard opvultekens: $,<$>, <-, ->, enz. Ze kunnen u een beetje in de war brengen aan het begin van de reis.

Geen zorgen! Als u eenmaal weet hoe u ze moet gebruiken, zult u begrijpen hoe nuttig en eenvoudig ze zijn. Ik telde ongeveer 5 symbolen die ik regelmatig gebruik.

Ik raad niet aan om de lensbibliotheek meteen te gebruiken, omdat deze een heleboel van dergelijke symbolen bevat. Deze bibliotheek is erg handig, maar in het begin zou je zonder deze bibliotheek groot succes moeten kunnen behalen. Wacht tot je redelijk complexe programma's veilig kunt schrijven in Haskell en ga dan lens gebruiken.

Je moet je kennis volledig vernieuwen

Terwijl je Haskell leert, zul je onderweg nieuwe termen tegenkomen, zoals: functor of monade.

Misschien vindt u deze woorden moeilijk te onthouden en te leren. Wanneer u vertrouwd raakt met een populaire programmeertaal, zijn veel van de termen duidelijk en vertrouwd voor u uit de talen die u hebt geleerd.

We onthouden informatie door deze te associëren met andere informatie. Ik heb bijvoorbeeld geen associaties met het woord functor, dus het zal niet gemakkelijk voor me zijn om deze term te leren.

Mijn strategie om zulke woorden te leren kwam vrij recent in me op, en ik begon hem elke keer te gebruiken als ik een term zag die ik niet begreep. Het bestaat uit het selecteren van synoniemen voor die woorden die u niet begrijpt en waarmee u niet vertrouwd bent. Na een tijdje leerde ik deze synoniemen op te pikken.

Bijvoorbeeld, functie.

In Haskell wordt er veel op je scherm weergegeven. Een lijst is bijvoorbeeld een functor. Dit betekent dat een weergavefunctie die een andere functie gebruikt, in de lijst wordt weergegeven. Toen gemaakt nieuwe lijst met de resultaten.

Kaart (+1) - resultaten in

Dus ik heb hier de naam aan gegeven - mapa. Het woord mapa is heel gemakkelijk te onthouden. De lijst is een functor. De lijst is een kaart.

Mijn foutcontrolesysteem

Toen ik in Python schreef, was mijn debugging-tool afdrukinstructies.

In Haskell gebruikte ik systematische tools.

Maar! U kunt Debug.Trace toepassen. Deze techniek is vergelijkbaar met die in Python-functie printen is onafhankelijk van Haskell IO. EN deze module kan in het begin voordelig zijn. Toen u voor het eerst met Haskell begon te werken, dacht u er dan over na hoeveel u het zou gebruiken?

Als je na controle op fouten geen trace-statements in je code gebruikt, zul je meteen merken dat je code er in Haskell slechter uitziet dan in Python.

Beste Monad-zelfstudie

Elke keer dat je hoort over het succes van een Haskell-programmeur, vraag je je af: "Hoe heeft deze persoon monaden tot het einde geleerd?" Alles is dus in orde.

Ik moet wat ontleden. Ik wist hier het een en ander over toen ik in Python schreef. Maar door mijn onervarenheid op dit gebied is het nu best lastig om een ​​analyse te maken.

Oké, nu zal ik je meer vertellen. Ik zal het uitleggen in Haskell.

Ik vond een YouTube-video, "Spullen parseren in Haskell", waarin wordt beschreven hoe je JSON-parsing in Haskell uitvoert met behulp van de Parsec-bibliotheek.

Deze video hielp me onbedoeld erachter te komen hoe ik monaden en applicatieve functors kon gebruiken om te creëren wat ik nodig had. Ik ontdekte hoe hun functies (har, har) met elkaar verbonden zijn.

Na het schrijven ontleden met behulp van de video begon ik alle code te begrijpen. Ik begon ook zijn hele "natuur" te begrijpen. Maar in de beginfase zal dit niet van pas komen.

Dus Parsec doet zijn werk redelijk goed, zodat mijn onervarenheid bij het schrijven van analyses praktisch onzichtbaar is. Net als elke andere beginner in Haskell, kon ik gemakkelijk goede programma's en bewerkingen maken, zelfs aan het begin van mijn kennis van deze taal.

Profiteer van uw kennis

Haskell is mijn primaire taal om verschillende redenen:

  1. De keuze van technologieën die ik zal gebruiken.
  2. Ik kan mijn programma's sneller schrijven en meestal verkoop ik deze programma's.
  3. Je hebt geen last van kleine bugs.
  4. Zelfs als ik met verschillende fouten wordt geconfronteerd, los ik ze snel op, omdat ze min of meer duidelijk zijn.
  5. Python was niet gericht op snelheid. Haskell doet hetzelfde, maar de keuze is aan mij.
  6. Refactoring is in feite nogal winderig. In Python schold ik mezelf soms veel uit als ik kleine fouten in de code vergat te repareren, wat later voor enorme problemen zorgde.
  7. Geweldige bibliotheken. Het belangrijkste kenmerk van Haskell is: van hoge kwaliteit bibliotheken.
  8. Gemeenschap klaar om te helpen.
  9. Gemak van het schalen van code naar de gewenste kernel.
  10. Haskell wordt regelmatig bijgewerkt. Vorig jaar, toen GHC (de compiler voor Haskell) werd geüpdatet naar versie 7.8, waardoor het coderen twee keer zo handig was, werden veel webservers versneld.

Tot slot wil ik zeggen dat Haskell me veel plezier heeft bezorgd. Het was beste ervaring in mijn hele leven.

Ik ben ze vaak gevraagd. Ik antwoord.

'Wat is die Haskell van jou?'

Haskell is een puur functionele programmeertaal algemeen doel, kan worden gebruikt om een ​​breed scala aan problemen op te lossen. Gecompileerd, maar het kan zich ook gedragen als een script. Cross-platform. Lui, sterk statisch getypt. En het is niet zoals andere talen. Helemaal niet.

"Is dit een nieuwe taal?"

Helemaal niet. De geschiedenis van Haskell gaat terug tot 1987. Deze taal werd geboren in wiskundige kringen toen een groep mensen besloot om de beste functionele programmeertaal te maken. In 1990 werd de eerste versie van de taal uitgebracht, genoemd naar de beroemde Amerikaanse wiskundige Haskell Curry. In 1998 werd de taal gestandaardiseerd en vanaf de jaren 2000 begon het langzaam de wereld binnen te komen. praktisch programmeren... In de loop der jaren is de taal verbeterd en in 2010 zag de wereld zijn bijgewerkte standaard. We hebben dus te maken met een taal die ouder is dan Java.

'En wie heeft het gemaakt?'

Haskell is gemaakt door veel mensen. De meest bekende implementatie van de taal werd belichaamd in de GHC (The Glasgow Haskell Compiler), die in 1989 werd geboren aan de Universiteit van Glasgow. De compiler had verschillende hoofdontwikkelaars, waarvan er twee de meest bekende zijn, Simon Peyton Jones en Simon Marlow. Vervolgens hebben enkele honderden mensen nog een belangrijke bijdrage geleverd aan de ontwikkeling van GHC. Bron de GHC-compiler is geopend. Trouwens, de compiler zelf is voor 82% geschreven in Haskell.

Voor de nieuwsgierigen: lees voor een uitgebreid verslag van de geschiedenis van Haskell en GHC.

'Zijn er bibliotheken voor Haskell?'

O ja! Het zijn er niet eens honderden - het zijn er duizenden. Tijdens het lezen zul je er veel van leren kennen.

"En wat, het is al mogelijk in productie?"

Het is al in productie. Sinds de release van de eerste standaard is de taal verbeterd, is het ecosysteem ontwikkeld, zijn er nieuwe bibliotheken verschenen en zijn er boeken gepubliceerd. Haskell is helemaal klaar voor serieus commercieel gebruik, zoals blijkt uit de verhalen over de succesvolle implementatie van Haskell in het bedrijfsleven, ook grote.

'Is de drempel om Haskell binnen te komen hoog?'

Ja en nee. Het beheersen van Haskell is vooral moeilijk vanwege de ongelijkheid met andere talen, dus mensen met ervaring met andere talen zullen hun hersens moeten breken. Om ze te breken, niet alleen om ze te verplaatsen: Haskell laat je anders kijken, zelfs naar bekende dingen. Aan de andere kant is Haskell eenvoudiger dan veel bekende talen. Geloof me niet op mijn woord, je zult het snel zelf zien. En weet: veel mensen, die de smaak van Haskell hebben geleerd, willen absoluut niet terugkeren naar andere talen. Ik heb je gewaarschuwd.

"En ik hoorde ook over enkele monaden ..."

Ja, zoiets bestaat. Sommige dingen uit de wereld van Haskell hebben geen directe tegenhangers in andere programmeertalen, en dit brengt nieuwelingen in de war. Maar maak je geen zorgen: ik ben zelf door deze verdoving heen gegaan en begrijp je goed. Onthoud: het nieuwe lijkt alleen maar eng.

"En als je het vergelijkt met C++ / Python / Scala..."

Haskell vergelijken met andere talen valt buiten het bestek van dit boek. Meerdere keren zul je hier stukjes code in andere talen tegenkomen, maar ik presenteer ze alleen om het verschil met Haskell te benadrukken, en helemaal niet ter vergelijking in de context van "beter / slechter". En in het algemeen zal ik mijn best doen om Haskell niet te veel te prijzen, ik wil je er gewoon de waarheid over vertellen. Ik heb mijn conclusie over deze taal al gemaakt, en u moet uw eigen conclusie daarover trekken.

    Soorten

    Haskell-programma's zijn uitdrukkingen die naar waarden evalueren. Elke waarde heeft een type. Intuïtief kan een type eenvoudig worden opgevat als een verzameling aanvaardbare waarden uitdrukkingen. Om het type van een uitdrukking te achterhalen, kunt u het interpreter-commando gebruiken: type (of: t). Als alternatief kunt u de opdracht geven: set + t om de interpreter automatisch het type van elk berekend resultaat te laten afdrukken.
    De belangrijkste soorten van de Haskell-taal zijn:
    De typen Integer en Int worden gebruikt om gehele getallen weer te geven, en de waarden van het type Integer niet beperkt in lengte.
    Typen vlotter en Double wordt gebruikt om reële getallen weer te geven.
    Het Bool-type bevat twee waarden, True en False, en is bedoeld om het resultaat van Booleaanse expressies weer te geven.
    Het Char-type wordt gebruikt om tekens weer te geven. Haskell-typenamen beginnen altijd met een hoofdletter.
    De Haskell-taal is een sterk getypeerde programmeertaal. In de meeste gevallen is de programmeur echter niet verplicht om aan te geven van welk type de variabelen zijn die hij invoert. De interpreter kan zelf de soorten variabelen afleiden die door de gebruiker worden gebruikt.
    Als het echter voor welk doel dan ook nodig is om aan te geven dat een waarde tot een bepaald type behoort, wordt een constructie van de vorm: variabele :: Type gebruikt. Als de + t interpreter-optie is ingeschakeld, worden de waarden in hetzelfde formaat afgedrukt.
    Hieronder ziet u een voorbeeld van het sessieprotocol voor het werken met de tolk. De tekst die volgt op de Prelude>-prompt moet door de gebruiker worden ingevoerd en de volgende tekst is de reactie van het systeem.

    Prelude>: set + t
    Prelude> 1
    1 :: Geheel getal
    Prelude> 1.2
    1.2 :: Dubbel
    Prelude> 'een'
    'A' :: Char
    Prelude> Waar
    Waar :: Bool

    Van van dit protocol kunnen we concluderen dat waarden van het type Integer, Double en Char volgens dezelfde regels worden ingesteld als in de C-taal.
    Een goed ontwikkeld typesysteem en sterke typering maken Haskell-programma's typeveilig. Het is gegarandeerd dat in het juiste programma alle typen worden correct gebruikt in Haskell. In de praktijk betekent dit dat een Haskell-programma bij uitvoering geen toegangsovertreding kan veroorzaken. Het is ook gegarandeerd dat niet-geïnitialiseerde variabelen niet in het programma kunnen worden gebruikt. Veel fouten in een programma worden dus bijgehouden bij het compileren, niet bij de uitvoering.

    Rekenkundig

    De Hugs-interpreter kan worden gebruikt om rekenkundige uitdrukkingen te evalueren. In dit geval kunt u de operatoren +, -, *, / (optellen, aftrekken, vermenigvuldigen en delen) gebruiken met de gebruikelijke voorrangsregels.
    Als alternatief kunt u de operator ^ (exponentiatie) gebruiken. De sessie kan er dus als volgt uitzien:

    Prelude> 2 * 2
    4 :: Geheel getal
    Prelude> 4 * 5 + 1
    21 :: Geheel getal
    Prelude> 2 ^ 3
    8 :: Geheel getal
    Als alternatief kunt u de standaard wiskundige functies sqrt ( Vierkantswortel), sin, cos, exp, enz. In tegenstelling tot veel andere programmeertalen hoeft Haskell het argument niet tussen haakjes te zetten bij het aanroepen van een functie. Je kunt dus gewoon sqrt 2 schrijven en niet sqrt (2). Voorbeeld:

    Prelude> sqrt 2
    1.4142135623731 :: Dubbel
    Prelude> 1 + sqrt 2
    2.4142135623731 :: Dubbel
    Prelude> sqrt 2 + 1
    2.4142135623731 :: Dubbel
    Prelude> vierkante (2 + 1)
    1.73205080756888 :: Dubbel

    Van dit voorbeeld kunnen we concluderen dat de functieaanroep een hogere prioriteit heeft dan rekenkundige bewerkingen dus de uitdrukking sqrt 2 + 1 wordt geïnterpreteerd als (sqrt 2) + 1 en niet als sqrt (2 + 1). Gebruik haakjes om de exacte volgorde van evaluatie op te geven, zoals in het laatste voorbeeld. (Eigenlijk heeft een functieaanroep voorrang op elke binaire operator.)
    Er moet ook worden opgemerkt dat, in tegenstelling tot de meeste andere programmeertalen, integer-expressies in Haskell worden geëvalueerd met een onbeperkt aantal cijfers (probeer de expressie 2 ^ 5000 te evalueren.) In tegenstelling tot C, waar de maximaal mogelijke waarde van type int is beperkt door de capaciteit van de machine (op moderne persoonlijke computers het is 231-1 = 2147483647), kan het Haskell Integer-type gehele getallen van willekeurige lengte opslaan.

    tupels
    Naast de hierboven genoemde eenvoudige typen, kunt u waarden definiëren in Haskell samengestelde typen... Als u bijvoorbeeld een punt op een vlak wilt definiëren, hebt u twee getallen nodig die overeenkomen met de coördinaten. In Haskell kan een paar worden gespecificeerd door de componenten op te sommen, gescheiden door komma's en tussen haakjes te plaatsen: (5,3). De componenten van een paar hoeven niet van hetzelfde type te zijn: je kunt een paar maken, waarvan het eerste element een string is, het tweede een getal, enzovoort.
    In het algemeen, als a en b wat zijn willekeurige soorten in Haskell wordt het type van een paar waarin het eerste element van het type a is en het tweede van het type b, aangeduid als (a, b). Het paar (5,3) is bijvoorbeeld van het type (Integer, Integer); paar (1, 'a') is van het type (Integer, Char). Je kunt meer meenemen complex voorbeeld: het paar ((1, 'a'), 1.2) is van het type ((Integer, Char), Double). Zoek het uit met een tolk. Opgemerkt moet worden dat hoewel constructies zoals (1,2) en (Integer, Integer) er hetzelfde uitzien, ze in Haskell totaal verschillende entiteiten aanduiden. De eerste is een waarde, terwijl de laatste een type is. Om met paren in de Haskell-taal te werken, zijn er: standaard functies fst en snd, die respectievelijk de eerste en tweede elementen van het paar retourneren (de namen van deze functies zijn afgeleid van de Engelse woorden "first" en "second"). Dus ze kunnen zo worden gebruikt

    Prelude> fst (5, True)
    5 :: Geheel getal
    Prelude> snd (5, True)
    Waar :: Bool
    Naast paren kunnen triples, quadruples, etc. op dezelfde manier worden gedefinieerd. Hun typen zijn op een vergelijkbare manier geschreven.
    Voorspel> (1,2,3)
    (1,2,3) :: (Integer, Integer, Integer)
    Voorspel> (1,2,3,4)
    (1,2,3,4) :: (Integer, Integer, Integer, Integer)
    Deze datastructuur wordt een tuple genoemd. Een tupel kan een vaste hoeveelheid heterogene gegevens opslaan. De functies fst en snd zijn alleen gedefinieerd voor paren en werken niet voor andere tupels. Als je ze probeert te gebruiken, bijvoorbeeld voor drielingen, geeft de interpreter een foutmelding. Een element van een tuple kan een waarde van elk type zijn, inclusief een andere tuple. Een combinatie van de functies fst en snd kan worden gebruikt om toegang te krijgen tot de elementen van gepaarde tupels. Het volgende voorbeeld demonstreert het extraheren van een element 'a' uit een tuple
    (1, ('een', 23.12)):
    Prelude> fst (snd (1, ('a', 23.12)))
    'A' :: Geheel getal

    Lijsten
    In tegenstelling tot tupels kan een lijst een willekeurig aantal elementen bevatten. Om een ​​lijst in Haskell te definiëren, moet u: vierkante haakjes vermeld de elementen, gescheiden door komma's. Al deze elementen moeten van hetzelfde type zijn. Lijsttype met elementen, behorend tot het type a wordt aangeduid als [a].

    Prelude>
    ::
    Prelude> ['1', '2', '3']
    [’1’,’2’,’3’] ::
    Het kan zijn dat er geen items in de lijst staan. Een lege lijst wordt aangeduid als.
    Operator: (dubbele punt) wordt gebruikt om een ​​item aan het begin van een lijst toe te voegen. Het linkerargument moet een element zijn en het rechterargument moet een lijst zijn:
    Prelude> 1:
    ::
    Prelude> '5': ['1', '2', '3', '4', '5']
    [’5’,’1’,’2’,’3’,’4’,’5’] ::
    Prelude> Onwaar:
    ::
    Elke lijst kan worden gemaakt met de operator (:) en een lege lijst:
    Prelude> 1: (2: (3 :))
    :: Geheel getal
    De operator (:) is rechts associatief, dus u kunt de haakjes in de bovenstaande uitdrukking weglaten:
    Prelude> 1: 2: 3:
    :: Geheel getal
    De elementen van de lijst kunnen elke waarde zijn - getallen, symbolen, tupels, andere lijsten, enz.
    Prelude> [(1, 'a'), (2, 'b')]
    [(1, 'a'), (2, 'b')] :: [(Integer, Char)]
    Voorspel> [,]
    [,] :: []
    Om met lijsten in Haskell te werken, is er: een groot aantal van functies. In deze laboratorium werk we zullen er slechts een paar bekijken.
    De functie head retourneert het eerste element van de lijst.
    De staartfunctie retourneert een lijst zonder het eerste element.
    De lengtefunctie retourneert de lengte van de lijst.
    De kop- en staartfuncties zijn gedefinieerd voor niet-lege lijsten. Wanneer u ze probeert toe te passen op lege lijst de tolk meldt een fout. Voorbeelden van het werken met de opgegeven functies:
    Prelude> hoofd
    1 :: Geheel getal
    Prelude> staart
    ::
    Prelude> staart
    :: Geheel getal
    Prelude> lengte
    3 :: Int
    Merk op dat het resultaat van de lengtefunctie behoort tot Int-type in plaats van Integer.
    Haskell definieert de ++ operator voor het samenvoegen (aaneenschakelen) van lijsten.
    Voorspel> ++
    :: Geheel getal

    Snaren
    Stringwaarden in Haskell, evenals in C, worden gespecificeerd in dubbele aanhalingstekens... Ze zijn van het type String.
    Prelude> "hallo" "hallo" :: String
    Strings zijn eigenlijk lijsten met karakters; dus de uitdrukkingen "hallo", ["h", "e", "l", "l", "o"] en

    'H': 'e': 'l': 'l': 'o': betekent hetzelfde, en String is een synoniem voor. Alle functies voor het werken met lijsten kunnen worden gebruikt bij het werken met strings:
    Prelude> hoofd "hallo"
    'H' :: Char
    Prelude> staart "hallo"
    "Hallo" ::
    Prelude> lengte "hallo"
    5 :: Int
    Prelude> "hallo" ++ ", wereld"
    "Hallo Wereld" ::
    Bekeren numerieke waarden naar lijnen en vice versa zijn er lees- en toonfuncties:
    Prelude> toon 1
    "1" ::
    Prelude> "Formule" ++ toon 1
    "Formule 1" ::
    Prelude> 1 + lees "12"
    13 :: Geheel getal
    Als de show-functie de string niet naar een getal kan converteren, zal deze een fout rapporteren.

    Functies
    Tot nu toe hebben we de ingebouwde functies van de Haskell-taal gebruikt. Nu is het tijd om te leren definiëren eigen functies... Om dit te doen, moeten we nog een paar interpreter-commando's bestuderen (herinner je dat deze commando's kunnen worden afgekort tot één letter):
    De opdracht: load laadt het Haskell-programma in het opgegeven bestand in de interpreter.
    Het: edit commando start het bewerkingsproces van het laatst geüploade bestand.
    Het: reload commando leest het laatst geladen bestand opnieuw. definities aangepaste functies moet in het bestand staan ​​om in de Hugs-interpreter te worden geladen met de opdracht: load.
    Om het geladen programma te bewerken, kunt u het commando gebruiken: edit. Het start een externe editor (standaard Kladblok) om het bestand te bewerken. Na het einde van de bewerkingssessie moet de editor worden gesloten; de Hugs-interpreter zal de inhoud van het gewijzigde bestand opnieuw lezen. Het bestand kan echter rechtstreeks vanuit de Windows-shell worden bewerkt. In dit geval is het nodig om de opdracht: reload expliciet aan te roepen, zodat de interpreter het bestand opnieuw kan lezen.
    Laten we naar een voorbeeld kijken. Maak een lab1.hs-bestand in een map. Laat vol pad naar dit bestand - c: \ labs \ lab1.hs (dit is slechts een voorbeeld, uw bestanden kunnen een andere naam hebben). Voer in de Hugs-interpreter de volgende opdrachten uit:

    Prelude>: laad "c: \\ labs \\ lab1.hs"
    Als het downloaden is gelukt, verandert de interpreter-prompt in Main>. Het feit is dat als de modulenaam niet is opgegeven, deze wordt beschouwd als gelijk aan Main.
    Hoofd>: bewerken
    Een editorvenster zou hier moeten openen, waarin u de tekst van het programma kunt invoeren. Binnenkomen:
    x =
    Sla het bestand op en sluit de editor. De Hugs-interpreter zal het bestand laden
    c: \ labs \ lab1.hs en nu wordt de waarde van de variabele x bepaald:
    Hoofd> x
    ::
    Merk op dat de \-tekens worden gedupliceerd bij het schrijven van de bestandsnaam in het argument: load command. Net als in de C-taal, dient in Haskell het \-teken als aanduiding van het begin van een serviceteken ('\ n', etc.) ...
    Nu kunt u doorgaan met het definiëren van functies. Maak, in overeenstemming met het hierboven beschreven proces, een bestand en schrijf daarin de volgende tekst:

    vierkant :: Integer -> Integer
    vierkant x = x * x

    De eerste regel (vierkant :: Integer -> Integer) verklaart dat we een functievierkant definiëren waaraan een Integer-parameter moet worden doorgegeven en een Integer-resultaat wordt geretourneerd. De tweede regel (vierkant x = x * x) is de functiedefinitie zelf. De kwadraatfunctie neemt één argument en retourneert het kwadraat ervan. Functies in Haskell zijn "eerste klas" waarden. Dit betekent dat ze "gelijk" zijn aan waarden zoals gehele getallen en echte getallen, karakters, strings, lijsten, enz. Functies kunnen als argumenten worden doorgegeven aan andere functies, worden geretourneerd door functies, enz. Zoals alle waarden in Haskell, zijn functies van een type. Het type functie dat waarden van type a aanneemt en waarden van type b retourneert, wordt aangeduid als a-> b.
    Laad het gegenereerde bestand in een interpreter en voer de volgende opdrachten uit:

    Hoofd>: typ vierkant
    vierkant :: Integer -> Integer
    Hoofd> vierkant 2
    4 :: Geheel getal
    Merk op dat de typedeclaratie van de kwadratenfunctie in principe niet nodig was: de interpreter zelf kon afleiden Nodige informatie over het type van de functie uit de definitie. Ten eerste zou het afgeleide type echter algemener zijn dan Integer -> Integer, en ten tweede is het expliciet aangeven van het type van de functie "good practice" bij het programmeren in Haskell, aangezien de typedeclaratie dient als een soort documentatie voor de functie en helpt bij het identificeren van programmeerfouten.
    Door de gebruiker gedefinieerde namen van functies en variabelen moeten beginnen met een kleine Latijnse letter. De rest van de tekens in de naam kunnen hoofdletters of kleine letters zijn met Latijnse letters, cijfers of symbolen _ en '(underscore en apostrof). Dit zijn dus voorbeelden van geldige variabelenamen:

    var
    var1
    variabelenaam
    variabele_naam
    var '

    Voorwaardelijke uitdrukkingen

    U kunt voorwaardelijke expressies gebruiken in een functiedefinitie in Haskell. Laten we de signum-functie schrijven die het teken berekent van het argument dat eraan wordt doorgegeven:

    signum :: Integer -> Integer
    signum x = als x> 0 dan 1
    anders als x anders 0

    De voorwaardelijke expressie wordt geschreven als:
    als voorwaarde dan uitdrukking anders uitdrukking. Merk op dat hoewel deze uitdrukking eruitziet als de corresponderende operator in C of Pascal, een voorwaardelijke uitdrukking in Haskell zowel het then-deel als het else-deel moet hebben. Uitdrukkingen in then-part en else-part voorwaardelijke operator moet van hetzelfde type zijn. Een voorwaarde in een voorwaardelijke instructiedefinitie is elke expressie van het type Bool. Vergelijkingen zijn voorbeelden van dergelijke uitdrukkingen. De volgende operatoren kunnen ter vergelijking worden gebruikt:
    , = - deze operatoren hebben dezelfde betekenis als in de C-taal (kleiner dan, groter dan, kleiner dan of gelijk, groter dan of gelijk).
    == is een gelijkheidsoperator.
    / = - operator van het controleren op ongelijkheid.
    Expressies zoals Bool kunnen worden gecombineerd met common logische operatoren&& en || (EN en OF), en de ontkenningsfuncties niet.
    Voorbeelden van geldige voorwaarden:
    x> = 0 && x x> 3 && x / = 10
    (x> 10 || x Natuurlijk kunt u uw eigen functies definiëren die Bool-waarden retourneren en deze als voorwaarden gebruiken. U kunt bijvoorbeeld de functie isPositive definiëren, die True retourneert als het argument niet-negatief en False is anders:
    isPositive :: Integer -> Bool
    isPositief x = als x> 0 dan waar, anders niet waar

    De signum-functie kan nu als volgt worden gedefinieerd:
    signum :: Integer -> Integer
    signum x = als is Positief x dan 1
    anders als x anders 0
    Merk op dat de functie isPositive op een eenvoudigere manier kan worden gedefinieerd:
    isPositief x = x> 0

    Informatie is afkomstig van: http://sguprog.narod.ru/