How do I code a tree of objects in Haskell with pointers to parent and children?

后端 未结 6 964
南方客
南方客 2021-02-06 06:49

I\'ve got the following problem: I have a tree of objects of different classes where an action in the child class invalidates the parent. In imperative languages, it is trivial

6条回答
  •  無奈伤痛
    2021-02-06 07:35

    Here is some zipper code that demonstrates easy modification of the data a cursor points at as well as a "global" property of the tree. We build a tree, move the cursor to the node initially containing a 1, change it to a 3, and are left with a cursor pointing at that node in a fully updated tree.

    import Data.Maybe (fromJust)
    import Data.Tree
    import Data.Tree.Zipper
    
    type NodeData = Either Bool Int
    type TreePath a = [TreePos Full a -> TreePos Full a]
    
    firstChild' = fromJust . firstChild
    parent'     = fromJust . parent
    prev'       = fromJust . prev
    next'       = fromJust . next
    
    -- Determine the path from the root of the tree to the cursor.
    pathToMe :: TreePos Full NodeData -> TreePath NodeData
    pathToMe t | isRoot t  = []
               | isFirst t = firstChild' : pathToMe (parent' t)
               | otherwise = next' : pathToMe (prev' t)
    
    -- Mark a tree as invalid, but leave the cursor in the same place.
    invalidate :: TreePos Full NodeData -> TreePos Full NodeData
    invalidate t = foldr ($) (setLabel (Left False) (root t)) (pathToMe t)
    
    -- Set a node's internal data.
    setData :: Int -> TreePos Full NodeData -> TreePos Full NodeData
    setData = (invalidate . ) . setLabel . Right
    
    main = let tree1 = Node (Left True) [Node (Right 1) [], Node (Right 2) []]
               Just cursor = firstChild (fromTree tree1)
               tree2 = setData 3 cursor
           in do putStrLn (drawTree (fmap show tree1))
                 putStrLn (drawTree (fmap show (toTree tree2)))
                 putStrLn $ "Cursor at "++show (label tree2)
    

    Output:

    Left True
    |
    +- Right 1
    |
    `- Right 2
    
    Left False
    |
    +- Right 3
    |
    `- Right 2
    
    Cursor at Right 3
    

提交回复
热议问题