计算树中叶子的数量

NuN*_*uNu 1 tree haskell

使用Haskell,我正在编写一个函数来计算树中叶子的总数.我已经将树定义为:

data Tree a = Leaf | Node a (Tree a) (Tree a)
Run Code Online (Sandbox Code Playgroud)

我通过以下方式编写了一个函数:

countL :: Tree a -> Int
countL Leaf = 1
countL (Node x tL tR) = (countL tL) + (countL tR)
Run Code Online (Sandbox Code Playgroud)

这有效,但我想通过使用fold函数做同样的事情更进一步.我有一个工作折叠函数的树,我通过这样做定义:

mytFold :: (a -> b -> b -> b) -> b -> Tree a -> b
mytFold f g Leaf = g
mytFold f g (Node a xl xr) = f a (mytFold f g xl) (mytFold f g xr)
Run Code Online (Sandbox Code Playgroud)

我试图包含fold函数(也使用了我通过这样做定义的辅助函数:

countL' :: Tree a -> Integer
countL' Leaf = 1
countL' = mytFold leafy 0 where
        leafy tL tR = tL + tR
Run Code Online (Sandbox Code Playgroud)

但是我得到了一些奇怪的错误.有没有人对什么是错的有任何见解?

huo*_*uon 5

有两个句法/类型问题.首先,每个顶级绑定必须具有相同数量的参数,所以

countL' Leaf = ..
countL' = ..
Run Code Online (Sandbox Code Playgroud)

无效.一个解决方案是

countL' Leaf = ..
countL' tree = mytFold leafy 0 tree
Run Code Online (Sandbox Code Playgroud)

一旦你完成了这个,那么GHC就会给你一个错误

    Couldn't match expected type `Integer -> Integer'
                with actual type `Integer'
    Expected type: Integer -> Integer -> Integer -> Integer
      Actual type: Integer -> Integer -> Integer
    In the first argument of `mytFold', namely `leafy'
    In the expression: mytFold leafy 0 tree
Run Code Online (Sandbox Code Playgroud)

这是因为mytFold需要一个3参数函数作为它的第一个参数,并且leafy只需要2.通过使用修复它leafy _ tL tR = tL + tR.


但是,一旦你完成了这个,你会发现这给出了错误的答案:countL' (Node 1 Leaf Leaf) == 0.一种可能使解决方案清晰的方法是删除countL' Leaf案例,并尝试写作countL折叠.即

countL'' = mytFold f a
Run Code Online (Sandbox Code Playgroud)

在这里你必须做决定什么fa是(提示:你已经有了f == leafy == const (+)).考虑mytFold leafy a Leaf.