问题
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 treet
by applying functionf
. (The leaves of the tree are scanned from left to right).foldListTree
is invoked as:
foldListTree f base t
wheref
is the combining function of typea->a->a
. The type offoldListTree
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
andNODE
in all caps, usually one writes this in camelcase, soListLeaf
andListNode
.
Note: It might be better that your
ListLeaf
stores ana
, 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