lens
提供holesOf
,这是这个假设函数的一个更通用和更强大的版本:
holesList :: Traversable t
=> t a -> [(a, a -> t a)]
给定一个容器,holesList
生成一个容器元素列表以及替换这些元素的函数。
的类型holesList
,与 real 的类型一样holesOf
,未能捕捉到生成的对数将等于容器元素数的事实。因此,一个更漂亮的类型将是
holes :: Traversable t
=> t a -> t (a, a -> t a)
我们可以holes
通过使用holesList
来创建一个列表,然后遍历State
以将元素重新插入。但这并不令人满意,原因有两个,其中一个会产生实际后果:
slurping 代码将有一个无法访问的错误调用来处理列表在遍历完成之前运行为空的情况。这很恶心,但对于使用该功能的人来说可能并不重要。
向左无限延伸的容器,或在左侧触底的容器根本不起作用。向左延伸很远的容器处理起来效率很低。
我想知道是否有任何方法可以解决这些问题。Magma
使用类似镜头的东西很可能捕获遍历的形状:
data FT a r where
Pure :: r -> FT a r
Single :: a -> FT a a
Map :: (r -> s) -> FT a r -> FT a s
Ap :: FT a (r -> s) -> FT a r -> FT a s
instance Functor (FT a) where
fmap = Map
instance Applicative (FT a) where
pure = Pure
(<*>) = Ap
runFT :: FT a t -> t
runFT (Pure t) = t
runFT (Single a) = a
runFT (Map f x) = f (runFT x)
runFT (Ap fs xs) = runFT fs (runFT xs)
现在我们有
runFT . traverse Single = id
traverse Single
使一棵树充满元素以及将它们构建到容器中所需的功能应用程序。如果我们替换树中的一个元素,我们可以runFT
得到一个替换了该元素的容器。不幸的是,我被困住了:我不知道下一步会是什么样子。
模糊的想法:添加另一个类型参数可能有助于更改元素类型。该Magma
类型做了类似的事情,并且至少可以追溯到 Zemyla 对 Van Laarhoven 的博客文章的评论关于FunList
.