import Data.List -- Pair 1 2 data Pair a = P a a data MultiTuplu a = Nimic | Unul { val :: a } | Pereche { first :: a, second :: a } | Triplu a a a deriving (Show, Read) data NestedList a = Atom a | List [NestedList a] deriving Read fromAtom (Atom x) = x fromAtom _ = undefined instance Show a => Show (NestedList a) where show (Atom x) = "<" ++ show x ++ ">" show (List l) = "{" ++ concat (intersperse ", " $ map show l) ++ "}" instance Show a => Show (Pair a) where show (P x y) = "<" ++ show x ++ ", " ++ show y ++ ">" l2 = List [List [List [Atom 4, Atom 5, Atom 6], Atom 7, Atom 8], List [Atom 10, Atom 11], Atom 12] ---------------------------- 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"] -- 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]) 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 limit 0 _ = Nil limit level t = case t of Node val children -> Node val $ map (limit (level-1)) children _ -> t preord Nil = [] preord (Leaf v) = [v] preord (Node v children) = v : concatMap preord children ------------ data Graph a = G { edges :: [(a, a)] } 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] ---------------------------- {- instance (Eq a, Num a) => Eq (a -> a -> a) where f == g = f 0 0 == g 0 0 -} {- read "[1,2,3]" *** Exception: Prelude.read: no parse head (read "[1,2,3]") + 5 -} class Invertible a where invert :: a -> a invert = id instance Invertible (Pair a) where invert (P x y) = P y x instance Invertible (MultiTuplu a) where invert m = case m of Triplu x y z -> Triplu z y x Pereche x y -> Pereche y x _ -> m instance Invertible a => Invertible [a] where invert list = reverse $ map invert list instance Invertible Char instance Invertible Bool instance Invertible Integer ------------- {- nu are foarte mult sens și dă un tip ciclic class Container a where contents :: a -> [a] instance Container [x] where -- contents [x] = [x] contents = id --} {- sintaxă incorectă class Container (t a) where contents :: t a -> [a] --} {- merge, dar la instanțierea pentru listă, de exemplu, -- nu poate forța tipul b la tipul elementelor listei class Container a where contents :: a -> [b] instance Container [x] where contents = id --} --{--v3 class Container t where -- -> t unifică la un constructor de tip contents :: Eq a => t a -> [a] instance Container Pair where contents (P x y) = [x, y] instance Container MultiTuplu where contents mt = case mt of Nimic -> []; Unul x -> [x]; Pereche x y -> [x, y]; Triplu x y z -> [x, y, z] instance Container NestedList where contents (Atom x) = [x] contents (List l) = --concatMap contents l -- sau --concat $ map contents l -- sau (concat . map contents) l instance Container [] where contents = id instance Container Tree where contents = preord instance Container Graph where contents = nodes --} --------------- f1 x y z = if x == y then x else z f2 x y = if (invert x) == (invert y) then contents x else contents y f3 x y = if head x > head y then (invert x) ++ (invert y) else [head y - head x] f4 x y z = if x == y then z else if x > y then x else y class TreeLike t where makeOne :: a -> t a toTree :: (Default a, Eq a) => (t a) -> Tree a instance TreeLike Tree where makeOne x = Leaf x toTree = id {- data NestedList a = Atom a | List [NestedList a] deriving Read fromAtom (Atom x) = x fromAtom _ = undefined data Tree a = Nil | Leaf { value :: a } | Node { value :: a, children :: [Tree a] } -} class Default a where implicit :: a instance Default Integer where implicit = 0 instance TreeLike NestedList where makeOne x = Atom x toTree (Atom x) = Leaf x toTree (List lista) = Node implicit $ map toTree lista instance TreeLike Graph where makeOne x = G [(x, undefined)] toTree g = Node implicit $ -- 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 ++ [oneTree . restrictG $ g] ) [] $ nodes g where oneTree g@(G edges) = build g [] (head $ nodes g) build g 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 g visitedAll successor] -- subarborele pentru acest succesor ) [] (outgoing gNode g) -- verificare makeOne {- makeOne 5 -- nu știm ce tip trebuie să întoarcă makeOne (este ambiguu) fromAtom $ makeOne 5 List [makeOne 5] preord $ makeOne 5 Node 1 [Leaf 2, makeOne 5] nodes $ makeOne 5 -- excepție (undefined) head $ nodes $ makeOne 5 -- nu dă excepție mulțumită evaluării leneșe -}