2012-11-19 36 views
1

对于数据的方便分析数据的树输出我想使用这对于下面的代码库:库进行分析

data SomeType = A [String] Int | B | C Int deriving (Eq, Ord, Show) 

main = do 
    let theData = A ["a", "b", "c"] 9 : C 3 : B : [] 
    putStr $ treeString theData -- `treeString` is the implied library function 

会产生类似以下的输出:

- A: 
| - - a 
| | - b 
| | - c 
| - 9 
- C: 
| - 3 
- B 

有没有这样的图书馆?或者,也许更好的方法来解决这个问题?

回答

4

Data.TreedrawTreedrawForest功能类似的格式,所以你可以写一个函数来你的数据结构转换为Tree String,然后使用drawTree

import Data.Tree 

data SomeType = A [String] Int | B | C Int deriving (Eq, Ord, Show) 

toTree :: SomeType -> Tree String 
toTree (A xs n) = Node "A" [Node "*" (map (flip Node []) xs), Node (show n) []] 
toTree B  = Node "B" [] 
toTree (C n) = Node "C" [Node (show n) []] 

main = do 
    let theData = A ["a", "b", "c"] 9 : C 3 : B : [] 
    putStr $ drawTree (Node "*" (map toTree theData)) 

输出:

* 
| 
+- A 
| | 
| +- * 
| | | 
| | +- a 
| | | 
| | +- b 
| | | 
| | `- c 
| | 
| `- 9 
| 
+- C 
| | 
| `- 3 
| 
`- B 
+0

谢谢!输出非常好,但toTree实现看起来像纯粹的样板。没有更通用的解决方案吗? –

+1

@NikitaVolkov:你可能可以用泛型做些事情,但是你会想要像列表或字符串这样的特殊情况,以便它们不会呈现为巨大的“(:)”节点树。 – hammar

+0

发现如何做到这一般。看到我的答案 –

1

添加到哈马尔的答案。这里有一个如何做一个通用的转换Data.Tree

import Data.Tree 
import Data.Generics 
import Control.Applicative 

dataTree = fix . genericTree 
    where 
    genericTree :: Data a => a -> Tree String 
    genericTree = dflt `extQ` string 
     where 
     string x = Node x [] 
     dflt a = Node (showConstr (toConstr a)) (gmapQ genericTree a) 
    fix (Node name forest) 
     | name == "(:)" 
     , a : b : [] <- forest 
     = Node "*" $ (fix a) : (subForest $ fix b) 
     | otherwise = Node name $ fix <$> forest 

但是这对一个人的数据类型的工作,他们必须有Data一个实例,它可以很容易地通过添加{-# LANGUAGE DeriveDataTypeable #-}编译和制造型来实现来自TypeableData像这样:

data SomeType = A [String] Int | B | C Int | D [[String]] 
    deriving (Typeable, Data)