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 --------------------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:y:rest) = x <= y && ordered (y:rest) 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 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 :: [[a]] -> [[a]] --notNull lst = filter (\l -> not (null l)) lst --notNull lst = filter (\l -> (not . null) l) lst --notNull lst = filter (not . null) lst 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 :: Num a => [[a]] -> [[a]] --replaceH lst = map (\l -> 1 : tail l) lst --replaceH lst = map (\l -> ((1:) . tail) l) lst --replaceH lst = map ((1:) . tail) lst 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 ([]:_) = [] myTransposePM matrix = map head matrix : myTransposePM (map tail matrix) --ex: de implementat filter cu pattern matching și case filterCase _ [] = [] 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 filterG _ [] = [] 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) => b=1, c=2 d = f 5 where f = (+1) --ex: de implementat filter cu pattern matching, gărzi și where --filterAll filterAll _ [] = [] filterAll p (x:xs) | p x = x : filterRest | otherwise = filterRest where filterRest = filterAll p xs --------------------Evaluare leneșă f x = trace "x" 2*x g x = f 2 + f 2 -- se evaluează de ? ori la apelul g 5 h x = x*x*x -- ? la apelul h (f 2) {- h (f 2) = {(f 2)} * {(f 2)} * {(f 2)} 4 * 4 * 4 64 -} i x y = if y>5 then y*y else x*x -- la apelul i (f 2) (f 3) ? --------------------Fluxuri {- (define naturals (let loop ((n 0)) (stream-cons n (loop (add1 n))))) -} naturals = let loop n = n : loop (n + 1) in loop 0 naturalsFrom n = [n ..] {- (define ones (stream-cons 1 ones)) -} ones = 1 : ones onesInterval = [1, 1 ..] {- (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 [1..] --map (1/) [1..] --ex: 1, 1/(1*2), 1/(2*3), 1/(3*4)... invProds = 1 : zipWith (*) invNats (tail invNats) --(1:) $ zipWith (/) ones $ zipWith (*) [1..] [2..] --------------------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. -} pascal = loop [1] where loop row = row : loop (next row) next row = [1] ++ zipWith (+) row (tail row) ++ [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]] -} parts [] = [[]] parts (x:xs) = map (x:) pxs ++ 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 0 = [[]] partitions n = [ h : rest | h <- [1 .. n], rest <- partitions (n - h), null rest || h <= head rest ] {- 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]]] -}