User Tools

Site Tools


laboratoare:02-functii-de-ordin-superior

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
laboratoare:02-functii-de-ordin-superior [2016/03/06 22:35]
mihai.dumitru2201 [Funcții anonime]
laboratoare:02-functii-de-ordin-superior [2016/03/06 23:34] (current)
mihai.dumitru2201
Line 16: Line 16:
 Pentru a înțelege importanța lor, vom da următorul exemplu: ne propunem să scriem două funcții care primesc o listă și returnează,​ într-o nouă listă Pentru a înțelege importanța lor, vom da următorul exemplu: ne propunem să scriem două funcții care primesc o listă și returnează,​ într-o nouă listă
   * toate elementele pare   * toate elementele pare
-  * toate elementele mai mari ca 10+  * toate elementele mai mari decât ​10
  
 <code haskell> <code haskell>
Line 71: Line 71:
 ===== Currying vs. uncurrying =====  ​ ===== Currying vs. uncurrying =====  ​
  
-Currying ​este o tehnică ​(numită după [[https://​en.wikipedia.org/​wiki/​Haskell_Curry|tizul Haskell-ului]]) prin care, dintr-o funcție care ia mai multe argumente, se obține o secvență de funcții care iau un singur argument.+Currying (numit după [[https://​en.wikipedia.org/​wiki/​Haskell_Curry|tizul Haskell-ului]]) ​este procesul ​prin care, dintr-o funcție care ia mai multe argumente, se obține o secvență de funcții care iau un singur argument.
  
-De exemplu, dintr-o funcție de două argumente ''​f : X × Y → Z''​ se obține o funcție ''​curry(f) : X → (Y → Z)''​. Noua funcție ''​curry(f)''​ primește un argument de tipul ''​X''​ și întoarce o funcție de tipul ''​Y → Z''​ (adică o funcție care primește un argument de tipul ''​Y''​ și întoarce un rezultat de tip ''​Z''​). Considerând operatorul ''​→''​ asociativ la dreapta, putem omite parantezele,​ i.e. ''​curry(f) : X → Y → Z''​.+De exemplu, dintr-o funcție de două argumente ''​f : X × Y → Z''​ se obține o funcție\\ 
 +''​curry(f) : X → (Y → Z)''​. Noua funcție ''​curry(f)''​ primește un argument de tipul ''​X''​ și întoarce o funcție de tipul ''​Y → Z''​ (adică o funcție care primește un argument de tipul ''​Y''​ și întoarce un rezultat de tip ''​Z''​). Considerând operatorul ''​→''​ asociativ la dreapta, putem omite parantezele,​ i.e. ''​curry(f) : X → Y → Z''​.
  
 Operația inversă se numește "​uncurry":​ ''​f : X → Y → Z,   ​uncurry(f):​ X × Y → Z''​. Operația inversă se numește "​uncurry":​ ''​f : X → Y → Z,   ​uncurry(f):​ X × Y → Z''​.
 +
 +Întorcându-ne la funcția de filtrare definită mai devreme, care este tipul ei?
 +
 +<​code>​
 +*Main> :t myFilter
 +myFilter :: (a -> Bool) -> [a] -> [a]
 +</​code>​
 +
 +Și în [[laboratoare:​01-functii-recursive#​definirea_unei_functii|laboratorul trecut]], am observat că nu există o separare între domeniu și codomeniu, de genul\\
 +''​(a -%%>%% Bool) x [a] -%%>%% [a]''​.
 +
 +<note important>​
 +Acest lucru se datorează faptului că, în Haskell, **toate funcțiile iau un singur argument**. Alternativ, putem spune despre ele că sunt //​curried//​.
 +
 +Tipul funcției noastre trebuie interpretat astfel:\\
 +primește ca argument o funcție de tipul ''​a -%%>%% Bool''​ (ia un argument și întoarce o booleană) și întoarce o funcție de tipul ''​[a] -%%>%% [a]''​ (ia o listă și întoarce o listă de același tip).
 +
 +De aceea, în exemplul de mai sus am putut definit ''​evenElements''​ (o funcție care ia o listă și returnează o listă) ca fiind ''​myFilter even''​ care are exact acest tip, i.e. ''​[a] -%%>%% [a]''​.
 +</​note>​
 +
 +<​note>​
 +Haskell pune la dispoziție funcțiile ''​curry''​ și ''​uncurry''​. ​
 +
 +<​code>​
 +*Main> :t curry
 +curry :: ((a, b) -> c) -> a -> b -> c
 +*Main> :t uncurry
 +uncurry :: (a -> b -> c) -> (a, b) -> c
 +</​code>​
 +
 +Funcțiile primite, respectiv returnate de ''​curry''​ și ''​uncurry''​ iau tot un singur argument, numai că acesta este un tuplu.
 +
 +<​code>​
 +*Main> let evenElements = (uncurry myFilter) even
 +
 +<​interactive>:​12:​39:​
 +    Couldn'​t match expected type `(a0 -> Bool, [a0])'
 +                with actual type `a1 -> Bool'
 +    In the second argument of `uncurry',​ namely `even'
 +    In the expression: (uncurry myFilter) even
 +    In an equation for `evenElements':​
 +        evenElements = (uncurry myFilter) even
 +*Main> let evenElements l = (uncurry myFilter) (even, l)
 +*Main>
 +</​code>​
 +
 +</​note>​
  
 ===== Funcții anonime ===== ===== Funcții anonime =====
Line 96: Line 144:
 multiplesOf5 = myFilter (\x -> x `mod` 5 == 0) multiplesOf5 = myFilter (\x -> x `mod` 5 == 0)
 </​code>​ </​code>​
 +
 +Următoarele expresii sunt echivalente:​
 +
 +<code haskell>
 +f x y = x + y
 +f x = \y -> x + y
 +f = \x y -> x + y
 +</​code>​
 +
 +<​note>​
 +Nu există vreo diferență între ''​\x y -%%>%% x + y''​ și ''​\x -%%>%% \y -%%>%% x + y''​.
 +</​note>​
 +
 ===== Combinatori și închideri funcționale ===== ===== Combinatori și închideri funcționale =====
  
laboratoare/02-functii-de-ordin-superior.1457296540.txt.gz · Last modified: 2016/03/06 22:35 by mihai.dumitru2201