-- Ascundem funcțiile predefinite, pentru a le redefini noi import Prelude hiding (sum, length) -- Clasa Aggregatable -- Grupează operatorii de combinare pentru reduceri class Agg t where --Combinare independentă (banana split): fuzionează două reduceri paralele (<+>) :: t a b b -> t a c c -> t a (b, c) (b, c) -- Combinare semidependentă: a doua reducere folosește rezultatul primei reduceri (>.>) :: t a b b -> t a (b, c) c -> t a (b, c) (b, c) -- Combinare mutual dependentă: ambele reduceri au acces la rezultatul comun (pereche) (<.>) :: t a (b, c) b -> t a (b, c) c -> t a (b, c) (b, c) ---Reduceri liniare (pe liste sau containere care admit liniarizare) data Folder a b c = Folder { foldNull :: c -- caz de bază , foldCons :: a -> b -> c -- funcția de combinare } instance Agg Folder where f <+> g = Folder (foldNull f, foldNull g) (\a (b, c) -> (foldCons f a b, foldCons g a c)) f >.> g = Folder (foldNull f, foldNull g) (\a (b, c) -> (foldCons f a b, foldCons g a (b, c))) f <.> g = Folder (foldNull f, foldNull g) (\a (b, c) -> (foldCons f a (b, c), foldCons g a (b, c))) -- Funcția de aplicare a unui folder pe o structură liniară/liniarizată fold :: Foldable t => Folder a b b -> t a -> b fold folder = foldr (foldCons folder) (foldNull folder) -- Exemple de reduceri liniare sum :: (Foldable t, Num a) => t a -> a sum = fold sumFolder sumFolder :: Num a => Folder a a a sumFolder = Folder 0 (+) length :: Foldable t => t a -> Int length = fold lenFolder lenFolder :: Folder a Int Int lenFolder = Folder 0 $ const (+1) -- Fuziune banana split: sumă + lungime într-o singură parcurgere sumLen :: (Foldable t, Num a) => t a -> (a, Int) sumLen = fold (sumFolder <+> lenFolder) -- Reducere semidependentă: verifică dacă fiecare element > suma restului listei steep :: (Ord a, Num a) => [a] -> Bool steep = snd . fold (sumFolder >.> steepFolder) steepFolder :: Ord a => Folder a (a, Bool) Bool steepFolder = Folder { foldNull = True , foldCons = \x (s, acc) -> x > s && acc } -- Reducere mutual dependentă: suma pozițiilor pare/impare evenOddSums :: Num a => [a] -> (a, a) evenOddSums = fold (evenFolder <.> oddFolder) evenFolder :: Num a => Folder a (a, a) a evenFolder = Folder { foldNull = 0 , foldCons = \x (evenS, oddS) -> x + oddS } oddFolder :: Num a => Folder a (a, a) a oddFolder = Folder { foldNull = 0 , foldCons = \_ (evenS, oddS) -> evenS } -- Combinarea a trei foldere: steepMean (fiecare element > media restului listei) steepMean :: (Ord a, Fractional a) => [a] -> Bool steepMean = snd . fold ((sumFolder <+> lenFolder) >.> steepMeanFolder) steepMeanFolder :: (Ord a, Fractional a) => Folder a ((a, Int), Bool) Bool steepMeanFolder = Folder True (\x ((s, l), acc) -> l == 0 || x > s / fromIntegral l && acc) ---Reduceri ierarhice - pe arbori binari data BST a = BSTNil | BSTNod { vl :: a, lt :: BST a, rt :: BST a} -- Funcții utile pentru construcția/afișarea arborilor insertElem :: (Ord a, Eq a) => BST a -> a -> BST a insertElem BSTNil elem = BSTNod elem BSTNil BSTNil insertElem root@(BSTNod value left right) elem | value == elem = root | value < elem = BSTNod value left (insertElem right elem) | value > elem = BSTNod value (insertElem left elem) right toBST :: Ord a => [a] -> BST a toBST = foldl insertElem BSTNil instance Show a => Show (BST a) where show tree = showH 0 tree where showH _ BSTNil = "" showH level (BSTNod elem left right) = replicate level '\t' ++ show elem ++ "\n" ++ showH (level + 1) left ++ showH (level + 1) right -- Folder pentru (structuri izomorfe cu) arborii binari data BSTFolder a b c = BSTFolder { foldNil :: c , foldNod :: a -> b -> b -> c } instance Agg BSTFolder where f <+> g = BSTFolder (foldNil f, foldNil g) (\a (b1, c1) (b2, c2) -> (foldNod f a b1 b2, foldNod g a c1 c2)) f >.> g = BSTFolder (foldNil f, foldNil g) (\a (b1, c1) (b2, c2) -> (foldNod f a b1 b2, foldNod g a (b1, c1) (b2, c2))) f <.> g = BSTFolder (foldNil f, foldNil g) (\a (b1, c1) (b2, c2) -> (foldNod f a (b1, c1) (b2, c2), foldNod g a (b1, c1) (b2, c2))) -- Funcția de aplicare a unui folder ierarhic foldBST :: BSTFolder a b b -> BST a -> b foldBST folder = go where go BSTNil = foldNil folder go (BSTNod elem left right) = foldNod folder elem (go left) (go right) -- Exemple de reduceri ierarhice height :: BST a -> Int height = foldBST heightFolder heightFolder :: BSTFolder a Int Int heightFolder = BSTFolder 0 (\_ lH rH -> 1 + max lH rH) --invert :: BST a -> BST a --invert = foldBST invertFolder --invertFolder :: BSTFolder a (BST a) (BST a) --invertFolder = -- Reducere semidependentă: fiecare nod se împerechează cu suma propriului subarbore -- sumBSTFolder >.> nodeSumFolder --nodeToSubtreeSum :: Num a => BST a -> BST (a, a)