如何制作两个镜头的产品? [英] How to make the product of two lenses?

查看:106
本文介绍了如何制作两个镜头的产品?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我有两个镜头:

  foo :: Lens'X Foo 
bar :: Lens'X Bar

有没有一种方法可以构建产品镜头:

  foobar :: Lens'X(Foo,Bar)
foobar = ... foo bar

或者是不可能的?

解决方案

是不可能的。可能是最常见的情况是,当您将镜头放在记录的不同区域时,镜头不相交,因此您可以制作合法的镜头。但总的来说这不是事实。这就是为什么combinator不在库中提供,即使它很容易编写。



假设 lensProd 存在。这是足够的两次采取相同的镜头:

  _1 :: Lens'(a,b)a  - 简单类型

badLens :: Lens'(a,b)(a,a)
badLens = lensProd _1 _1

然后,你放回你放入的东西的法律并不成立。它应该是:

  view badLens(set badLens(1,2)(3,4))≡(1,2) 

但它不可能是真的,因为查看badLens对 s,c>返回一些值两次:(x,x)

@dfeuer举例说明如何定义 lensProd






有趣的是,这个对偶也被打破了。一般来说,你不能有合法的
棱镜总和:

$ $ p $ {$#$ c $ { - #LANGUAGE RankNTypes# - }

导入Control.Applicative
导入Control.Lens

- |
- >>> :t sumPrism _Just _Nothing :: Prism'(也许a)(或者a())
- sumPrism _Just _Nothing :: Prism'(也许a)(或者a())
- :: (Applicative f,Choice p)=>
- p(a())(f(a())) - > p(也许a)(f(也许a))
-
sumPrism :: Prism'a b - > Prism'a c - > Prism'a(bc)
sumPrism ab ac = prism'build match where
build(Left b)= ab#b $ b build(Right c)= ac#c

match x = Left< $> x ^? ab< |>正确< $> x ^? ac

- 法律
-
- @
- 预览l(查看lb)≡只需b
- @
-
- 打破
-
- >>>预览badPrism(复习badPrism(Right'x'))
- Just(Left'x')
-
badPrism :: Prism'a(aa)
badPrism = sumPrism id id

正如您所看到的,我们将 code>,但出去 Left


If I have two lenses:

foo :: Lens' X Foo
bar :: Lens' X Bar

Is there a way to construct a product lens:

foobar :: Lens' X (Foo, Bar)
foobar = ... foo bar 

or is it impossible?

解决方案

In general case, this is impossible. Probably the most common case when you have lenses to different fields of the record, the lenses are disjoint, so you can make a lawful lens. But in general it's not true. This is why the combinator is not provided in the libraries, even it would be easy to write.

Assume lensProd exists. It's enough to take the same lens twice:

_1 :: Lens' (a, b) a -- Simpler type

badLens :: Lens' (a, b) (a, a)
badLens = lensProd _1 _1

Then the "You get back what you put in" law doesn't hold. It should be:

view badLens (set badLens (1, 2) (3, 4)) ≡ (1, 2)

But it cannot be true, as view badLens pair returns some value twice: (x, x) for all pairs.

@dfeuer gives an example how to define lensProd.


Interestingly the dual is also broken. In general you cannot have lawful sum of prism:

{-# LANGUAGE RankNTypes #-}

import Control.Applicative
import Control.Lens

-- |
-- >>> :t sumPrism _Just _Nothing :: Prism' (Maybe a) (Either a ())
-- sumPrism _Just _Nothing :: Prism' (Maybe a) (Either a ())
--  :: (Applicative f, Choice p) =>
--     p (Either a ()) (f (Either a ())) -> p (Maybe a) (f (Maybe a))
--
sumPrism :: Prism' a b -> Prism' a c -> Prism' a (Either b c)
sumPrism ab ac = prism' build match where
    build (Left b)  = ab # b
    build (Right c) = ac # c

    match x = Left <$> x ^? ab <|> Right <$>  x ^? ac

-- The law
--
-- @
-- preview l (review l b) ≡ Just b
-- @
--
-- breaks with
--
-- >>> preview badPrism (review badPrism (Right 'x'))
-- Just (Left 'x')
-- 
badPrism :: Prism' a (Either a a)
badPrism = sumPrism id id

As you can see, we put in Right, but get out Left.

这篇关于如何制作两个镜头的产品?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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