从镜头列表创建遍历
Create a traversal from a list of lenses
假设我们在数据结构 S a
上有一个镜头列表 [Lens' (S a) a]
。我想用同样的方法修改数据结构中每个镜头的焦距
我可以这样做:
s :: S a
s = _
ls :: [Lens' (S a) a]
ls = [a, b, c]
a, b, c = _
f :: a -> a
f = _
s' :: S a
s' = s
& a %~ f
& b %~ f
& c %~ f
没关系,但如果我有 10、100 个镜头怎么办?我想要一些东西
喜欢
s' :: S a
s' = s & ls ??? f
(???) :: *
我在哪里找不到运算符 (???)
。
或许也可以把ls
转成遍历,直接用(%~)
,我
不知道。
你有什么想法吗?
第一个问题是:那个类型是非法的。正如该问题中所讨论的,要将镜头放入容器中,您需要具体化镜头。完成后,您可以通过应用 (%~ f)
将每个镜头变成一个函数,然后通过简单的折叠来组合这些函数。
你得到的不是一个镜头,也不是一个遍历,而只是一个S a -> S a
类型的函数(和你从a %~ f
得到的一样)。我发现 a discussion 为什么通常不可能按照您提到的您希望的方式将多个镜头、设置器或遍历组合成一个遍历。
这是我上面概述的想法的实现。
data S a = S {_x, _y :: a} deriving Show
makeLenses ''S
ls :: [ReifiedLens' (S (S Int)) Int]
ls = [Lens (x.x), Lens (y.y)]
overEach :: [ReifiedLens' s a] -> (a -> a) -> (s -> s)
overEach ls f s = foldr applySetter s ls
where applySetter (Lens l) acc = acc & l %~ f
s :: S (S Int)
s = S (S 1 2) (S 3 4)
λ> s & overEach succ ls
S {_x = S {_x = 2, _y = 2}, _y = S {_x = 3, _y = 5}}
(???) :: [ReifiedLens' (s a) a] -> (a -> a) -> s a -> s a
reLenses ??? f = foldl (.) identity $ map ((%~ f) . runLens) reLenses
将镜头封装在 Lens
构造函数中以获得 ReifiedLens'
。
假设我们在数据结构 S a
上有一个镜头列表 [Lens' (S a) a]
。我想用同样的方法修改数据结构中每个镜头的焦距
我可以这样做:
s :: S a
s = _
ls :: [Lens' (S a) a]
ls = [a, b, c]
a, b, c = _
f :: a -> a
f = _
s' :: S a
s' = s
& a %~ f
& b %~ f
& c %~ f
没关系,但如果我有 10、100 个镜头怎么办?我想要一些东西 喜欢
s' :: S a
s' = s & ls ??? f
(???) :: *
我在哪里找不到运算符 (???)
。
或许也可以把ls
转成遍历,直接用(%~)
,我
不知道。
你有什么想法吗?
第一个问题是(%~ f)
将每个镜头变成一个函数,然后通过简单的折叠来组合这些函数。
你得到的不是一个镜头,也不是一个遍历,而只是一个S a -> S a
类型的函数(和你从a %~ f
得到的一样)。我发现 a discussion 为什么通常不可能按照您提到的您希望的方式将多个镜头、设置器或遍历组合成一个遍历。
这是我上面概述的想法的实现。
data S a = S {_x, _y :: a} deriving Show
makeLenses ''S
ls :: [ReifiedLens' (S (S Int)) Int]
ls = [Lens (x.x), Lens (y.y)]
overEach :: [ReifiedLens' s a] -> (a -> a) -> (s -> s)
overEach ls f s = foldr applySetter s ls
where applySetter (Lens l) acc = acc & l %~ f
s :: S (S Int)
s = S (S 1 2) (S 3 4)
λ> s & overEach succ ls
S {_x = S {_x = 2, _y = 2}, _y = S {_x = 3, _y = 5}}
(???) :: [ReifiedLens' (s a) a] -> (a -> a) -> s a -> s a
reLenses ??? f = foldl (.) identity $ map ((%~ f) . runLens) reLenses
将镜头封装在 Lens
构造函数中以获得 ReifiedLens'
。