我是 Control.Lens
的新手,正在尝试将两个镜头 "并行"(而不是按顺序)组合在一起,就像使用 `Control.Arrow.&&&` 一样。
如果我采用 lens
文档中的示例:
`data Foo a = Foo { _baz :: Int, _bar :: Int, a }
我希望能够做以下的事情:
>> let foo = (bar &&& baz) .~ (1, 20) $ Foo undefined undefined "FOO"
>> foo ^. (bar &&& baz)
(1, 20)
我已经到处寻找,但无法找到一种方法来这样做。是因为:
- (&&&)存在其他名称,并且我错过了它。
- 它没有用。我不应该需要它,因此没有人去实现它。
- 可以用另一种方式轻松完成(使用both或<*>)
更新
&&&
可以这样实现:(/|\) :: Lens' f a -> Lens' f b -> Lens' f (a, b)
a /|\ b = lens getBoth setBoth where
getBoth f = (f ^. a, f ^. b)
setBoth f (v, w) = a .~ v $ f' where
f' = b .~ w $ f
barz :: Lens' Foo (Int, Int)
barz = bar /|\ baz
然而,它需要一个类型签名,这有点烦人。
l
应该是f
。(顺便说一句,“编辑必须至少为6个字符”真的很烦人) - chia &&& a
违反了 lens 定律,但这有什么关系?重要的是bar &&& baz
没有违反,这才是最重要的。我可以找到参数(a,b),使得lens a b
违反 lens 定律。但这并不能阻止lens
函数成为有效的函数。此外,&&&
可以被实现,并且似乎可行(请参见更新部分)。 - mb14