使用 graphviz 可视化 Haskell 数据树
Visualize Haskell Data Tree with graphviz
我尝试用 Graphviz 可视化 Haskell 树:
import Data.GraphViz.Types as G
data Animal = Dog String | Cat String
data Stable = Stable [Animal]
main :: IO ()
main= let myanimals=Stable [Dog "Max",Cat "Cooper"]
in print $G.printDotGraph myanimals
输出应该是点格式的,类似于:
digraph {
Stable -> Dog "Max";
Stable -> Cat "Cooper";
}
但是代码会产生一条错误消息:
* Couldn't match expected type `dg0 n0' with actual type `Stable'
* In the first argument of `printDotGraph', namely `myanimals'
In the second argument of `($)', namely `printDotGraph myanimals'
In the expression: print $ printDotGraph myanimals
我做错了什么?
您必须将您的数据类型转换为该包可以呈现的图形;它不会为您进行转换。它确实允许转换 fgl graph to its DotGraph
type. For that, you can construct a graph with one of the concrete graph types like Data.Graph.Inductive.PatriciaTree
using the mkGraph
函数。这是您如何做到这一点的未经测试的草图。具体细节取决于您要生成的图表。 (它可以做得更紧凑,但我试图更明确地说明。)
type NodeLabel = String -- Just the animal name.
type EdgeLabel = () -- No information for now.
graphFromStable :: Stable -> Gr NodeLabel EdgeLabel
graphFromStable (Stable animals) = mkGraph nodes edges
where
-- Define the set of nodes in your desired graph.
nodes :: [LNode NodeLabel]
nodes = stableNode : animalNodes
-- Make an edge from the stable node to each animal node.
edges :: [(Node, Node, EdgeLabel)]
edges =
[ (stableId, animalId, ())
| (animalId, _animalLabel) <- animalNodes
]
-- Define the stable node’s ID and label.
stableNode :: LNode NodeLabel
stableNode@(stableId, _stableName) = (0, "Stable")
-- Give IDs and labels to each animal node.
animalNodes :: [LNode NodeLabel]
animalNodes = zip [1..] (map animalLabel animals)
-- Get a label for an animal node.
animalLabel :: Animal -> NodeLabel
animalLabel (Dog name) = name
animalLabel (Cat name) = name
那么你应该可以在这个函数的结果上使用graphToDot
将其转换为DotGraph
类型,最后使用printDotGraph
.
(其他图形表示之一可能允许您更方便地针对您的用例执行此操作,例如,使用字符串而不是整数作为节点 ID,但我对这些库不太熟悉,无法立即判断。 )
如果您想要更快更脏的东西,另一种方法是将图形打印为一串 Dot 源代码。但我会投资于将这些结构化类型用于任何重要的事情,因为它会给你更多来自类型的指导,并让你使用 FGL 的图形算法来分析和转换你的图形。
我尝试用 Graphviz 可视化 Haskell 树:
import Data.GraphViz.Types as G
data Animal = Dog String | Cat String
data Stable = Stable [Animal]
main :: IO ()
main= let myanimals=Stable [Dog "Max",Cat "Cooper"]
in print $G.printDotGraph myanimals
输出应该是点格式的,类似于:
digraph {
Stable -> Dog "Max";
Stable -> Cat "Cooper";
}
但是代码会产生一条错误消息:
* Couldn't match expected type `dg0 n0' with actual type `Stable'
* In the first argument of `printDotGraph', namely `myanimals'
In the second argument of `($)', namely `printDotGraph myanimals'
In the expression: print $ printDotGraph myanimals
我做错了什么?
您必须将您的数据类型转换为该包可以呈现的图形;它不会为您进行转换。它确实允许转换 fgl graph to its DotGraph
type. For that, you can construct a graph with one of the concrete graph types like Data.Graph.Inductive.PatriciaTree
using the mkGraph
函数。这是您如何做到这一点的未经测试的草图。具体细节取决于您要生成的图表。 (它可以做得更紧凑,但我试图更明确地说明。)
type NodeLabel = String -- Just the animal name.
type EdgeLabel = () -- No information for now.
graphFromStable :: Stable -> Gr NodeLabel EdgeLabel
graphFromStable (Stable animals) = mkGraph nodes edges
where
-- Define the set of nodes in your desired graph.
nodes :: [LNode NodeLabel]
nodes = stableNode : animalNodes
-- Make an edge from the stable node to each animal node.
edges :: [(Node, Node, EdgeLabel)]
edges =
[ (stableId, animalId, ())
| (animalId, _animalLabel) <- animalNodes
]
-- Define the stable node’s ID and label.
stableNode :: LNode NodeLabel
stableNode@(stableId, _stableName) = (0, "Stable")
-- Give IDs and labels to each animal node.
animalNodes :: [LNode NodeLabel]
animalNodes = zip [1..] (map animalLabel animals)
-- Get a label for an animal node.
animalLabel :: Animal -> NodeLabel
animalLabel (Dog name) = name
animalLabel (Cat name) = name
那么你应该可以在这个函数的结果上使用graphToDot
将其转换为DotGraph
类型,最后使用printDotGraph
.
(其他图形表示之一可能允许您更方便地针对您的用例执行此操作,例如,使用字符串而不是整数作为节点 ID,但我对这些库不太熟悉,无法立即判断。 )
如果您想要更快更脏的东西,另一种方法是将图形打印为一串 Dot 源代码。但我会投资于将这些结构化类型用于任何重要的事情,因为它会给你更多来自类型的指导,并让你使用 FGL 的图形算法来分析和转换你的图形。