Tree building function in Haskell (Homework)

倖福魔咒の 提交于 2020-01-02 22:06:11

问题


data Tree a = Leaf | Node (Tree a) a (Tree a) deriving (Eq, Show)

unfoldTree:: (b -> Maybe (b, a, b)) -> b -> Tree a
unfoldTree f b =
    case f b of
      Nothing -> Leaf
      Just (lt, x, rt) -> Node (unfoldTree f lt) x (unfoldTree f rt)

Given the two piece of information above, I'm asked to implement a tree building function.

and my attempt is

treeBuild :: Integer -> Tree Integer
treeBuild 0 = Leaf
treeBuild n = treeUnfold (\b -> if b < 2^n-1 
                then Just(2*b, b + 1, 2*b + 1) 
                else Nothing) 
                0

The base case works where n = 0 works fine but I know the function is completely wrong. Can someone re-explain to me how would a 3-tuple Just work? In a normal unfold, the first element in a Just would be the element I want and the second element would be used to continue unfolding but how does this work in a 3-tuple Just?

As example output: treeBuild 2 ----> Node (Node Leaf 0 Leaf) 1 (Node Leaf 2 Leaf)

Edit: I'm not completely sure how Just works here, for the case of Just(2*b, b + 1, 2*b + 1) where b starts at 0, does it become Just(0, 1, 0)? How do I actually increment b?


回答1:


I think you omitted a space when pasting the definition of unfoldTree. Should it be this?

unfoldTree f b =
    case f b of ...

There's nothing intrinsically meaningful about Maybe (b, a, b), but in this particular case you can see that unfoldTree binds the items in the tuple to lt, x, and rt. The middle value x is used to create a node, and lt and rt are used to seed the recursive calls to unfoldTree.

To explain your example output, note that n is always bound to 2. The initial 0 argument to treeUnfold means the (\b -> ...) function first checks 0 < 2^n-1, then yields Just (2*0, 0+1, 2*0+1).

The middle value, 0+1 is the value of the root node in your tree. The left subtree is built similarly except b is now 2*0, and the right subtree is built with b as 2*0+1.


You mention this is homework which is supposed to build a tree with 2^n - 1 nodes. I'm going to guess that Leaf values don't count and that you want to number these nodes in breadth-first order, and hopefully this example gets you in the neighborhood. Here's how to do that:

treeBuild :: Int -> Tree Int
treeBuild n = treeUnfold (\b -> if b < 2^n - 1
                                   then Just (2*b+1, b, 2*b+2)
                                   else Nothing) 0

The way I arrived at this is by drawing a binary tree with depth 3. I numbered the nodes starting with the root as 0, the left node as 1 and the right node as 2. The bottom nodes are numbered from left to right starting with 4 and ending at 7.

Now the pattern is visible: if the current node is numbered b, his left and right nodes are numbered 2*b+1 and 2*b+2 respectively. Since 2^n - 1 is the total number of nodes in a tree of depth n, and I'm numbering nodes in breadth-first order, returning Nothing when b >= 2^n-1 ensures I stop after filling the tree up to depth n.



来源:https://stackoverflow.com/questions/15538151/tree-building-function-in-haskell-homework

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!