Sfaturi (novice) Horror Haskel

Sunt programator începător pentru Haskell și, în timp ce îmi amintesc tot ce este teribil. Și vreau să scriu asta. Trebuie să spun că, când am început Haskell, încă nu știam nimic despre programarea funcțională, deci simultan cu limba, trebuia să învăț noi idei și moduri de gândire. Și de fapt a fost minunat. Și frică, după cum știți, ochii sunt minunați. În general, cred că această notă poate fi utilă și pentru alți începători. În ea, voi scoate în evidență cinci lucruri de neînțeles la început, dar lucruri relativ simple, înțelegând care, cel puțin aproximativ, mi-a fost mult mai ușor să stăpânesc limba.







1. Funcțiile Lambda

"Dar o numim o pâine de lămâie sau pământ, se consolidează mai bine decât orice alimente de oameni și este mult mai gustoasă".

Expresia Lambda - însăși esența "funcțiilor" este o expresie a formei
Valoarea acestei expresii este încă o funcție fără nume a unui argument (x), ceea ce îl calculează (și anume, expresia din dreapta punctului). Cu funcțiile lambda, o teorie matematică gravă este conectată, dar din punct de vedere al programării poate fi considerată un cuvânt cheie pentru definirea funcțiilor. Într-adevăr, când am folosit deja lambdas în Python (și există, de asemenea, în aproape toate celelalte limbi moderne). În Python, arată astfel:
Ele erau foarte convenabile pentru a fi folosite în filtrul () și reduce (). Și, în general, aproape peste tot, în cazul în care numele funcției este necesar ca argument. Cu toate acestea, funcțiile lambda nu au nume, și de aceea ele sunt numite și funcții anonime (fără nume). În Python, uneori i-am dat numele pe zbor:
Acum, numele add_42 indică funcția. Exact același rezultat ar putea fi obținut prin scrierea definiției funcției ca de obicei:
Și cum rămâne cu Haskell? Da, aproape la fel. Caracterul \ înlocuiește, -> servește în locul unei perioade. Toată lumea este scrisă astfel:
Și putem da chiar și nume unor astfel de funcții fără nume, la fel ca în Python:
Sunt de acord, foarte asemănătoare.

În Haskell, toate funcțiile sunt funcții ale unui singur argument. La început acest lucru poate părea o limitare, dar în realitate este o idee foarte convenabilă și practică. Orice funcție a argumentelor n poate fi reprezentată ca o funcție a unui argument, returnând o altă funcție a argumentelor n-1. Și în știință se numește currying. Această idee, în special, vă permite să transferați funcții doar o parte din argumente.

Chiar și aceste concepții simple despre funcțiile lambda erau deja suficiente pentru a începe să folosească Haskel și pentru a înțelege cele mai multe exemple și explicații.

2. Semnul privind egalitatea

- Dacă nu are sens, spuse Regele, atunci avem un munte de pe umeri: nu trebuie să încercăm să-l găsim! Salvați o mulțime de muncă! Și totuși.

În opinia mea, semnul egal (=) este cel mai important simbol al lui Haskell. Pentru a înțelege este important pentru înțelegerea limbii. Și mi se pare că sensul egalității nu este suficient de subliniat în tot felul de manuale. De exemplu, acesta este singurul cuvânt cheie care lipsește din lista de cuvinte cheie a lui Haskell pe wiki-ul său.

Spre deosebire de majoritatea limbajelor imperative, unde = înseamnă alocare (adică acțiune), în Haskell înseamnă că partea stângă este egală cu cea dreaptă (adică, descrie proprietatea).

"Egal" nu înseamnă "devine". Aceasta înseamnă că ceva este egal cu altceva. Întotdeauna. Ca și în matematică. a = b în Haskell înseamnă că a este egală cu b prin definiție. a este echivalent cu b.

Astfel, în Haskell servește pentru a scrie definiții. "Equals" poate identifica o varietate de lucruri, dar le definește în mod static. Nu depinde de ordinea operațiunilor. Te poți baza pe el.

Pentru utilizatorii de limbi funcționale, acest lucru pare prea evident, dar tocmai în sensul semnului de egalitate cea mai importantă schimbare este pentru cei care au folosit limbi imperative. Acum, apropo, putem da nume funcțiilor noastre fără nume:
Recunosc că este citit prost, deci în majoritatea cazurilor funcțiile din Haskell sunt definite după cum urmează:
Dar aceasta este în continuare definiția funcției add.

3. Clase de tipuri

Beneficii semnificative decurg din partajarea unui sistem de tip comun, a unui set comun de instrumente și așa mai departe. Aceste avantaje tehnice se traduc în beneficii practice importante, cum ar fi permiterea grupurilor cu nevoi moderat diferite. - atribuită lui B. Straustrupu

Sistemul de tip din Haskell este pur și simplu frumos. Multe idei se exprimă foarte ușor și natural în ea. Și este posibil ca clasele de tip să fie cel mai puțin străin concept pentru cei care vin la Haskell dintr-o lume procedurală și orientată spre obiecte. În orice caz, m-am gândit așa. Cu toate acestea, clasele de tip nu sunt la fel ca clasele din C ++ sau Java. Mult mai mult ele sunt similare cu șabloanele clasei abstracte din C ++, deoarece clasele de tip






  • defini doar interfața abstractă
  • permiteți să creați mai multe implementări independente ale interfeței (astfel, pentru orice tip, puteți defini o instanță a unei clase dacă furnizați o implementare a metodelor sale)
  • polimorfic în natură și sprijin moștenire
  • nu pot avea variabile de stare

De îndată ce ne obisnuim cu ce tipuri de clase - nu este clasele C ++, și interfețe abstracte, și cazuri de clase nu sunt „obiecte“, și punerea în aplicare specifică a interfețelor abstracte, Haskell o dată devine familiar și confortabil.

Vă sfătuiesc cu fermitate să citiți articolul wiki OOP vs clase de tip. care compară abordarea orientată-obiect și abordarea de tip de clasă mult mai detaliat.

Și de vreme ce orice stare de fapt a unei simple substanțe, desigur, este o consecință a stării sale anterioare, prezentul este plin de un viitor - Leibniz, "Monadologia"

Nu contează cât de ușoară este introducerea lui Haskell. mai devreme sau mai târziu, cititorul își sprijină fruntea pe un zid puternic de monade. Da, nu este pentru tine să freți chiflele, este o matematică serioasă pentru tine. Undeva dincolo de acest zid.

Dar iată ce mi-am dat seama: studierea matematicii abstracte nu este necesară pentru a folosi monadele și ele sunt într-adevăr tehnici de programare foarte elegante. La început, mi sa părut puțin ciudat, dar pentru a înțelege o dată pentru totdeauna monadele este mult mai ușor decât să ne amintim (și să aplicăm corect!). Numeroasele modele ale designului OO. Monadele sunt mai logice.

Deoarece există multe tutoriale despre monade, nu le voi repeta aici și mă aștept să le citiți deja un cuplu. Ce e în neregulă cu monadele? Pentru un om obișnuit cu un limbaj imperativ, răsfățat de ani de gândire orientată spre obiecte, monadele par ciudate. Ele arata ca o clasa abstracta de containere cu o metoda misterioasa >> =:
Ei bine, dacă întoarcerea este un constructor, atunci de ce un nume minunat? Dacă este vorba despre o clasă de containere, cum să extrag ceva din ea? Și care este folosirea funcției în interiorul containerului (ceea ce este metoda >> >> numită și operația de legare), dacă nu putem obține rezultatul din acest container?

Mai întâi răspund la ultima întrebare. De ce trebuie să leagă (>> =)? Monadele sunt și în același timp nu sunt containere. Sunt ambalaje, pachete pentru calcule. nu pentru valori (return). Cu toate acestea, ele nu calculează calculele pentru a fi mai convenabile pentru a le depozita în cutii monadice, dar ele pot fi mai bine conectate una cu cealaltă. În loc de "cutii" imaginați cărămizi obișnuite, care sunt așezate plat unul față de celălalt. Acest lucru, apropo, este similar cu modelul adaptorului în design-ul OO. Fiecare monad definește o modalitate de a transfera rezultatul de la un calcul la altul și implementează interfața standard pentru a utiliza această metodă (>> =). Și orice se întâmplă, rezultatul va rămâne întotdeauna în același monad (chiar dacă nu reușește, nu reușește).

Monadele sunt foarte asemănătoare. >> = ia calculul interior din monada din stânga și îl înlocuiește în calculul din dreapta, care ar trebui să creeze întotdeauna o altă monadă de același tip.

În majoritatea limbilor, returul returnează rezultatul calculului din funcție. În Haskell, el este un designer pentru monade. Acest lucru este foarte ciudat. Cu toate acestea, să vedem cum funcționează >>. această operație readuce valoarea din monad pe stânga și apoi o asociază cu argumentul funcției în dreapta (de aici, apropo, un alt nume de metodă se leagă). Și funcția din dreapta ar trebui să returneze valoarea înapoi la monadă, astfel încât să fie posibilă trecerea bastonului dincolo de următoarea operație >> =. Aceasta este prima regulă mnemonică: întoarcere - returnează valoarea calculată înapoi la monad.

Al doilea mnemonic. Funcția de nivel superior a oricărui program de pe Haskell este executată în monada IO (tipul funcției principale este IO ()). Acest monad vă permite să efectuați I / O și, în general, orice acțiuni secvențiale. Astfel, codul monadic este executat la cel mai înalt nivel al programului și numește orice cod "curat" după cum este necesar și nu invers. Astfel, orice valoare "pură", dacă nu este aruncată, devine mai devreme sau mai târziu moneda care a numit-o.

Sper că după aceste explicații numele de returnare al constructorului monadic nu mai pare ciudat. Cu toate acestea, nu susțin că explicațiile mele sunt 100% corecte din punct de vedere tehnic.


Concluzie privind monadele

Deci, legarea (>> =) vă permite să combinați împreună diferite calcule monadice. Aproape peste tot, unde există un lanț de calcule, monadele sunt foarte potrivite. Implementările concrete ale monazelor pot conține reguli diferite pentru combinarea calculelor. Numele metodei de întoarcere confundă începătorii, această metodă returnează rezultatul calculului înapoi la monadă, și nu la monad. În general, când am înțeles aceste idei simple, acest lucru a ajutat foarte mult.

5. Cuvintele înfricoșătoare

Știu doar că nu știu nimic.

Chiar și luni de fapt, am început să învețe Haskell, fiind capabil să scrie unele programe utile pe el, eu văd în jurul valorii de Haskell în lume, încă multe concepte, care nu știu nimic sau au doar o idee foarte vagă. Eu numesc astfel de concepte "cuvinte teribile". Și văd că există oameni care creează și folosesc biblioteci care întruchipează aceste concepte în viață.

Desigur, Haskell rămâne terenul de testare pentru cercetători. Și este atât bun și rău. Asta e bine, pentru că dă sentimentul că marginea de taiere a științei și tehnologiei este foarte aproape, și puteți lua în mod opțional profite de noi abordări. Dacă doriți. Și, în același timp, este un lucru rău, pentru că, uneori, atunci când doriți să utilizați o nouă bibliotecă elegantă, se pare că ea este în mod activ, folosind idei necunoscute și nu foarte clare, iar noi trebuie să fim pregătiți pentru a dezvolta aceste idei.

De exemplu, există o bibliotecă XML modernă HXT. Folosește o mulțime de săgeți. Săgețile sunt computere de calcul mai versatile decât monadele, dar mi-a luat mult mai mult decât o zi pentru a le înțelege mai mult sau mai puțin. Strict vorbind, săgețile nu fac parte din limbă, dar sunt un concept pe care utilizatorii acestei limbi le folosesc. Și există multe astfel de exemple. Deși cei care nu doresc să învețe săgeți, puteți utiliza o HaXml bibliotecă XML mai tradițională și activă.

Cred că este important să nu vă fie frică de "cuvinte teribile". Din fericire, ideile de bază sunt bine descrise. De regulă, există articole care le explică în detaliu. Eu însumi am decis să stăpânesc astfel de idei, după cum este necesar. Se promite că este atât fascinantă, cât și fezabilă.

concluzie

Am enumerat cinci idei simple, după ce le-am stăpânit, mi-a devenit mai ușor să mă obișnuiesc cu Haskell. Lambdas sunt doar o modalitate de scriere a funcțiilor, iar funcțiile mai multor argumente pot fi întotdeauna scrise ca o funcție a uneia, returnând o altă funcție. Tipurile de clase sunt foarte asemănătoare cu interfețele polimorfe abstracte în abordarea orientată pe obiecte. Monadele sunt un mod standardizat de conectare a calculilor împreună. Cuvintele teribile - doar cuvinte groaznice. Puteți trăi fără ei, dar este plictisitor.

Sper că notele mele vor fi utile pentru altcineva.







Articole similare

Trimiteți-le prietenilor: