import Data.List data FuzzyBoolean = CertainTrue | Unsure | CertainFalse couldBeTrue x = case x of CertainTrue -> True Unsure -> True otherwise -> False -- | x == CertainTrue = True couldBeFalse CertainFalse = True couldBeFalse _ = False data Natural = Zero | Succ Natural deriving (Show, Eq) unu = Succ Zero doi = Succ unu cinci = Succ $ Succ $ Succ $ Succ $ Succ Zero add Zero y = y add (Succ z) y = Succ (add z y) type GridPoint = (Float, Float) dist0 :: GridPoint -> Float dist0 (x, y) = x + y newtype GridPointN = GP (Float, Float) dist0N (GP (x, y)) = x + y ones = 1 : ones --treeOnes = [1, treeOnes, treeOnes] --treeOnes = (1, treeOnes, treeOnes) data TreeInt = TreeIntConstr Int TreeInt TreeInt | NilInt treeOnes = TreeIntConstr 1 treeOnes treeOnes rootInt (TreeIntConstr root _ _) = root trivialTree val = TreeIntConstr val NilInt NilInt --trivialTree val = TreeIntConstr val undefined undefined data Tree a = Nil | Leaf a | Node a [Tree a] --deriving Show treeOnes2 = Node 1 [treeOnes2, treeOnes2] treeB = makeTree 1 where makeTree n = Node n [makeTree (2*n), makeTree (2*n + 1)] -- e.g. -- Node "radacina" [Node "copil1" [Leaf "frunza1", Leaf "frunza2"], Leaf "frunza3"] limit 0 _ = Nil limit at t = case t of Node val chd -> Node val $ map (limit $ at - 1) chd _ -> t 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 preord :: Tree a -> [a] preord Nil = [] preord (Leaf x) = [x] preord (Node x children) = x : concatMap preord children 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 | HeadList a [NestedList a] deriving Read fromAtom (Atom x) = x fromAtom _ = undefined instance Show a => Show (Pair a) where show (P x y) = "<" ++ show x ++ ";" ++ show y ++ ">" instance Show a => Show (NestedList a) where show (Atom x) = "<" ++ show x ++ ">" show (HeadList h l) = "{" ++ concat (intersperse ", " $ show h : map show l) ++ "}" l = HeadList 1 [Atom 2, HeadList 3 [Atom 4, Atom 5], Atom 6] class Invertible a where invert :: a -> a invert = id instance Invertible (Pair a) where invert (P x y) = P y x instance Invertible (NestedList a) where invert a@(Atom _) = a invert (HeadList x lista) = HeadList x $ reverse $ map invert lista instance Invertible a => Invertible [a] where --invert l = reverse $ map invert l invert = reverse . map invert instance Invertible (Tree a) where invert t = case t of Node val children -> Node val $ invert children _ -> t {- 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] --} --{- class Container t where contents :: t b -> [b] --} instance Container Pair where contents (P x y) = [x, y] instance Container Tree where contents = preord instance Container [] where contents = id -- clasa tuturor tipurilor care pot fi asemănate cu un arbore -- (care pot fi transformate într-un arbore) class TreeLike t where --t constructor de tip -- construcție a unei valori triviale de tipul t a makeOne :: a -> t a toTree :: Eq a => t a -> Tree a -- trebuie Eq pentru mai târziu la parcurgerea grafului instance TreeLike Tree where makeOne x = Leaf x toTree = id instance TreeLike NestedList where makeOne x = Atom x toTree (Atom x) = Leaf x toTree (HeadList x lista) = Node x $ map toTree lista instance Eq a => Eq (Tree a) where Nil == Nil = True Leaf x == Leaf y = x == y Node x _ == Node y _ = x == y --instance Eq (Pair a) where -- pot lăsa doar așa, dar == ciclează la infinit --instance Ord (Pair a) where -- exerciții tipare: f1 :: Eq a => a -> a -> a -> a f1 x y z = if x == y then x else z f2 :: (Eq (t a), Container t, Invertible (t a)) => t a -> t a -> [a] f2 x y = if (invert x) == (invert y) then contents x else contents y f3 :: (Ord a, Num a, Invertible a) => [a] -> [a] -> [a] f3 x y = if head x > head y then (invert x) ++ (invert y) else [head y - head x] f4 :: Ord a => a -> a -> a -> a f4 x y z = if x == y then z else if x > y then x else y newtype 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, Show a) => Show (Graph a) where show = show . toTree instance TreeLike Graph where makeOne x = G [(x, x)] 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 -- verificare makeOne {- makeOne 5 -- nu știm ce tip trebuie să întoarcă makeOne (este ambiguu) fromAtom $ makeOne 5 preord $ makeOne 5 nodes $ makeOne 5 -- excepție (undefined) head $ nodes $ makeOne 5 -- nu dă excepție mulțumită evaluării leneșe -}