【发布时间】:2011-12-10 14:27:03
【问题描述】:
如何定义一个 Haskell 函数,它将一个函数应用于二叉树中的每个值?所以我知道它类似于map 函数——它的类型是:
mapT :: (a -> b) -> Tree a -> Tree b
但仅此而已......
【问题讨论】:
-
这是作业吗?如果是这样,请相应地标记。
标签: algorithm haskell binary-tree
如何定义一个 Haskell 函数,它将一个函数应用于二叉树中的每个值?所以我知道它类似于map 函数——它的类型是:
mapT :: (a -> b) -> Tree a -> Tree b
但仅此而已......
【问题讨论】:
标签: algorithm haskell binary-tree
您可以声明类Functor 的实例。这是允许映射函数的数据类型的标准类。请注意fmap 的类型与您的mapT 的类型有多相似:
class Functor f where
fmap :: (a -> b) -> f a -> f b
假设你的树被定义为
data Tree a = Node (Tree a) (Tree a) | Leaf a
deriving (Show)
那么你可以这样声明Functor的实例:
instance Functor Tree where
fmap f (Node l r) = Node (fmap f l) (fmap f r)
fmap f (Leaf x) = Leaf (f x)
你可以这样使用它:
main = do
let t = Node (Node (Leaf 1) (Leaf 2)) (Leaf 3)
let f = show . (2^)
putStrLn $ "Old Tree: " ++ (show t)
putStrLn $ "New Tree: " ++ (show . fmap f $ t)
输出:
Old Tree: Node (Node (Leaf 1) (Leaf 2)) (Leaf 3)
New Tree: Node (Node (Leaf "2") (Leaf "4")) (Leaf "8")
为方便起见,您也可以定义:
mapT = fmap
当然,你可以在没有类型类的情况下做到这一点,但如果你使用标准函数,它会使代码对其他人更具可读性(每个人都知道fmap 的通常行为)。
【讨论】:
我会假装这是家庭作业,而不是给出所有答案。如果我弄错了,我很抱歉。
您的Tree 类型可能看起来像这样:
data Tree a = TreeNode a (Tree a) (Tree a) | EmptyNode
这里有两种情况,您需要为每种情况编写一个mapT 实现:
TreeNode,它带有一个a 类型的值,并且有一个左子节点和一个右子节点。这种情况下需要做什么?EmptyNode。这种情况下需要做什么?【讨论】:
地图功能的基本格式适用于两者。我们来看一下list的map函数的定义:
map f (x:xs) = f x : map f xs
map _ [] = []
我们可以这样概括:
您真正需要的只是查看您的构造函数,map 函数应该就位。
【讨论】:
map f (x:xs) = f x : map f xs吗?
如果输入和输出应该是排序二叉树,这是一个有趣的问题。如果你只是天真地遍历树并应用函数,输出树可能不再排序。例如,考虑函数是否是非线性的,比如
f(x) = x * x - 3 * x + 2
如果输入有 { 1, 2, 3, 4 },那么输出将有 {2, 0, 0, 2 }。输出树应该只包含 0 和 2 吗?
如果是这样,您可能需要在剥离和处理输入树时迭代地构建输出树。
【讨论】: