我可以使用“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)的原因是我们需要在更新节点之前更新子节点,这意味着需要排序。不可能进行同时指向一个节点和该节点的子节点的遍历。
我可以很容易地得到 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)的原因是我们需要在更新节点之前更新子节点,这意味着需要排序。不可能进行同时指向一个节点和该节点的子节点的遍历。