有没有直接的方法将多个记录字段的setter组合到一个setter?

lef*_*out 6 haskell arrows lenses haskell-lens

import Control.Lens
import Control.Lens.TH

data Foo = Foo {
    _bar, _baz :: Int
   }
makeLenses ''Foo
Run Code Online (Sandbox Code Playgroud)

现在,如果我想修改两个int字段,我可以做

barbaz :: Setter' Foo Int
barbaz = sets $ \foo f -> foo & bar %~ f
                              & baz %~ f
Run Code Online (Sandbox Code Playgroud)

但这似乎是一种非常难看的手动方式.

使用镜头/箭头组合器可以直接实现吗?

Chr*_*ann 1

我以前遇到过这个问题,并且有一个适用于两个镜头的解决方案,将它们组合成一个遍历:

fields2 :: Lens' s a -> Lens' s a -> Traversal' s a
fields2 f1 f2 f s = (\v1 v2 -> s & f1 .~ v1 & f2 .~ v2) <$> f (s ^. f1) <*> f (s ^. f2)

barbaz = fields2 bar baz
Run Code Online (Sandbox Code Playgroud)

这可以像这样使用:

foo & barbaz %~ f
Run Code Online (Sandbox Code Playgroud)

它有点脏并且无法扩展,但它对我有用:D 如果有人发布更好的答案,我会很高兴!