我有一个玫瑰树结构,我想Traversable
为它写一个实例。所以我从以下开始:
data Tree a = Tree a [Tree a] deriving (Show)
instance Functor Tree where
fmap f (Tree x subs) = Tree (f x) (fmap (fmap f) subs)
我做了它的深度优先变体:
newtype Depth a = Depth (Tree a) deriving (Show)
depth :: Tree a -> [a]
depth (Tree x subs) = x : concatMap depth subs
instance Functor Depth where
fmap f (Depth t) = Depth $ fmap f t
instance Foldable Depth where
foldMap f (Depth t) = mconcat $ f <$> depth t
instance Traversable Depth where
traverse f (Depth t) = Depth <$> go t
where go (Tree x subs) = Tree <$> f x <*> traverse go subs
然后我尝试了广度优先的变体:
newtype Breadth a = Breadth (Tree a) deriving (Show)
breadth :: Tree a -> [a]
breadth tree = go [tree]
where
go [] = []
go (Tree x subs:q) = x : go (q <> subs)
instance Functor Breadth where
fmap f (Breadth t) = Breadth $ fmap f t
instance Foldable Breadth where
foldMap f (Breadth t) = mconcat $ f <$> breadth t
instance Traversable Breadth where
traverse f (Breadth t) = ???
我意识到这个的广度和深度优先变体Traversable
应该是相同的。是这样吗?我不相信我实际上在任何地方都读过这篇文章,但遍历与元素的顺序无关?
如果是这样,这有点奇怪,因为Traversable
可以直接实现 for Tree
,这意味着Foldable
需要实现 for Tree
,但显然有多种方式Foldable
可以实现。