This is a question from Chapter 11, Algebraic Datatypes of "Haskell Programming from first principles":
data BinaryTree a =
Leaf
| Node (BinaryTree a) a (BinaryTree a)
deriving (Eq, Ord, Show)
We do not actually insert a value into an existing tree; each time we want to insert a value into the data structure, we build a whole new tree:
insert' :: Ord a => a -> BinaryTree a -> BinaryTree a
insert' b Leaf = Node Leaf b Leaf
insert' b (Node left a right)
| b == a = Node left a right
| b < a = Node (insert' b left) a right
| b > a = Node left a (insert' b right)
This is a map function for the data structure of BinaryTree:
mapTree :: (a -> b) -> BinaryTree a -> BinaryTree b
mapTree _ Leaf = Leaf
mapTree f (Node left a right) =
Node (mapTree f left) (f a) (mapTree f right)
Write foldr for BinaryTree
Given the definition of BinaryTree we have provided, write a catamorphism for the binary trees.
-- any traversal order is fine
foldTree :: (a -> b -> b)
-> b
-> BinaryTree a
-> b
The type above is a hint for those that don’t convert the tree into a list before applying the folding function.
Rewrite map for BinaryTree
Using the foldTree you just wrote, rewrite mapTree using foldTree. The absence of an Ord constraint is intentional, you don’t need to use the insert function.
mapTree' :: (a -> b)
-> BinaryTree a
-> BinaryTree b
mapTree' f bt =
foldTree undefined undefined undefined
I managed to get an answer that works for the first question about foldr with a lot of help from: https://github.com/johnchandlerburnham/hpfp/blob/master/11/BinaryTree.hs
My answer:
foldTree f b Leaf = b
foldTree f b (Node left a right)
= (foldTree f tempb left) where
tempb = (f a) tempright
tempright = foldTree f b right
However, for the second question about writing a new mapTree for BinaryTree, I could not find an answer to that. The original mapTree is provided above. Even the answer at the johnchandlerburnham link uses a different foldtree.
Could someone please help get a workable answer for the second question based on my answer to the first question? Or is another answer for the first question required?
A tree for testing could be:
testTree :: BinaryTree Integer
testTree =
Node (Node Leaf 3 Leaf) 1 (Node Leaf 4 Leaf)
cataon trees, we should have a signature likefoldTree :: (b -> a -> b -> b) -> b -> BinaryTree a -> b, with the additionalb ->representing the left subtree. Are you sure about that signature? It looks like there is some confusion betweenfoldras inFoldable(which flattens the tree into a list) andcatawhich preserves the full structure (being the catamorphism). You need the latter formapTree(it is calledfoldTree1in that file, IIUC). - chidata Bool = False | Truebool :: a -> a -> Bool -> a, anddata Maybe a = Nothing | Just amaybe :: b -> (a -> b) -> Maybe a -> b. - maxloodata Either a b = Left a | Right beither :: (a -> c) -> (b -> c) -> Either a b -> c. The book just says "See if you can notice a pattern". Can you notice any pattern? - maxloocatareplaces constructor applications with arbitrary function applications. E.g. a value of typeNode Leaf 3 (Node Leaf 4 Leaf)can be applied tofoldTree node leafand the result is (the evaluation of)node leaf 3 (node leaf 4 leaf), wherenodeandleafare arbitrary arguments. To type check, we need a constantleaf :: band a functionnode :: b -> Int -> b -> bas arguments forfoldTree(possibly further generalizingInttoa). - chimaybedoes the same.maybe n japplied toNothingoutputsn, and applied toJust xoutputsj x-- again, replacing constructors with arbitrary functions/constants.foldr c nsimilarly maps1 : 2 : []which is(:) 1 ((:) 2 [])toc 1 (c 2 n)and is a catamorphism for lists. - chi