{-# LANGUAGE ScopedTypeVariables #-} module Data.Tree.Circular where import Data.Tree (Tree(Node)) -- $setup -- >>> import Data.List (nub) -- >>> import System.Mem.StableName (makeStableName) -- >>> t0 = Node "1" [Node "1.1" [Node "1.1.1" [], Node "1.1.2" []], Node "1.2" []] data TreeNode a = TreeNode { treeNodeParent :: Maybe (TreeNode a) , treeNodeLabel :: a , treeNodeChildren :: [TreeNode a] } -- | -- >>> t1 = freeze t0 -- >>> [t11, t12 ] = treeNodeChildren t1 -- >>> [t111, t112] = treeNodeChildren t11 -- >>> Just t1' = treeNodeParent t11 -- >>> Just t1'' = treeNodeParent t12 -- >>> Just t11' = treeNodeParent t111 -- >>> Just t11'' = treeNodeParent t112 -- >>> foldr seq () [t1, t1', t1'', t11, t11', t11''] -- () -- >>> length . nub <$> mapM makeStableName [t1,t1',t1''] -- 1 -- >>> length . nub <$> mapM makeStableName [t11,t11',t11''] -- 1 freeze :: forall a. Tree a -> TreeNode a freeze = go Nothing where go :: Maybe (TreeNode a) -> Tree a -> TreeNode a go parent (Node a ts) = treeNode where treeNode :: TreeNode a treeNode = TreeNode parent a children children :: [TreeNode a] children = go (Just treeNode) <$> ts -- | -- >>> thaw (freeze t0) == t0 -- True thaw :: TreeNode a -> Tree a thaw (TreeNode _ a ts) = Node a (fmap thaw ts)