我可以使用“Control.Lens.Plated”对存储在分支中的项目进行“遍历”吗?

Can I get a `Traversal` to items stored in branches using `Control.Lens.Plated`?

我可以很容易地得到 Traversal 存储在树叶中的物品:

data Tree a = Br (Tree a) (Tree a) | Lf a
    deriving (Data)

instance Plated (Tree a) where

makePrisms ''Tree

leaves :: Traversal' (Tree a) a
leaves = deep _Lf

但是 deep 如果我从树枝上拿东西,就无法继续前进。我似乎可以用分支中的数据实现的最好结果是 Fold:

data Tree a = Br a (Tree a) (Tree a) | Lf
    deriving (Data)

instance Plated (Tree a) where

makePrisms ''Tree

branchData :: Fold (Tree a) a
branchData = cosmos._Br._1

显然可以手动构造一个Traversal因为这个Tree可以制作Traversable:

instance Traversable Tree where
    sequenceA Lf = pure Lf
    sequenceA (Br x l r) = Br <$> x <*> sequenceA l <*> sequenceA r

可以 Plated 以某种方式自动为我们完成吗?

我认为使用 Plated 是不可能的,但是使用 Data.Data.Lens 中的 template 是微不足道的:

branchData :: Data a => Traversal' (Tree a) a
branchData = template

模板查找一个类型的所有元素,无需通过相同类型即可访问。


我可以从 Plated 得到的最接近遍历的东西(除了你提到的 cosmos 折叠)是 transformM :: (Monad m, Plated a) => LensLike' m a a。它可以用作 Setter 并且可以做一些其他的事情。

transformM 需要 Monad(而不是遍历所需的 Applicative)的原因是我们需要在更新节点之前更新子节点,这意味着需要排序。不可能进行同时指向一个节点和该节点的子节点的遍历。