How can I write general开发者_如何学Cized foldr and foldl function for generic Haskell trees, given this definition?
data (Eq a, Show a) => Tree a = Void | Node a [Tree a]
deriving (Eq, Show)
treefoldr :: (Eq a, Show a) =>
(a -> b -> c) -> c -> (c -> b -> b) -> b -> Tree a -> c
treefoldl :: (Eq a, Show a) =>
(b -> a -> c) -> c -> (c -> b -> b) -> b -> Tree a -> c
Even if I can understand how foldr and foldl functions work in Haskell, I'm not quite sure how to write this generalized function for trees.
EDIT: I tried something like this (not even compiling):
treefoldr _ g1 _ _ Void = g1
treefoldr f1 g1 f2 g2 (Node a ts) = f1 a (foldr f2 g2 ts)
EDIT 2: another try...
treefoldr _ z1 _ _ Void = z1
treefoldr f z1 g z2 (Node a ts) =
f a (foldr g z2 (map (\x -> treefoldr f z1 g z2 x) ts))
treefoldl _ z1 _ _ Void = z1
treefoldl f z1 g z2 (Node a ts) =
f (foldl g z2 (map (\x -> treefoldl f z1 g z2 x) ts)) a
treefoldr is working, however treefoldl not:
Couldn't match expected type `c' against inferred type `b' `c' is a rigid type variable bound by the type signature for `treefoldl' at trees.hs:47:42 `b' is a rigid type variable bound by the type signature for `treefoldl' at trees.hs:47:32 In the first argument of `foldl', namely `g' In the first argument of `f', namely `(foldl g z2 (map (\ x -> treefoldl f z1 g z2 x) ts))' In the expression: f (foldl g z2 (map (\ x -> treefoldl f z1 g z2 x) ts)) a
The error message in full:
Couldn't match expected type `c' against inferred type `Tree a'
`c' is a rigid type variable bound by
the type signature for `treefoldr' at so.hs:5:14
Expected type: [c]
Inferred type: [Tree a]
In the third argument of `foldr', namely `ts'
In the second argument of `f1', namely `(foldr f2 g2 ts)'
That means that
tsis of type[Tree a]- you are using it as the third argument to
foldr foldrexpects its third argument to be of type[c][c]and[Tree a]are different types, hence this is an error
So you need to process ts into something of type [c] and pass that result to foldr instead of ts itself. The map function would be a good place to start.
I don't know if such a solution is allowed for your homework, but when the use of type classes is okay, you could write
import Data.Foldable
import Data.Monoid
data Tree a = Void | Node a [Tree a]
deriving (Eq, Show)
instance Foldable Tree where
foldMap f Void = mempty
foldMap f (Node value []) = f value
foldMap f (Node value (x:xs)) = foldMap f x `mappend` foldMap f (Node value xs)
Using this definition the implementation of your functions should be trivial, as Foldable defines a foldl, foldr etc.
I have talk to the same your professor, at the end I found the right solution:
treefoldr :: (Eq a, Show a) => (a -> b -> c) -> c -> (c -> b -> b) -> b -> Tree a -> c
treefoldr _ z1 _ _ Void = z1
treefoldr f z1 g z2 (Node a ts) = f a $ foldr (aggr) z2 ts
where
aggr t z = g (treefoldr f z1 g z2 t) z
treefoldl :: (Eq a, Show a) => (b -> a -> c) -> c -> (c -> b -> b) -> b -> Tree a -> c
treefoldl _ z1 _ _ Void = z1
treefoldl f z1 g z2 (Node a ts) = f (foldl (aggr) z2 ts) a
where
aggr z t = g (treefoldl f z1 g z2 t) z
Regards
加载中,请稍侯......
精彩评论