如何将镜片组合成“平行” [英] How to combine lenses in "parallel"
问题描述
我是新来的优秀 Control.Lens
,我试图将2个镜头以并行(不按顺序)组合起来,就像我会用` Control.Arrow。&&& amp;& amp; amp; amp; amp; amp; amp; amp; amp; amp;& amp; amp; amp; amp;& amp; amp; amp;& amp; amp; amp;& amp; amp;
`data Foo a = Foo {_baz :: Int,_bar :: Int,a}
我希望能够做到这样的东西:
>>让foo =(bar&& baz)。〜(1,20)$ Foo undefined undefinedFOO
>> foo ^。 (bar& amp; baz)
(1,20)
'I'我无所不在,无法找到办法。是因为:
- (&&& amp; b
- 没用。我不应该需要它,因此没有人会执行它。
- 以另一种方式执行操作很简单(使用
$ b $ h
$ b $ $ b&&&
可以这样实现:
(/ | \):: Lens'fa - >镜头'f b - >镜头'f(a,b)
a / | \ b =镜头getBoth setBoth其中
getBoth f =(f ^。a,f ^ .b)
setBoth f(v,w )= a。〜v $ f'其中
f'= b。〜w $ f
barz :: Lens'Foo(Int,Int)
barz = bar / | \ baz
然而,它需要一个类型签名,这有点烦人。
解决方案我只是偶然发现了这个实际的函数,,因为它是在
lens
中定义的有关模块名称中不健全权限的评论:Control.Lens.Unsound
)- |镜片产品。一般来说,没有遵守法律的方法。
- 如果输入镜头投影
的不相交部分 - 结构@ s @,结果只是一个有效的镜头。否则你得到你放入的东西法律
-
- @
- 'Control.Lens.Getter.view'l('Control.Lens.Setter.set'lvs )≡v
- @
-
- 违反
-
- >>>让badLens :: Lens'(Int,Char)(Int,Int); badLens = lensProduct _1 _1
- >>>查看badLens(set badLens(1,2)(3,'x'))
- (2,2)
-
- 但我们应该得到@(1,2 )@。
-
- 您是否在寻找'Control.Lens.Lens.alongside'?
-
lensProduct :: ALens的a - >阿伦斯的b - >镜头(a,b)
lensProduct l1 l2 f s =
f(s ^#l1,s ^#l2)<&> \(a,b) - > s& l1#〜a& l2#〜b
I'm new to the excelent
Control.Lens
and I'm trying to combine 2 lens in "parallel" (not in sequence) like I would do with `Control.Arrow.&&&).If I take the example from the
lens
documentation:`data Foo a = Foo { _baz :: Int, _bar :: Int, a }
I would like to be able to do stuff like :
>> let foo = (bar &&& baz) .~ (1, 20) $ Foo undefined undefined "FOO" >> foo ^. (bar &&& baz) (1, 20)
I've looked everywhere and I could not find a way to do so. Is that because :
- (&&&) exist with another name and I missed it.
- It's useless. I should not need it, therefore nobody bothered implementing it.
- It's trivial to do in another way (using
both
or<*>
)
Update
&&&
can be implemented that way :(/|\) :: 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
However, it needs a type signature which is a bit annoying.
解决方案I've just stumbled over this actual function, as it is defined in
lens
(with a fat comment about the unsoundness right in the module name:Control.Lens.Unsound
)-- | A lens product. There is no law-abiding way to do this in general. -- Result is only a valid 'Lens' if the input lenses project disjoint parts of -- the structure @s@. Otherwise "you get what you put in" law -- -- @ -- 'Control.Lens.Getter.view' l ('Control.Lens.Setter.set' l v s) ≡ v -- @ -- -- is violated by -- -- >>> let badLens :: Lens' (Int, Char) (Int, Int); badLens = lensProduct _1 _1 -- >>> view badLens (set badLens (1,2) (3,'x')) -- (2,2) -- -- but we should get @(1,2)@. -- -- Are you looking for 'Control.Lens.Lens.alongside'? -- lensProduct :: ALens' s a -> ALens' s b -> Lens' s (a, b) lensProduct l1 l2 f s = f (s ^# l1, s ^# l2) <&> \(a, b) -> s & l1 #~ a & l2 #~ b
这篇关于如何将镜片组合成“平行”的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!