Find Sum of leaves

六月ゝ 毕业季﹏ 提交于 2020-01-15 03:13:29

问题


I am supposed to write a code such that

A polymorphic tree type with nodes of an arbitrary number of children might be represented as follows (note that the leaves store a list, and interior nodes store list of “ListTree”s):

data ListTree a = ListLEAF [a] | ListNODE [(ListTree a)]
 deriving (Show, Read, Eq)

Write a function foldListTree that takes a function (f), a base value (base), and a ListTree (t) and combines the values in the lists of the leaf notes in tree t by applying function f. (The leaves of the tree are scanned from left to right). foldListTree is invoked as:

foldListTree f base t where f is the combining function of type a->a->a. The type of foldListTree should be:

foldListTree :: (a -> a -> a) -> a -> ListTree a -> a

I am trying to read every node in the list but I guess it's getting into an infinite loop.

data ListTree a = ListLEAF [a] | ListNODE [(ListTree a)] deriving (Show, Read, Eq)


foldListTree :: (Num a) => (a -> a -> a) -> a -> ListTree a -> a 
foldListTree op base (ListLEAF []) = base
foldListTree op base (ListNODE []) = base
foldListTree op base (ListLEAF [a]) = foldr op base [a]
foldListTree op base (ListNODE b) = (op (foldListTree op base x) 
                                        (foldListTree op base (ListNODE xs)))
                                        where x:xs = b

t4 = ListNODE
       [ ListNODE
           [ ListLEAF [1,2,3]
           , ListLEAF [4,5]
           , ListNODE [ListLEAF [6], ListLEAF []]
           ]
       , ListNODE []
       , ListLEAF [7,8]
       , ListNODE [ListLEAF [], ListLEAF []]
       ]

Command: foldListTree (+) 0 t4

> Error : *** Exception: indi.hs:(86,1)-(90,54): Non-exhaustive patterns in function foldListTree


回答1:


It really helps if you turn on -Wall since Haskell can provide you a list of the patterns you did not cover.

The main problem is that you wrote as pattern:

foldListTree op base (ListLEAF [a]) = foldr op base [a]

So that means you restricted the pattern to singleton lists. Nowhere in the code, is there a pattern for a ListLEAF constructor that takes a list with an arbitrary number of elements.

You can however make the above a lot simpler by implementing two cases: one for each constructor. We can use foldListTree as folding function in the ListNODE case:

foldListTree :: Num a => (a -> a -> a) -> a -> ListTree a -> a 
foldListTree op base (ListLEAF x) = foldr op base x
foldListTree op base (ListNODE b) = foldr (flip (foldListTree op)) base b

This gives us:

Prelude> foldListTree (+) 0 t4
36

Note: Although strictly speaking not wrong, I find it odd to write LEAF and NODE in all caps, usually one writes this in camelcase, so ListLeaf and ListNode.

 

Note: It might be better that your ListLeaf stores an a, not an [a], since then you give more freedom what to store in your leaves. It does not exclude the possibility at all to store lists in the leaves, but you leave that decision to the user of the data type.



来源:https://stackoverflow.com/questions/58059220/find-sum-of-leaves

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