在 haskell 中使用 Diagrams 库(绘制二叉树)

Using Diagrams library in haskell (draw binary trees)

我正在尝试使用 Haskell 图库来绘制二叉树。

这是我的树类型:

data Tree a = Empty
            | Node { label :: a, left,right :: Tree a }

leaf :: a -> Tree a
leaf a = Node a Empty Empty

这是一棵随机树:

t0 = Node 1 (Node 2 (leaf 3) (leaf 4))   (Node 5 (leaf 6) (leaf 7))

为了在中间画一个带有字符的圆,我使用了这个简单的函数(工作正常):

diagNode :: String -> Diag

这是我绘制二叉树的代码:

diagTree :: Show s => Tree s -> Diag
diagTree Empty = diagNode "Empty"

diagTree (Node x Empty Empty) = connectOutside "X" "L" $
                                connectOutside "X" "R" $
          nx
          ===
      (nl ||| nr) # center
  where
    nx = named "X" ( diagNode (show x) )  
    nl = named "L" (diagNode "Empty" )
    nr = named "R" (diagNode "Empty" )  

diagTree (Node x left right) = connectOutside "X" "L" $
                               connectOutside "X" "R" $
          nx
          ===
      (nl ||| nr) # center
  where
    nx = named "X" ( diagNode (show x) ) 
    nl = named "L" (diagTree left )
    nr = named "R" (diagTree right )

你可以看到我的代码只适用于最后一个"leafs",但它没有将上面的节点与下面的节点连接起来。我认为问题是,我正在递归调用 diagTree。

我该如何解决这个问题?

我认为问题在于您在命名时为内部节点赋予了相同的名称,因此 connectOutside 连接了它找到的第一个名称(恰好是树中的最后一个节点)。您可以通过根据每个节点的位置给每个节点一个唯一的名称来解决这个问题:

diagTree :: Show s => Tree s -> Diagram Rasterific
diagTree = go [] where
  go nm Empty        = diagNode  "Empty" # named nm
  go nm (Node x l r) = 
    connectOutside nm nmL .
    connectOutside nm nmR $
          nx
          ===
      (nl ||| nr) # centerX
    where
      (nmL, nmR) = ('L':nm, 'R':nm)
      nx = diagNode (show x) # named nm 
      nl = go nmL l # named nmL
      nr = go nmR r # named nmR

data Tree a = Empty
            | Node { label :: a, left,right :: Tree a }
  deriving Show

leaf :: a -> Tree a
leaf a = Node a Empty Empty

diagNode :: String -> Diagram Rasterific
diagNode txt = text txt # fontSizeL 0.4 <> circle 1 & pad 2

我明白了