import Data.List import Debug.Trace --------------------Indentare și paranteze insSort [] = [] insSort (x:xs) = ins x (insSort xs) -- aplicația de funcție are prioritate -- și e asociativă la stânga ins e [] = [e] ins e (x:xs) = -- erau necesare aceste paranteze? DA if e < x then e : x : xs else x : ins e xs -- dar acestea? NU, aplicația de funcție are cea mai mare prioritate --------------------Pattern matching fib :: Int -> Int fib 0 = 0 fib 1 = 1 fib n = fib (n-2) + fib (n-1) sumL :: [Int] -> Int sumL [] = 0 sumL (x:xs) = x + sumL xs --sumP :: (Int, Int) -> Int --mai elegant decât sumP p = fst p + snd p sumP (x,y) = x + y --ordered :: [Int] -> Bool ordered [] = True ordered [x] = True ordered (x:xs@(y:_)) = x <= y && ordered xs --ordered2 :: [Int] -> Bool ordered2 (x:xs@(y:_)) = x <= y && ordered2 xs ordered2 _ = True --ex: de implementat map si filter cu PM mapPM f [] = [] mapPM f (x:xs) = f x : mapPM f xs filterPM p [] = [] filterPM p (x:xs) = if p x then x : filterPM p xs else filterPM p xs --nu funcționează (din cauză că pattern-urile nu pot fi potrivite și între ele) --eq x x = True -- dă eroare Conflicting definitions for `x' --eq _ _ = False --------------------Compunere de funcții (operatorul .) --myLast :: [a] -> a myLast = head . reverse -- myLast [1..5] = myMin :: Ord a => [a] -> a myMin = head . sort -- myMin [2,4,1,2,3,6,2] = myMax :: Ord a => [a] -> a myMax = myLast . sort -- myMax [2,4,1,2,3,6,2] = --ex --selectarea listelor nevide dintr-o listă de liste --[[],[1],[],[2,3]] ===> [[1],[2,3]] --evoluăm treptat de la varianta fără compunere la cea cu compunere {- notNull l = filter (\lst -> not (null lst)) l notNull l = filter (\lst -> (not . null) lst) l notNull l = filter (not . null) l notNull = filter (not . null) -} notNull :: [[a]] -> [[a]] notNull = filter $ not . null --înlocuirea cu 1 a head-ului fiecărei liste dintr-o listă de liste nevide --[[1],[2,3],[4,5,6]] ===> [[1],[1,3],[1,5,6]] {- replaceH l = map (\(x:xs) -> 1 : xs) l replaceH l = map (\lst -> 1 : tail lst) l replaceH l = map (\lst -> ((1:) . tail) lst) l replaceH l = map ((1:) . tail) l replaceH = map ((1:) . tail) -} replaceH :: Num a => [[a]] -> [[a]] replaceH = map $ (1:) . tail --------------------Operatorul $ --de încercat în terminal --take 4 $ filter (odd . fst) $ zip [1..] [2..] --------------------Expresii condiționale --uglySum :: [Int] -> Int uglySum l = if null l then 0 else head l + uglySum (tail l) --myTranspose :: [[a]] -> [[a]] -- [[1,2,3], [4,5,6], [7,8,9]] ===> -- [ [2,3], [5,6], [8,9]] ===> -- [ [3], [6], [9]] ===> -- [ [], [], []] myTranspose matrix = case (head matrix) of [] -> [] _ -> map head matrix : myTranspose (map tail matrix) --myTranspose cu pattern matching myTransposePM ([]:xs) = [] myTransposePM matrix = map head matrix : myTransposePM (map tail matrix) --ex: de implementat filter cu pattern matching și case filterCase p [] = [] filterCase p (x:xs) = case p x of True -> x : filterCase p xs _ -> filterCase p xs --allEqual :: Eq a => a -> a-> a-> Bool allEqual a b c | a==b = b==c | otherwise = False --ex: de implementat filter cu pattern matching și gărzi filterG p [] = [] filterG p (x:xs) | p x = x : filterG p xs | otherwise = filterG p xs --------------------Legări locale myFoldl :: (b -> a -> b) -> b -> [a] -> b myFoldl f acc [] = acc myFoldl f acc (x:xs) = let newAcc = f acc x -- în Haskell, funcția lui foldl primește acc ca parametru stâng! in myFoldl f newAcc xs myFoldr :: (a -> b -> b) -> b -> [a] -> b myFoldr f acc [] = acc myFoldr f acc (x:xs) = f x rightResult where rightResult = myFoldr f acc xs exwhere = a + b + c + d --7+1+2+6 where a = 2+5 (b, c) = head (zip [1..] [2..]) --(b,c) = (1,2) d = f 5 where f = (+1) --ex: de implementat filter cu pattern matching, gărzi și where filterAll p [] = [] filterAll p (x:xs) | p x = x : resRec | otherwise = resRec where resRec = filterAll p xs --------------------Evaluare leneșă f x = trace "x" 2*x g x = f 2 + f 2 -- se evaluează de 2 ori la apelul g 5 h x = x*x*x -- evaluare leneșă la apelul h (f 2) i x y = if y>5 then y*y else x*x -- la apelul i (f 2) (f 3) nu se evaluează argumentele --------------------Fluxuri {- (define naturals (let loop ((n 0)) (stream-cons n (loop (add1 n))))) -} naturals = loop 0 where loop n = n : loop (n + 1) naturalsFrom n = [n ..] {- (define ones (stream-cons 1 ones)) -} ones = 1 : ones {- (define fibonacci (stream-cons 0 (stream-cons 1 (stream-zip-with + fibonacci (stream-rest fibonacci))))) -} fibonacci = 0 : 1 : zipWith (+) fibonacci (tail fibonacci) --ex: 1/1, 1/2, 1/3... invNats = zipWith (/) ones (tail naturals) --ex: 1, 1/(1*2), 1/(2*3), 1/(3*4)... invProds = 1 : zipWith (*) invNats (tail invNats) --------------------List comprehensions lc1 = [ (x,y,z) | x<-[1..3], y<-[1..4], x x] --alte ex: {- Să se implementeze triunghiul lui Pascal: [[1], [1,1], [1,2,1], [1,3,3,1], [1,4,6,4,1] ... ] În triunghiul lui Pascal, pe fiecare linie valorile se obțin din adunarea valorilor adiacente de pe linia anterioară, iar la stânga și la dreapta fiecărei linii se adaugă valoarea 1. -} {- cu loop pascal = loop [1] where loop lst = lst : loop (f lst) f lst = [1] ++ zipWith (+) lst (tail lst) ++ [1] -} -- cu iterate si lc pascal = iterate (\lst -> [1] ++ [ x+y | (x,y) <- zip lst (tail lst) ] ++ [1]) [1] {- Să se construiască mulțimea părților unei liste. Exemplu: pt lista [1,2,3]: [[], [1], [2], [3], [1,2], [1,3], [2,3], [1,2,3]] -} {- cu map parts [] = [[]] parts (x:xs) = pxs ++ map (x:) pxs where pxs = parts xs -} -- cu lc parts [] = [[]] parts (x:xs) = pxs ++ [ x:p | p <- pxs ] where pxs = parts xs {- Să se construiască mulțimea partițiilor unui număr. Partiție a unui număr n = o listă de numere strict pozitive, ordonate crescător, a căror sumă este n. Exemplu: pt numărul 4: [[1,1,1,1], [1,1,2], [1,3], [2,2], [4]] -} partitions 1 = [[1]] partitions n = [ h:x:xs | h <- [1 .. n-1], (x:xs) <- partitions (n-h), h <= x ] ++ [[n]] {- Să se construiască fluxul de permutări: mai întâi permutări [1], apoi permutări [1,2] etc. Exemplu: take 3 permStream: [[[1]] [[2,1], [1,2]] [[3,1,2], [1,3,2], [1,2,3], [3,2,1], [2,3,1], [2,1,3]]] -} permStream = loop [[1]] 2 where loop perms n = perms : loop (insertEverywhere n perms) (n + 1) insertEverywhere n perms = concat [ insAllPos n p | p <- perms ] insAllPos n perm = map (\len -> take len perm ++ [n] ++ drop len perm) [0 .. n-1]