假設我們有一個[Lens' (S a) a]關于資料結構的鏡頭串列S 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為遍歷并簡單地使用(%~),我不知道。
你有想法嗎?
uj5u.com熱心網友回復:
第一個問題是您實際上無法ls像在問題中所做的那樣定義串列:該型別是非法的。正如那個問題中所討論的,要將鏡頭放入容器中,您需要將鏡頭具體化。完成后,您通過應用將每個鏡頭變成一個函式(%~ f),然后將這些函式簡單折疊起來。
您得到的不是鏡頭或遍歷,而只是型別的函式S a -> S a(與您從 中得到的相同a %~ f)。我發現了一個關于為什么通常不可能以您提到的您可能希望的方式將多個鏡頭、設定器或遍歷組合成單個遍歷的討論。
這是我上面概述的想法的實作。
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}}
uj5u.com熱心網友回復:
(???) :: [ReifiedLens' (s a) a] -> (a -> a) -> s a -> s a
reLenses ??? f = foldl (.) identity $ map ((%~ f) . runLens) reLenses
將您的鏡頭包裹在Lens建構式中以獲得ReifiedLens'.
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/359165.html
