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

Haskell 我可以使用Control.Lens.Plated对存储在分支中的项目进行遍历吗?,haskell,generic-programming,haskell-lens,Haskell,Generic Programming,Haskell Lens,我可以轻松地对存储在叶子中的项目进行遍历: 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如果我从一个分支中取出一些东西,它就不能继续前进。对于分支中的数据,我似乎能达到的最佳效果是折叠: data Tr

我可以轻松地对存储在叶子中的项目进行
遍历

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
如果我从一个分支中取出一些东西,它就不能继续前进。对于分支中的数据,我似乎能达到的最佳效果是
折叠

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
显然可以手动构造一个
遍历
,因为可以使该
可遍历:

instance Traversable Tree where
    sequenceA Lf = pure Lf
    sequenceA (Br x l r) = Br <$> x <*> sequenceA l <*> sequenceA r
实例可遍历树,其中
sequenceA Lf=纯Lf
sequenceA(Br x l r)=Br x sequenceA l Sequencer

Plated
能自动为我们做吗?

我不相信使用
Plated
做这件事是可能的,但使用
模板
从以下方面做是微不足道的:

模板查找一个类型的所有元素,这些元素可以在不经过相同类型的情况下访问


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


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

如果您只想
遍历
,可以启用
-XDeriveTraversable
,让GHC为您派生可遍历实例。@Zeta这只是一个示例,但我实际使用的数据类型是单态的,有不同的分支,其中包含不同类型的数据。老实说,我问这个问题更多是出于好奇(也许是为了将来的实用程序):在我目前的情况下,在几分钟内手动编写遍历显然更有意义,而不是等待几天有人回答我的堆栈溢出问题!
branchData :: Data a => Traversal' (Tree a) a
branchData = template