Haskell中的Filter函数

时间:2013-06-11 23:56:01

标签: haskell

我的树定义如下:

data Tree a = Leaf a | Node (Tree a) (Tree a) deriving (Show)

我想编写一个过滤函数,它只选择数组的每个第3个元素(第1,第4,第7,......)。例如,假设我的树如下:

Node 
    (Node 
        (Node 
            (Leaf 'a') 
            (Leaf 'b')) 
        (Leaf 'c'))
    (Node 
        (Node 
            (Leaf 'd') 
            (Leaf 'e')) 
        (Leaf 'f'))

然后,过滤器函数应该生成一个新树:

Node (Leaf 'a') (Leaf 'd')

1 个答案:

答案 0 :(得分:4)

这是适合你的游戏计划。

  1. 编写一个函数,将函数应用于树的每个元素。

    mapTree :: (a -> b) -> Tree a -> Tree b
    

    (加分:将Tree设为Functor个实例,并使用fmap代替mapTree

  2. 编写一个函数,按照从左到右的顺序标记树的元素。

    labelTree :: Tree a -> Tree (Integer, a)
    

    (提示:你需要一个辅助函数,它接受一个“当前标签”并返回带标签的树和一个新标签;即:: Integer -> Tree a -> (Tree (Integer, a), Integer)。这个函数的分支情况如下:

    aux n (Branch l r) = 
        let (l', n')  = aux n l
            (r', n'') = aux n' r in
        (Branch l' r', n'')
    

    仔细阅读此代码,然后看看您是否可以提出Leaf案例

    (奖励:使用State monad

  3. 编写一个函数,删除不满足条件的树的元素。

    filterTree :: (a -> Bool) -> Tree a -> Maybe (Tree a)
    

    请注意,我们返回的是Maybe (Tree a)而不仅仅是Tree a - 这是因为如果没有符合条件的元素,我们需要返回一些内容,并且您的Tree类型会不允许空树。事实上,返回Maybe (Tree a)也使这个函数非常简单地递归写入。

  4. 结合使用这些函数来获取您正在寻找的功能 - 仅过滤掉可被3整除的标签的元素。

  5. 以这种方式分解它的好处在于,除了解决您的特定问题之外,您还编写了许多通用的工具来处理Tree类型。映射和过滤器是在实现数据结构时出现的非常常见的功能。

    高级: State的{​​{1}} monad奖励实现是另一种称为"traversal"的常见函数类型的特定情况:

    labelTree

    就像一张地图,但也结合了每个元素上可能出现的“效果”。超级双加奖金,如果你可以实现它然后用它来写traverse :: (Applicative f) => (a -> f b) -> Tree a -> f (Tree b)