Haskell How to convert general tree to Data.Tree -


i have declared general tree follows

data generaltree = emptytree | node [generaltree a] 

i have built instance of generaltree. want convert tree type declared in data.tree. how do it?

i want write function follows type

converttree :: generaltree -> tree 

but i'm having trouble dealing empty tree because there no counterpart in data.tree definition of tree.

the maybe can use @ top level of tree, due definition of tree a. avoid conversion of 'pure' emptytree, sound there can't equivalent value in targeted type. said in first answer way accommodate later occurrence of emptytree take advantage of linear recursive nature of list allowing easy way skip them.

finally, top node must wrap result maybe type avoid conversion of pure emptytree. then, can reasonably work on sub-forest without worry.

this lead version, easiest follow.

convertgtree :: generaltree -> maybe (tree a) convertgtree emptytree             = nothing convertgtree (gnode forestgtree) = (node forest)            forest = buildforest forestgtree       buildforest :: [generaltree a] -> [tree a]       buildforest []     = []       buildforest (x:xs) = case x of           gnode n forest -> (node n (buildforest forest)) : (buildforest xs)          _              -> buildforest xs 

an illustration test,

>>> let testgeneraltree = gnode "0" [gnode "1" [gnode "2" [], emptytree], gnode "3" [emptytree]] >>> putstrln . drawtree . fromjust . convertgtree $ testgeneraltree 0 | +- 1 |  | |  `- 2 | `- 3 

using unfoldtree , returning tree (maybe a)

first, avoid use of node data constructor it's in use tree data type or encounter name's collision. why we've chosen redefine this,

data generaltree = emptytree | gnode [generaltree a]      deriving (show) 

you can deal emptytree mean of intermediate maybe type.
start, pass buildsafetree function use unfoldtree behind scene.
helper manage case , return nothing when encounter emptytree value.
when safe tree build, can clean using cleansafetree, trick reside in cleanforest skip nothing value case of statement.

the code below,

testgeneraltree = gnode "0" [gnode "1" [gnode "2" [], emptytree], gnode "3" [emptytree]]  converttree :: generaltree -> tree converttree = cleansafetree . buildsafetree  buildsafetree :: generaltree -> tree (maybe a) buildsafetree =    unfoldtree helper             helper :: generaltree -> (maybe a, [generaltree a])        helper emptytree       = (nothing, [])        helper (gnode trees) = (just a, trees)   cleansafetree :: tree (maybe a) -> tree  cleansafetree tree@(node (just root) forest) =    node root (cleanforest forest)             cleanforest :: forest (maybe a) -> forest       cleanforest []     = []       cleanforest (x:xs) = case x of           node nothing _      -> cleanforest xs         node (just x) trees -> (node x (cleanforest trees)) : (cleanforest xs)  

some test,

>>> testgeneraltree  gnode "0" [gnode "1" [gnode "2" [],emptytree],gnode "3" [emptytree]]  >>> putstrln . drawtree .  converttree $ testgeneraltree 0 | +- 1 |  | |  `- 2 | `- 3  >>> putstrln . drawtree . fmap show . buildsafetree $ testgeneraltree "0" | +- "1" |  | |  +- "2" |  | |  `- nothing | `- "3"    |    `- nothing 

using unfoldforest shorter.

converttrees :: generaltree -> tree converttrees (gnode forest) =    node (cleanforest . unfoldforest helper $ forest)            -- build forest of tree (maybe a) generaltree       totreemaybe :: generaltree -> (maybe a, [generaltree a])       totreemaybe emptytree           = (nothing, [])       totreemaybe (gnode subforest) = (just , subforest)       -- clean maybe a, forest of tree maybe       frommaybe :: forest (maybe a) -> forest       frommaybe []     = []       frommaybe (x:xs) = case x of             node nothing _     -> cleanforest xs         node (just x) trees -> (node x (cleanforest trees)) : (cleanforest xs)  

a monadic version using unfoldtreem return maybe (tree a)

a solution using unfoldtreemonadic

convertmonadictrees :: generaltree -> maybe (tree a) convertmonadictrees = unfoldtreem helper      helper :: generaltree -> maybe (a, [generaltree a])      helper emptytree       = nothing     helper (gnode trees) = (a, trees) 

the main difference, it's returning nothing if generaltree contain emptytree value discarded.

>>> testgeneraltree2  gnode 0 [gnode 1 [gnode 2 [],emptytree],gnode 3 [emptytree]] >>> convertmonadictrees testgeneraltree2 nothing 

Comments

Popular posts from this blog

linux - xterm copying to CLIPBOARD using copy-selection causes automatic updating of CLIPBOARD upon mouse selection -

c++ - qgraphicsview horizontal scrolling always has a vertical delta -