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

2 回答 2

4

Data.TreehasdrawTreedrawForest具有类似格式的函数,因此您可以编写一个函数将您的数据结构转换为 aTree 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
于 2012-11-19T13:59:02.103 回答
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 #-}pragma 并使类型派生自如下方式Typeable轻松实现Data

data SomeType = A [String] Int | B | C Int | D [[String]] 
  deriving (Typeable, Data)
于 2012-11-20T15:17:15.720 回答