如何将镜片组合成“平行” [英] How to combine lenses in "parallel"

查看:193
本文介绍了如何将镜片组合成“平行”的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是新来的优秀 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
  • 没用。我不应该需要它,因此没有人会执行它。

  • 以另一种方式执行操作很简单(使用 或<$ c
    $ 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆