Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
pp:hoogle [2019/03/03 16:56]
dmihai [Anatomia unui rezultat]
pp:hoogle [2019/04/12 14:49] (current)
dmihai [Căutare după tip]
Line 3: Line 3:
 [[https://​www.haskell.org/​hoogle/​|Hoogle]] este un motor de căutare pentru funcții, tipuri, clase etc. de Haskell. Puterea sa constă în abilitatea de a căuta funcții atât după nume cât și după tip. [[https://​www.haskell.org/​hoogle/​|Hoogle]] este un motor de căutare pentru funcții, tipuri, clase etc. de Haskell. Puterea sa constă în abilitatea de a căuta funcții atât după nume cât și după tip.
  
-====== Căutare după nume =====+==== Căutare după nume ====
  
 Considerați că tocmai ați auzit de funcția Haskell ''​scanl'',​ dar nu știți ce face. Căutând numele pe Hoogle (https://​www.haskell.org/​hoogle/?​hoogle=scanl) obțineți o listă de rezultate similare; observați că hoogle face matching parțial și vă găsește și funcții numite ''​scanl1''​. Considerați că tocmai ați auzit de funcția Haskell ''​scanl'',​ dar nu știți ce face. Căutând numele pe Hoogle (https://​www.haskell.org/​hoogle/?​hoogle=scanl) obțineți o listă de rezultate similare; observați că hoogle face matching parțial și vă găsește și funcții numite ''​scanl1''​.
Line 11: Line 11:
 </​note>​ </​note>​
  
-===== Anatomia unui rezultat ​=====+==== Anatomia unui rezultat ====
  
 {{:​pp:​hoogle-scanl-result.png|}} {{:​pp:​hoogle-scanl-result.png|}}
Line 18: Line 18:
   * pe prima linie este numele complet al funcției, urmat de tipul funcției   * pe prima linie este numele complet al funcției, urmat de tipul funcției
     * click pe numele sau pe tipul funcției vă va duce la descrierea completă a acesteia din cadrul pachetului în care e definită     * click pe numele sau pe tipul funcției vă va duce la descrierea completă a acesteia din cadrul pachetului în care e definită
-  * următoarea linie (cu verde) conține o listă separată cu virgulă de forma "​pachet modul-din-pachet"​ în care se găsește funcția (nu e necesar să înțelegeți bine noțiunile de "​pachet"​ și de "​modul";​ vă veți uita în principal ​după funcții care conțin ''​base Prelude''​)+  * următoarea linie (cu verde) conține o listă separată cu virgulă de forma "​pachet modul-din-pachet"​ în care se găsește funcția (nu e necesar să înțelegeți bine noțiunile de "​pachet"​ și de "​modul"; ​cel mai des vă veți uita după funcții care conțin ''​base Prelude''​)
   * următoarea linie conține o descriere a comportamentului funcției; butonul ''​+''​ de la începutul rândului expandează acest câmp, dacă descrierea este lungă   * următoarea linie conține o descriere a comportamentului funcției; butonul ''​+''​ de la începutul rândului expandează acest câmp, dacă descrierea este lungă
  
Line 32: Line 32:
  
 <note tip> <note tip>
-acumulatorul e 0; +întâi ​0, acumulatorul\\ 
-apoi 14, rezultatul operației (0 + 14); +apoi 14, rezultatul operației (0 + 14)\\ 
-apoi 42, rezultatul operației (14 + 28);+apoi 42, rezultatul operației (14 + 28)\\  ​
 apoi 44, rezultatul operației (42 + 2) apoi 44, rezultatul operației (42 + 2)
 +</​note>​
 +
 +==== Căutare după tip ====
 +
 +Când scrieți cod (indiferent de limbaj), veți ajunge des în situația în care aveți nevoie de un anumit comportament;​ vreți să găsiți o funcție despre care știți ce ați vrea să facă, însă nu știți cum s-ar putea numi. Ar fi util să existe o implementare pentru această funcție în biblioteca standard; astfel vă scutiți de timpul de dezvoltare a funcției și aveți garanția unei implementări robuste, testată de mulți. Hoogle vă ajută să o găsiți, dacă există.
 +
 +=== Exemplu === 
 +
 +Aveți de rezolvat următoarea problemă: se dă o listă de numere întregi; trebuie să o rearanjați astfel încât toate numerele pare să se afle la începutul listei, urmate de toate numerele impare.
 +
 +<​code>​
 +[1, 2, 3, 4] -> [2, 4, 1, 3]
 +[44, 2, 13, 8, 77] -> [44, 2, 8, 13, 77]
 +[11, 1, 3, 9, 2] -> [2, 11, 1, 3, 9]
 +</​code>​
 +
 +Pentru acest task, cel mai util ar fi să existe o funcție care face exact asta; din păcate aceasta nu se găsește în biblioteca standard Haskell.
 +Gândidu-ne la ce ne-ar fi de folos, putem ajunge la ideea că ne dorim o funcție care primește un predicat și o listă de întregi și ne întoarce un tuplu de două liste: elementele pentru care predicatul ține și restul. Funcția ar avea semnătura:
 +
 +<code haskell>
 +(Int -> Bool) -> [Int] -> ([Int], [Int])
 +</​code>​
 +
 +Căutând acest tip pe hoogle, găsim 3 rezultate!\\
 +https://​www.haskell.org/​hoogle/?​hoogle=%28Int+-%3E+Bool%29+-%3E+%5BInt%5D+-%3E+%28%5BInt%5D%2C+%5BInt%5D%29
 +
 +Observăm că rezultatele nu au exact tipul dat de noi. Tipul la care ne-am gândit a fost mai restrictiv decât necesar, biblioteca standard oferindu-ne o soluție pentru liste de orice tip generic ''​a'';​ hoogle a fost însă în stare să le găsească.
 +
 +Dar ordinea parametrilor?​ Ce s-ar fi întâmplat dacă am fi căutat o funcție care primește întâi o listă, apoi predicatul?​\\
 +https://​www.haskell.org/​hoogle/?​hoogle=%5BInt%5D+-%3E+%28Int+-%3E+Bool%29+-%3E+%28%5BInt%5D%2C+%5BInt%5D%29
 +
 +Aceleași rezultate! Hoogle reușește să găsească ce ne dorim chiar și în ciuda ordinii greșite a parametrilor.
 +
 +Acum nu ne mai rămâne decât să citim descrierile funcțiilor găsite (''​break'',​ ''​span'',​ ''​partition''​). Observăm că ''​partition''​ are comportamentul dorit. Hoogle ne arată faptul că această funcție se află în modulul ''​Data.List'',​ care trebuie importat:
 +
 +<​code>​
 +Prelude> :m + Data.List
 +Prelude Data.List>​ partition even [1..10]
 +([2,​4,​6,​8,​10],​[1,​3,​5,​7,​9])
 +Prelude Data.List>​
 +</​code>​
 +
 +Concatenând cele două liste, obținem soluția problemei inițiale:
 +
 +<code haskell>
 +import Data.List
 +
 +evensFirst l = let (e, o) = partition even l
 +               in e ++ o
 +</​code>​
 +
 +<note tip>
 +Am putea scrie o expresie mai scurtă, folosindu-ne de compunere de funcții? Funcția ''​partition''​ întoarce un tuplu, dar funcția de concatenare (''​++''​) primește pe rând două argumente - este curried. Putem rezolva problema, folosindu-ne de ''​uncurry''​.
 +
 +
 +<code haskell>
 +import Data.List
 +
 +evensFirst = uncurry (++) . partition even
 +</​code>​
 +
 +Funcția ''​uncurry (++)''​ are tipul ''​([a],​ [a]) -%%>%% [a]''​.
 </​note>​ </​note>​