import Data.List import Data.Maybe --- Clasa Eq -- TDA: Unordered List newtype UList a = UList [a] -- ex: Instanțiere Eq pentru (UList a) a. î. să conteze numărul de apariții, dar nu ordinea -- Hint: nub instance Eq a => Eq (UList a) where UList a == UList b = (length a == length b) && all (\x -> freq x a == freq x b) (nub a) where freq x a = length $ filter (==x) a --- Clasa Ord type Name = (String, String) names :: [Name] names = [("Frederic","Chopin"), ("Antonio","Vivaldi"), ("Maurice","Ravel")] -- ex: O funcție care sortează lista după nume, nu după prenume -- Hint: :t sortBy sortByLastName :: [Name] -> [Name] sortByLastName = sortBy (\(f1, l1) (f2, l2) -> compare (l1, f1) (l2, f2)) -- Pot institui această relație de ordine și pentru alte operații (ex: <, >)? -- TDA Ordered Name newtype OName = OName Name deriving (Show, Eq) instance Ord OName where OName (f1, l1) <= OName (f2, l2) = (l1, f1) <= (l2, f2) oNames = map OName names --- Clasa Show {- ex: Supraîncărcați afișarea funcțiilor unare cu parametru numeric, astfel: - o funcție se afișează ca listă de 6 perechi: - fst: numerele de la 0 la 5 - snd: valoarea funcției în aceste puncte ex: show (*2) = "[(0,0),(1,2),(2,4),(3,6),(4,8),(5,10)]" -} instance (Num a, Enum a, Show a, Show b) => Show (a -> b) where show f = show [ (x, f x) | x <- [0 .. 5] ] --- Clasa Enum data Day = Mon | Tue | Wed | Thu | Fri | Sat | Sun deriving (Eq, Ord, Show) days = [Mon, Tue, Wed, Thu, Fri, Sat, Sun] -- ex: Instanțiere Enum pentru Day, astfel încât succ Sun = Mon instance Enum Day where fromEnum day = fromJust $ lookup day $ zip days [0 ..] toEnum n = fromJust $ lookup (n `mod` 7) $ zip [0 ..] days --- Clasa Bounded -- ex: O clasă CyclicEnum care ciclează pentru funcțiile prev și next: -- prev minim = maxim, next maxim = minim class (Enum t, Bounded t, Eq t) => CyclicEnum t where prev, next :: t -> t prev x = if x == minBound then maxBound else pred x next x = if x == maxBound then minBound else succ x instance CyclicEnum Bool --------------------Containere class Container t where contents :: t a -> [a] instance Container [] where -- [a]; [a] ~ [] a contents = id data List a = Nil | Cons a (List a) deriving Show --ex: instanțierea clasei Container cu constructorul List (pt tipul List a) instance Container List where contents Nil = [] contents (Cons x xs) = x : contents xs -- ex: instanțierea cu Maybe instance Container Maybe where contents Nothing = [] contents (Just x) = [x] --ex: instanțierea clasei Functor cu constructorul List (pt tipul List a) instance Functor List where fmap _ Nil = Nil fmap f (Cons x xs) = Cons (f x) (fmap f xs) --ex: instanțierea clasei Foldable cu constructorul List (pt tipul List a) instance Foldable List where foldr _ acc Nil = acc foldr f acc (Cons x xs) = f x $ foldr f acc xs -- fmap :: (a -> b) -> f a -> f b (întoarcem un container cu valorile din container transformate) -- exemplu: instance Functor [] -- [1,2,3] :: [a] => fiecare valoare din listă este o valoare închisă în container, deci toate trebuie supuse transformării --instance Functor Maybe ex1 = fmap (+1) (Just 5) -- Just {5} :: Maybe a => Just (5+1) = Just 6 --instance Functor ((->) r) ex2 = fmap (+1) (+1) 2 -- \x -> {x+1} :: (->) a b => -- fmap (+1) (\x -> {x+1}) = \x -> x+2 => -- 4 --instance Functor ((,) a) ex3 = fmap (+1) (1,2) -- (1,{2}) :: (,) a b => (1,3) -- foldl :: (a -> b -> a) -> a -> t b -> a (întoarcem un rezultat bazat pe procesarea acumulatorului și a valorilor din container) --instance Foldable ((,) a) ex4 = foldl (+) 10 (1,2) -- (1,{2}) :: (,) a b => 12 {- eq :: a -> a -> Bool eq x y = x == y -} {- eq :: (Eq a, Eq b) => a -> b -> Bool eq x y = x == y -}