测试树的存在叶子的功能

时间:2012-09-08 13:52:55

标签: haskell

让我们说我们有一个具有这个定义的类型:

data Tree a = Leaf a | Branch [Tree a] deriving (Show,Eq)

我想要的是一个返回布尔值的函数。 False如果我的二叉树包含一个Leaf,如果没有,则True

这是我的代码:

tester :: Tree a -> Bool
tester (Leaf x) = False
tester (Branch y) = if (Branch (map tester y)) then True else False

我知道这个问题的主要问题是无法评估(Branch (map tester y)),但我真的不知道如何解决它。

我可以添加一个新子句,例如像tester (Branch y) = True这样的东西,但我认为这不是一个好主意。

2 个答案:

答案 0 :(得分:5)

tester不是一个描述性名称,因此我将其称为leafless,并且更容易考虑leafy

leafy :: Tree a -> Bool
leafy (Leaf x) = True              -- yup - there's a leafy
leafy (Branch ts) = any leafy ts   -- yes if there are any leaves (recursive)

我们只需要否定结果即可获得我们想要的结果。

leafless :: Tree a -> Bool
leafless = not.leafy

any :: (a -> Bool) -> [a] -> Boolany f xs检查列表中的任何元素是否满足测试(谓词)f。它的工作方式类似于or (map f xs)。)

您不能(Branch (map tester y)),因为构造函数Branch的类型为[Tree a] -> Tree a,但map tester y的类型为[Bool],而不是[Tree a]。你不需要在右边写Branch;你已经在左侧正确地使用它来与分支进行模式匹配 - 它不再需要了。

答案 1 :(得分:4)

编写leafless比写自己的递归更有惯用方法:

{-# LANGUAGE DeriveFoldable #-}
import qualified Data.Foldable as F

data Tree a = Leaf a | Branch [Tree a] deriving (Show,Eq,F.Foldable)

leafless :: Tree a -> Bool
leafless = F.foldl (\x y -> False) True

甚至更短:

leafless :: Tree a -> Bool
leafless = null . F.toList

此外,您的树类型称为“玫瑰树”,并且已在Data.Tree