====== Aplicații cu funcții de ordin superior ====== Responsabili laborator: * [[mihai.dumitru@cti.pub.ro|Dumitru Mihai-Valentin]] * [[calin.cruceru@cti.pub.ro|Călin Cruceru]] Scopul laboratorului este de a exersa lucrul cu funcții de ordin superior. ===== Recapitulare ===== O **funcție de ordin superior** este //o funcție care primește ca argument sau returnează o funcție//. applyTwice f x = f (f x) adder x = (+x) ==== Folduri ==== Două funcții de ordin superior foarte importante sunt foldurile pe liste: ''foldl'' și ''foldr''. Aceasta combină, în mod recursiv, elementele unei liste cu o valoare default, pentru a obține un rezultat. foldr (:) [] l -- intoarce o lista identica cu l foldl (flip (:)) [] l -- intoarce inversul listei l O variantă importantă a lui ''foldl'' este ''foldl%%'%%'', care se găsește în modulul ''Data.List''. Prelude> import Data.List Prelude Data.List> :t foldl' foldl' :: (a -> b -> a) -> a -> [b] -> a Puteți citi [[https://wiki.haskell.org/Foldr_Foldl_Foldl'|aici]] despre diferențele dintre aceste trei folduri. O vizualizare utilă: {{:laboratoare:fold-visualization.png?800|}} Tipurile acestor funcții sunt: Prelude> :t foldr foldr :: (a -> b -> b) -> b -> [a] -> b Prelude> :t foldl foldl :: (a -> b -> a) -> a -> [b] -> a Nu trebie să rețineți pe de rost tipurile. Încercați să înțelegeți ce exprimă și de ce sunt așa. Alte funcții de ordin superior des întâlnite: ''map'', ''filter'', ''zipWith'', ''flip''. ===== Exerciții ===== 1. Fie două matrici reprezentate ca liste de liste. În rezolvarea exercițiilor de mai jos, puteți folosi doar funcții de ordin superior (împreună cu ''take'' și ''drop''). Implementați funcții care să returneze: * linia ''i'' dintr-o matrice * elementul ''(i, j)'' dintr-o matrice * suma a două matrici * transpusa unei matrici * produsul a două matrici 2. O imagine poate fi reprezentată ca o matrice de caractere (numiți, în continuare, "pixeli"). Considerăm că avem trei tipuri de pixeli: ''%%'%%.%%'%%'', ''%%'%%*%%'%%'', ''%%'%% %%'%%'' Implementați următoarele funcții: * flip orizontal, flip vertical, rotație de 90 în sens trigonometric și invers trigonometric * negativul (''%%'%%*%%'%%'' si ''%%'%%.%%'%%'' devin ''%%'%% %%'%%'', iar ''%%'%% %%'%%'' devine ''%%'%%*%%'%%'') * scalarea unei imagini cu ''x'' unități * alipirea a două imagini (cu aceeași înălțime) pe orizontală * alipirea a două imagini (cu aceeași lungime) pe verticală * crop orizontal de la de la coloana ''x'' la coloana ''y'' * crop vertical de la linia ''x'' la linia ''y'' * Implementați suprapunerea unei imagini peste o alta (având aceeași dimensiune) ===== Resurse ====== Puteți folosi următoarea imagine pentru a vă testa funcțiile. l1=" ***** ** ***** ** " l2=" ****** **** ****** **** " l3=" ** * * *** ** * * *** " l4=" * * * *** * * * *** " l5=" * * ** * * ** " l6=" ** ** ** ** ** ** " l7=" ** ** ** ** ** ** " l8=" **** ** * **** ** * " l9=" * *** ** * * *** ** * " l10=" ** ******* ** ******* " l11=" ** ****** ** ****** " l12=" ** ** ** ** " l13=" ** ** ** ** " l14=" ** ** ** ** " l15=" ** ** ** ** ** ** " l16="*** * * *** * * " l17=" *** * *** * " l18=" ****** ****** " l19=" *** *** " img = [l1,l2,l3,l4,l5,l6,l7,l8,l9,l10,l11,l12,l13,l14,l15,l16,l17,l18,l19] ===== Solutii laborator ==== - [[https://github.com/Programming-Paradigms/Labs/archive/master.zip | Solutii laborator 3]] - Puteți, alternativ, să folosiți următorul repository git [[https://github.com/Programming-Paradigms/Labs]] pentru a descărca soluțiile și a le sincroniza, ulterior.