-- construim un tip de date ca alias al unui alt tip type ListInt = [Int] -- alias incList :: ListInt -> ListInt incList = map (+1) incTail = tail . incList -- tipul lui incTail este incTail :: ListInt -> [Int] -- construim un tip de date nou, ca enumerare de valori data FuzzyBoolean = CertainTrue | CertainFalse | Fuzzy -- FuzzyBoolean - constructor de tip -- 3 constructori de date -- pot apărea în expresii fromFuzzy CertainTrue = True fromFuzzy CertainFalse = False fromFuzzy Fuzzy = undefined -- construim un nou tip de date nou folosind constructori de bază. data Natural = Zero | Succ Natural -- Zero - constr date nular ~ valoare -- Succ - constr date unar ~ funcție deriving (Show, Eq) -- putem afișa la consolă și putem face == -- Zero -- constructor de date nular ~ valoare -- Succ -- constructor de date unar ~ funcție unu = Succ Zero doi = Succ unu --- important: vezi utilizare constructori de date în pattern-matching addNat Zero n = n addNat (Succ m) n = Succ $ addNat m n infixl 6 +* Zero +* n = n Succ m +* n = Succ $ m +* n {- rulați addNat (Succ (Succ doi)) (Succ (Succ (Succ Zero))) addNat unu doi doi +* Zero == doi :t addNat -} ones = 1 : ones --treeOnes = (1, [treeOnes, treeOnes]) -- > tip infinit pentru al doilea element din pereche data TreeInt = NilInt | NodeInt Int [TreeInt] -- atenție! Definiție ineficientă (semnatic) în care se suprapun semantic constructorii de date -- Tree constructor de tip unar -- a variabilă de tip data Tree a = Nil | Leaf { value :: a } | Node { value :: a, children :: [Tree a] } myTree = Node "radăcină" [ Node "copil1" [ Leaf "frunză 1", Leaf "frunză 2"], Leaf "frunză 3"] instance Show a => Show (Tree a) where show tree = pt 0 tree where pt level tree = case tree of Nil -> space level ++ "- \n" Leaf val -> space level ++ show val ++ "\n" Node val children -> space level ++ show val ++ "\n" ++ if all isNil children then "" else concatMap (pt $ level + 1) children space sp = [' ' | _ <- [1..sp * 2]] isNil Nil = True isNil _ = False -- arbore binar infinit care în toate nodurile conține numărul 1 treeOnes = Node 1 [treeOnes, treeOnes] -- arbore binar infinit care la BFS dă lista de numere treeB = build 1 where build n = Node n (map build [2*n, 2*n+1]) limit 0 _ = Nil limit at t = case t of Node x children -> Node x $ map (limit $ at - 1) children otherwise -> t preord :: Tree a -> [a] preord Nil = [] preord (Leaf x) = [x] preord (Node x children) = x : concatMap preord children {- încercați la consolă limit 5 treeOnes limit 5 treeB take 10 $ preord treeB -- doar calea de pe partea stângă a arborelui, pentru că nu ne întoarcem niciodată preord $ limit 5 treeB -} data Graph a = G { edges :: [(a, a)] } deriving Show graph = G [(1, 2), (1, 3), (1, 4), (2, 1), (2, 2), (2, 7), (4, 6), (6, 4), (6, 3), (6, 7), (6, 8), (5, 2), (5, 6), (5, 9)] outgoing v g = map snd $ filter (\(i,j)->i==v) (edges g) -- sau: -- outgoing v = map snd . (filter $ (== v) . fst) . edges nodes (G []) = [] nodes (G (e:rest)) = -- eNodes ++ filter ((flip notElem) eNodes) (nodes (G rest)) eNodes ++ filter (`notElem` eNodes) (nodes $ G rest) where eNodes = [fst e, snd e] -- toTree vizitează doar noduri la care se poate ajunge din primul nod toTree g@(G edges) = build [] (head $ nodes g) where build visited gNode = -- consider că visited sunt noduri din graf pentru care am construit deja noduri în arbore (am apelat Node) -- gNode este un nod din graf -- consider că node a fost verificat deja că nu a fost vizitat și acum pot construi un Node cu el Node gNode $ foldl (\ -- iau pe rând succesorii în parcurgere și construiesc arbori pentru fiecare; în arbore, aceștia devin copiii lui gNode previousTrees -- arborii pentru frații anteriori, copii ai lui node successor -- succesor din parcurgere al lui gNode, pentru care construiesc un arbore -> let -- nodurile din graf vizitate în frații (din parcurgere / din arbore) acestui nod visitedInSiblings = concatMap preord previousTrees -- toate nodurile din graf deja vizitate: -- node, -- nodurile vizitate anterior apelului build pentru gNode, -- și nodurile vizitate în frații din parcurgere ai lui gNode visitedAll = gNode : visited ++ visitedInSiblings -- testez dacă am vizitat nodul deja in if successor `elem` visitedAll then previousTrees else previousTrees -- adaug la lista de arbori copii ai lui gNode ++ [build visitedAll successor] -- subarborele pentru acest succesor ) [] (outgoing gNode g) -- toTree vizitează toate nodurile din graf toTreeComplete g = Node (head $ nodes g) $ -- la rădăcina arborelui trebuie să pun o valoare de tipul valorilor din graf -- nu am ce face decât să aleg o valoare oarecare din graf (e.g. valoarea primului nod) foldl (\trees node -> let visited = concatMap preord trees -- nodurile din graf parcurse până acum restrictG (G edges) = -- un graf care conține doar muchii între noduri nevizitate până acum G $ filter (\(i, j) -> i `notElem` visited && j `notElem` visited) $ edges in if node `elem` visited then trees else trees ++ [toTree . restrictG $ g] ) [] $ nodes g