Haskell - 树遍历:预订

时间:2014-03-04 03:54:35

标签: haskell types tree preorder

我对Haskell相当新,并且正在尝试从我的课程中完成作业。 我正在尝试创建一个预订单函数,以下列格式遍历树对象

preorder :: (a -> c) -> (b -> c) -> Tree a b -> [c]
preorder f g Empty = []
preorder f g (Leaf x) = [x]

My Tree类如下

data Tree a b = Empty | Leaf b | Branch a (Tree a b) (Tree a b)

定义预订单功能时,我会收到如下所示的错误。

Couldn't match expected type 'c' with actual type 'b'
'c' is a rigid type variable bound by the type signature for preorder :: (a -> c) -> (b -> c) -> Tree a b -> [c].
'b' is a rigid type variable bound by the type signature for preorder :: (a -> c) -> (b -> c) -> Tree a b -> [c].

它们发生在最后一个预订函数定义

preorder f g (Leaf x) = [x]

1 个答案:

答案 0 :(得分:4)

类型Tree a b包含带有b类型元素的树叶,除了空白树叶外,还包含类型为a的元素。您希望按预先访问树的每个节点,收集在f :: a -> c类型列表中应用函数g :: b -> c[c]结果。编译器抱怨您的preorder函数的原因是x的类型为b;这会强制cb统一。但这是一种不太通用的类型,而不是你向编译器指出的类型。作为练习,看看您是否可以为编译器接受的函数编写更具体的类型。提示:bc不同类型?

但是,您将获得一个函数g :: b -> c。将此函数应用于x会生成c类型的值,并且值可以收集到类型[c]的列表中。此列表可能或可能不包含ab类型的元素。您可以按以下方式重写符合给定签名的前序遍历:

preorder :: (a -> c) -> (b -> c) -> Tree a b -> [c]
preorder f g Empty          = []
preorder f g (Leaf b)       = [g b]
preorder f g (Branch a l r) = f a : preorder f g l ++ preorder f g r