让我们说我们有一个具有这个定义的类型:
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
这样的东西,但我认为这不是一个好主意。
答案 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] -> Bool
和any 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