我是优秀的新手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
or <*>
)
Update
&&&
可以这样实现:
(/|\) :: 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
然而,它需要一个有点烦人的类型签名。
这个组合器可能无法实现。考虑:
> (baz &&& baz) .~ (1,5)
这个应该怎么办呢?
组合器的甚至更弱:
(/|\) :: Lens' s a -> Lens' s a -> Traversal' s a
a /|\ b = (a &&& b) . both
会违反法律:
例如,让我们看看baz /|\ baz
。自从一个Traversal
也是一个Setter
,它还必须满足Setter laws。现在,采用第二设置法:
over (baz /|\ baz) (f . g) = over (baz /|\ baz) f . over (baz /|\ baz) g
现在,我们得到:
over (baz /|\ baz) (f . g)
= \(Foo _baz _bar) -> Foo (f . g . f . g $ _baz) _bar
and:
over (baz /|\ baz) f . over (baz /|\ baz) g
= \(Foo _baz _bar) -> Foo (f . f . g . g $ _baz) _bar
这两者显然是不同的。当两个镜头“重叠”时就会出现问题,并且这不会在类型中进行编码。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)