I have a Rose Tree structure and I wanted to write a Traversable
instance for it. So I started with the following:
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)
I did the depth-first variant of it:
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
Then I tried the breadth-first variant:
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) = ???
And I realized that the breadth and depth first variants of Traversable
for this should be the same. Is this the case? I don't believe I've actually read this anywhere but traversal is independent of the order of the elements?
If so, this gets a little weird because Traversable
can then be implemented directly for Tree
, which means that Foldable
needs to be implemented for Tree
, but there are obviously multiple ways that Foldable
can be implemented.