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:l05 [2019/03/24 15:41]
dmihai
pp:l05 [2020/02/05 15:50] (current)
dmihai [Exerciții]
Line 81: Line 81:
 O **clasă de tipuri** (**typeclass**) este o colecție de funcții care specifică un comportament. Un tip de date poate fi //​înrolat//​ într-o clasă, furnizând implementări ale funcțiilor,​ particularizate pentru acest tip.  O **clasă de tipuri** (**typeclass**) este o colecție de funcții care specifică un comportament. Un tip de date poate fi //​înrolat//​ într-o clasă, furnizând implementări ale funcțiilor,​ particularizate pentru acest tip. 
  
-<​note ​warning>+<​note ​important>
 În ciuda numelui, clasele Haskell nu corespund claselor din limbaje de programare orientate pe obiecte (e.g. Java, C%%+%%%%+%%). Clasele Haskell //nu conțin date// și //nu pot fi instanțiate//​. O comparație mai pertinentă este cu interfețele din Java. În ciuda numelui, clasele Haskell nu corespund claselor din limbaje de programare orientate pe obiecte (e.g. Java, C%%+%%%%+%%). Clasele Haskell //nu conțin date// și //nu pot fi instanțiate//​. O comparație mai pertinentă este cu interfețele din Java.
 </​note>​ </​note>​
Line 225: Line 225:
     Empty == Empty = True     Empty == Empty = True
     (Cons a as) == (Cons b bs) = (a == b) && (as == bs)     (Cons a as) == (Cons b bs) = (a == b) && (as == bs)
 +    _ == _ = False
 </​code>​ </​code>​
  
-Primul rând exprimă ideea că putem compara ​două liste //de același tip// (''​List a''​),​ doar dacă //​elementele lor sunt comparabile// (''​(Eq a) =%%>​%%''​).+Primul rând exprimă ideea că putem egala două liste //de același tip// (''​List a''​),​ doar dacă //​elementele lor sunt egalabile// (''​(Eq a) =%%>​%%''​).
  
 Observați că, în expresia celui de-al doilea caz, funcția ''​==''​ apare de două ori: o dată pentru a compara elemente, o dată pentru a compara liste. Acesta este un exemplu de **polimorfism ad hoc**. Cele două apeluri de ''​==''​ pot avea implementări diferite (al doilea este mereu un apel recursiv; primul poate fi, de exemplu, comparație între doi întregi, în cazul ''​List Int''​). Observați că, în expresia celui de-al doilea caz, funcția ''​==''​ apare de două ori: o dată pentru a compara elemente, o dată pentru a compara liste. Acesta este un exemplu de **polimorfism ad hoc**. Cele două apeluri de ''​==''​ pot avea implementări diferite (al doilea este mereu un apel recursiv; primul poate fi, de exemplu, comparație între doi întregi, în cazul ''​List Int''​).
Line 282: Line 283:
  
 <​note>​ <​note>​
-Respectarea strictă a tuturor legilor unei clase are excepții. De exemplu, pentru operațiile în virgulă mobilă, o valoare specială [[https://​en.wikipedia.org/​wiki/​NaN|NaN (Not a Number)]] modelează rezultatul anumitor expresii cu rezultat nedefinit. Două valori ''​NaN''​ nu sunt considerate egale; prin urmare, pentru tipuri ca ''​Float''​ și ''​Double'',​ operația ''​==''​ nu respectă proprietatea de reflexivitate:​+Respectarea strictă a tuturor legilor unei clase are excepții. De exemplu, pentru operațiile în virgulă mobilă, o valoare specială [[https://​en.wikipedia.org/​wiki/​NaN|NaN (Not a Number)]] modelează rezultatul anumitor expresii cu rezultat nedefinit. Două valori ''​NaN''​ nu sunt considerate egale; prin urmare, pentru tipuri ca ''​Float''​ și ''​Double'',​ operația ''​==''​ nu respectă proprietatea de reflexivitate ​pe întreg domeniul:
  
 <​code>​ <​code>​
Line 293: Line 294:
 ===== Exerciții ===== ===== Exerciții =====
  
-1. În [[pp:​l04|laboratorul anterior]], ați definit ​un tip pentru a modela numerele naturale extinse cu un punct la infinit, precum și niște ​operații ​pe acestea. Dorim să facem implementarea elegantă, pentru a putea folosi operatori deja existenți ​(e.g. ''​=='' ​pentru comparare) și pentru a putea folosi alte funcții existente care impun constrângeri de tip (e.g. ''​Data.List.sort :: Ord a =%%>%% [a] -%%>%% [a]''​). ​Astfel, ne dorim să înrolăm ​tipul de date în următoarele clase:+1. Înrolați tipul ''​List a''​ în clasa ''​Show'',​ astfel încât șirul rezultat să fie identic cu cel pentru listele Haskell: 
 +   
 +<​code>​ 
 +*Main> Cons 1 (Cons 2 (Cons 3 Empty)) 
 +[1,2,3] 
 +</​code>​ 
 +   
 +2. În [[pp:​l04|laboratorul anterior]], ați definit operații (''​foldrT''​''​mapT'' ​etc.pentru lucrul cu arbori binari polimorficiAm vrea să înrolăm ​acest tip la clasele corespunzătoare.
  
-  * Show (astfel încât ​să afișăm numerele fără ​a fi precedate de vreun nume de constructor,​ iar infinitul ca "​Inf"​) +a. înrolați ''​BTree a''​ în ''​Eq''​ 
-  ​* ​Eq + 
-  ​* ​Ord +b. înrolați ''​BTree''​ în ''​Foldable''​ și definiți ''​foldr''​ cu aceeași definiție ca ''​foldrT''​ din laboratorul trecut; veți avea apoi acces la funcții ca ''​foldl'',​ ''​sum'',​ ''​minimum''​ ('':​info Foldable''​ în ''​ghci''​ pentru a le vedea pe toate) 
-  ​* ​Num+ 
 +c. înrolați ''​BTree''​ în ''​Functor''​ și definiți ''​fmap''​ cu aceeași definiție ca ''​mapT''​ din laboratorul trecut (mai multe informații [[https://​wiki.haskell.org/​Functor|aici]]) 
 + 
 +<note important>​ 
 +Atenție la tipurile ''​foldr''​ și ''​fmap'':​ 
 + 
 +<​code>​ 
 +Prelude> :t foldr 
 +foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b 
 +Prelude> :t fmap 
 +fmap :: Functor f => (a -> b) -> f a -> f b 
 +</​code>​ 
 + 
 +Observați că constrângerile sunt puse pe //​constructorul de tip//, deci va trebui înrolat ''​BTree'',​ nu ''​BTree a''​. 
 +</​note>​ 
 + 
 +3. Tot în [[pp:​l04|laboratorul anterior]], ați definit un tip pentru a modela numerele naturale extinse cu un punct la infinit, precum și niște operații pe acestea. Dorim să facem implementarea elegantă, pentru a putea folosi operatori deja existenți (e.g. ''​==''​ pentru comparare) și pentru a putea folosi alte funcții existente care impun constrângeri de tip (e.g. ''​Data.List.sort :: Ord a =%%>%% [a] -%%>%% [a]''​). Înrolați tipul ''​Extended''​ în clasele: 
 + 
 +a. ''​Show'' ​(a.î. să afișăm numerele fără vreun nume de constructor,​ iar infinitul ca "​Inf"​) 
 + 
 +b. ''​Eq''​ 
 + 
 +c. ''​Ord''​ 
 + 
 +d. ''​Num''​ 
 + 
 +4. Definiți un tip de date polimorfic care să modeleze următoarea gramatică (în care o valoare poate avea orice tip):
  
-2. Definiți un tip de date asociat următoarei gramatici: 
 <​code>​ <​code>​
    <​expr>​ ::= <​value>​ | <​variable>​ | <​expr>​ + <​expr>​ | <​expr>​ * <​expr> ​    <​expr>​ ::= <​value>​ | <​variable>​ | <​expr>​ + <​expr>​ | <​expr>​ * <​expr> ​
 </​code>​ </​code>​
-unde o valoare poate avea orice tip. 
  
-3Considerăm următorul constructor ​de tip:+5Amintiți-vă de tabelele asociative din laboratorul trecut. Vom defini un "​dicționar"​ ca fiind o tabelă asociativă cu șiruri ​de caractere drept chei: 
 <code haskell> <code haskell>
 type Dictionary a = [(String, a)] type Dictionary a = [(String, a)]
 </​code>​ </​code>​
-care modeleaza //​dicționare//​ - mapări de tip "​nume-variabilă"​-"​valoare polimorfica"​ 
  
-Definiți funcția: +Ne mai interesează și funcția ​care primește o cheie și o tabelă asociativă și întoarce valoarea asociată cheii, împachetată într-un ''​Maybe''​: 
-<​code>​valueof ​:: Dictionary a -> String ​-> Maybe a</​code>​ + 
-care intoarce valoarea asociata unui nume-variabilă, dintr-un dicționar+<​code ​haskell> 
 +getValue ​:: String -> Dictionary a -> Maybe a 
 +</​code>​ 
 + 
 +Fie următoarea clasă:
  
-4. Definiți următoarea clasă: 
 <code haskell> <code haskell>
 class Eval t a where class Eval t a where
Line 325: Line 360:
  
 <​note>​ <​note>​
-Acest tip de clasă reprezintă o extensie a limbajului, **Multi-parameter type-class**. ​ Cel mai probabil este nevoie de următoarele directive pentru a o defini și pentru a înrola tipuri la ea:+Acest tip de clasă reprezintă o extensie a limbajului, **Multi-parameter type-class**. ​ Cel mai probabil este nevoie de următoarele directive ​//la începutul fișierului// ​pentru a o defini și pentru a înrola tipuri la ea (directivele se găsesc deja în scheletul de laborator):
  
 <code haskell> <code haskell>
Line 332: Line 367:
  
 class Eval t a where class Eval t a where
-    eval :: Dictionary a -> t a -> Result ​a+    eval :: Dictionary a -> t a -> Maybe a
 </​code>​ </​code>​
  
Line 338: Line 373:
 </​note>​ </​note>​
  
-5. Înrolați ''​Expr''​ și ''​Integer''​ în clasa ''​Eval''​. Care este semnificația evaluării?​ +a. Înrolați ''​Expr''​ și ''​Integer''​ în clasa ''​Eval''​. Care este semnificația evaluării?\\ 
- +bînrolați ''​Expr''​ și ''​Extended''​ în clasa ''​Eval''​.\\ 
-6Înrolați ''​Expr''​ și ''​FIFO a''​ în clasa ''​Eval''​. ​Semnificația înmulțirii este //​concatenarea//​ a două FIFO.  +cCe observați? Cum ați putea simplifica?
- +
-===== Alte exerciții ===== +
- +
-1Ați definit, în laboratorul anterior, tipurile polimorfice ''​List ​a''​ ș''​Tree a''​. Pentru le putea reprezenta, ați folosit implementarea implicită a funcției ''​show'',​ oferită de ''​deriving (Show)''​. Aceasta nu era însă o reprezentare citibilă. +
- +
-Ne dorim să reprezentăm tipul listă, la fel ca cel existent în Haskell: +
- +
-<​code>​ +
-Prelude> show (Cons 1 (Cons 2 (Cons 3 Nil))) +
-[1,2,3] +
-</​code>​ +
- +
-(Pentru arbori există multe reprezentări posibile, puteți alege orice reprezentare preferați). +
- +
-2. Înrolați aceleași tipuri în clasa ''​Eq''​. +
- +
-3. Implementați sortarea pentru ''​List a'',​ unde ''​a''​ e un tip oarecare înrolat în clasa ''​Ord''​. +
-  +
-4. Implementați căutarea binară pentru ''​Tree a'',​ unde ''​a''​ e un tip oarecare înrolat în clasa ''​Ord''​. +
- +
-5. Înrolați tipurile de date ''​List''​ și ''​Tree''​ în clasa ''​Functor''​.+
  
-===== Resurse ​=====+{{:​pp:​lab5_-_schelet.zip|Lab 5 - Schelet}}\\ 
 +===== Recommended Reading ​=====
  
-  ​* [[https://​www.haskell.org/​tutorial/​classes.html|Type Classes and Overloading - Haskell wiki]] +  * [[http://​learnyouahaskell.com/​types-and-typeclasses#​typeclasses-101|Learn you a Haskell for Great Good - Chapter 2: Types and Typeclasses#​Typeclasess ​101]]\\ 
-  * [[https://​wiki.haskell.org/​Typeclassopedia|Typeclassopedia - Haskell wiki]] +  * [[http://​learnyouahaskell.com/​making-our-own-types-and-typeclasses#​typeclasses-102|Learn you a Haskell for Great Good - Chapter 8: Making Our Own Types and Typeclasses#​Typeclasess ​102]]\\ 
-  ​* [[http://​learnyouahaskell.com/​types-and-typeclasses#​typeclasses-101|Typeclasses 101 - Learnyouahaskell]] +  * [[http://​book.realworldhaskell.org/​read/​using-typeclasses.html|Real World Haskell - Chapter 6: Using Typeclasses]]\\ 
-  * [[http://​learnyouahaskell.com/​making-our-own-types-and-typeclasses#​typeclasses-102|Typeclasses 102 - Learnyouahaskell]]+  * [[https://​www.haskell.org/​tutorial/​stdclasses.html|A Gentle Introduction to Haskell - Chapter 8: Standard Haskell Classes]]