如何用Haskell的Graphviz绑定正确绘制Record节点间的边
解决Haskell Graphviz绑定生成Record节点边时的端口引号问题
核心解决方案:用NodePort显式区分节点ID和端口
你遇到的问题根源是直接把带端口的字符串(比如"mynode1:f0")当作节点ID传入,绑定会把整个字符串视为节点名,因此自动添加引号。正确的做法是利用Haskell Graphviz绑定提供的NodePort类型,把节点ID和端口分开定义,这样生成的Dot代码里端口就不会带引号。
具体代码示例
- 导入必要模块
import Data.GraphViz import Data.GraphViz.Attributes.Complete import Data.GraphViz.Types.Generalised
- 定义节点ID和带端口的引用
-- 基础节点ID node1 :: NodeID node1 = Str "mynode1" node2 :: NodeID node2 = Str "mynode2" -- 带端口的节点引用:NodePort 节点ID (PortName 端口名) node1PortF0 :: NodeID node1PortF0 = NodePort node1 (PortName "f0") node2PortF1 :: NodeID node2PortF1 = NodePort node2 (PortName "f1")
- 定义Record节点的属性
确保节点的形状设为Record,并通过RecordLabels定义带端口的字段:
node1Attrs :: Attributes node1Attrs = [ Shape Record, Label (RecordLabels [PortLabel (Just "f0") (StrLabel "字段0")]) ] node2Attrs :: Attributes node2Attrs = [ Shape Record, Label (RecordLabels [PortLabel (Just "f1") (StrLabel "字段1")]) ]
- 创建边并生成Dot代码
直接用带端口的节点引用来创建边:
-- 创建边 portEdge :: Edge NodeID portEdge = (node1PortF0, node2PortF1) -- 构建图 myGraph :: DotGraph NodeID myGraph = dotGraph $ directedGraph [ (node1, node1Attrs) , (node2, node2Attrs) ] [ portEdge ] -- 生成Dot代码 main :: IO () main = print myGraph
这样生成的Dot代码里,边会是mynode1:f0 -> mynode2:f1的形式,没有多余引号,完全符合Graphviz Record节点的语法要求,无需手动修改。
内容的提问来源于stack exchange,提问作者JeanJouX
相关产品推荐
相关产品推荐

