如何在Haskell中创建树层次结构?

时间:2019-05-30 06:06:19

标签: haskell tree

如何使用Haskell和非二叉树(例如this question)来达到Data.Tree中所示的相同结果?考虑到记录let lastAttack = null; // ... if (self.pressingAttack) { let now = new Date(); if (!lastAttack || now - lastAttack > 3000) { self.shootBullet(self.mouseAngle); lastAttack = now; } } 用于存储数据,而记录NodeData { nodeID :: String , parentID :: String, value :: a }对于树类型,树将是:

Data.Tree

现在如何根据节点的子节点的Node $ NodeData "id" "parent" (value :: a) (children :: Forest (NodeData a)) :: Tree (NodeData a) 及其自身的值来更新value?输入表将是列表value[NodeData]和id可以成为NodeData的实例,但不能成为Eq的实例。

1 个答案:

答案 0 :(得分:4)

我认为没有特别聪明的单通解决方案。您只需要轻咬一下子弹,然后执行两次遍历:一次遍历创建Map Id [Node]形式的索引,列出每个节点的所有子节点。然后,第二遍将消耗该索引,并将其重构为Forest a。请注意,它不是Tree a,因为根本没有价值可言,而且因为我们都知道有多个根。

import qualified Data.Map.Lazy as M
import qualified Data.Tree as T

newtype Id = Id Int deriving (Eq, Show, Ord)
data Node a = Node {id, parent :: Id, value :: a} deriving Show

input :: [Node String]
input = [ Node (Id 1) (Id 0) "1"
        , Node (Id 2) (Id 1) "1.1"
        , Node (Id 3) (Id 0) "2"
        , Node (Id 4) (Id 2) "1.1.1"
        , Node (Id 5) (Id 3) "2.1"
        , Node (Id 6) (Id 1) "1.2"
        ]

index :: [Node a] -> M.Map Id [Node a]
index m = M.fromListWith (++) $ do
  n@(Node this parent v) <- m
  pure (parent, [n])

recombine :: M.Map Id [Node a] -> T.Forest a
recombine m = go (Id 0) -- Implied root, but a more thorough solution would be explicit
  where go root = [ T.Node v (go idx)
                  | Node idx p v <- M.findWithDefault [] root m
                  ]

在这之后,我们有了想要的树:

> putStr . T.drawForest . recombine . index $ input
2
|
`- 2.1

1
|
+- 1.2
|
`- 1.1
   |
   `- 1.1.1