我有数据类型
data KTree a = Empty | Leaf a | Node a [KTree a] deriving (Eq, Show)
我想编写一个函数,该函数返回true或false,以确定项目是否包含在我的树中。
ktreeContains :: Eq a => a -> (KTree a) -> Bool
ktreeContains _ Empty = False
ktreeContains y (Leaf x) = (x==y)
-- code for nodes goes here
所以我意识到我需要找到节点本身是否是项目,然后递归调用节点子节点的ktreeContains但我不明白如何做到这一点,因为每个节点可以有很多子节点。
我认为到目前为止我所拥有的代码是正确的,但如果没有,请随时纠正我。
感谢任何帮助,谢谢。
答案 0 :(得分:3)
ktreeContains y (Node x ts) = x == y || any (ktreeContains y) ts
只是出于兴趣,Leaf x
和Node x []
之间有什么区别?
答案 1 :(得分:2)
ktreeContains y (Node x ts) = x == y || (any . ktreeContains) y ts
答案 2 :(得分:1)
我很无聊所以我决定使用Data.Foldable
类型类推广解决方案。
import Data.Monoid
import Data.Foldable hiding (any)
data KTree a = Empty | Leaf a | Node a [KTree a] deriving (Ord, Eq, Show)
ktreeContains :: Eq a => a -> (KTree a) -> Bool
ktreeContains _ Empty = False
ktreeContains y (Leaf x) = (x==y)
-- code for nodes goes here
ktreeContains y (Node x ts) = x == y || any (ktreeContains y) ts
example1 = Empty
example2 = Leaf 1
example3 = Node 1 [Leaf 2]
example4 = Node 2 [Leaf 1, Node 4 [Leaf 5, Leaf 3]]
ktreeContainsF :: Eq a => a -> KTree a -> Bool
ktreeContainsF y = getAny . foldMap (Any.(==y))
instance Foldable KTree where
foldMap f (Empty) = mempty
foldMap f (Leaf a) = f a
-- work out a possible ordering thats better than this
-- it works for now since we are only dealing with Equality
foldMap f (Node a x) = f a `mappend` (mconcat . map (foldMap f)) x
ktreeContains
和ktreeContainsF
是相同的函数,但ktreeContainsF
KTree
的遍历由Data.Foldable
类处理。由于foldMap
会返回Monoid
,因此可以使用Any
monoid来合并搜索结果。
如果有助于更好地理解这一点,ktreeContainsF
是ktreeContainsMonoid
的更通用版本,定义为
ktreeContainsMonoid y = getAny . Data.Foldable.foldl
-- combination function, implicit when using FoldMap
(\z x-> z `mappend` Any (x == y)) mempty -- also implicit in foldMap