如何定义一个Haskell函数,它将函数应用于二叉树中的每个值?所以我知道它类似于map
函数 - 它的类型是:
mapT :: (a -> b) -> Tree a -> Tree b
但那是关于它......
答案 0 :(得分:9)
您可以声明类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
的通常行为),它会使代码对其他代码更具可读性。
答案 1 :(得分:6)
我会假装这是作业而不是放弃所有的答案。如果我弄错了,我道歉。
可能您的Tree
类型看起来像这样:
data Tree a = TreeNode a (Tree a) (Tree a) | EmptyNode
这里有两种情况,您需要为每种情况编写一个mapT
实现:
TreeNode
,其值为a
,并且具有左子项和右子项。在这种情况下需要做什么?EmptyNode
。在这种情况下需要做什么?答案 2 :(得分:4)
地图功能的基本格式适用于两者。让我们看一下列表的map函数的定义:
map f (x:xs) = f x : map f xs
map _ [] = []
我们可以这样概括:
你真正需要的只是看看你的构造函数,地图函数应该到位。
答案 3 :(得分:1)
有趣的问题,如果输入和输出应该是排序二进制树。如果您只是天真地遍历树并应用该函数,则可能不再对输出树进行排序。例如,考虑函数是否是非线性的,如
f(x) = x * x - 3 * x + 2
如果输入有{1,2,3,4},则输出将具有{2,0,0,2}。输出树是否应仅包含0和2?
如果是这样,您可能需要在删除并处理输入树时迭代地构建输出树。