【发布时间】:2011-02-13 20:56:25
【问题描述】:
如何为通用 Haskell 树编写通用的 foldr 和 foldl 函数?
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
即使我能理解 foldr 和 foldl 函数在 Haskell 中的工作原理,我也不太清楚如何为树编写这个通用函数。
编辑:我尝试过这样的事情(甚至没有编译):
treefoldr _ g1 _ _ Void = g1
treefoldr f1 g1 f2 g2 (Node a ts) = f1 a (foldr f2 g2 ts)
EDIT 2:再试一次...
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 工作正常,但 treefoldl 不工作:
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
【问题讨论】:
-
你说它没有编译。你明白错误信息了吗?
-
@Dave Hinton:
Couldn't match expected type c against inferred type Tree a,我认为treefoldr必须返回一个类型c,而它返回的是一个完整的Tree a? -
错误信息是否也说
In the third argument of `foldr', namely `ts'? -
顺便说一句,去掉
Tree上的类型类上下文。它们没用,因为你仍然需要到处重复它们。