私は2枚のレンズがある場合:2枚のレンズを作る方法は?
foobar :: Lens' X (Foo, Bar)
foobar = ... foo bar
か、それは不可能です:
foo :: Lens' X Foo
bar :: Lens' X Bar
製品レンズを構築する方法はありますか?
私は2枚のレンズがある場合:2枚のレンズを作る方法は?
foobar :: Lens' X (Foo, Bar)
foobar = ... foo bar
か、それは不可能です:
foo :: Lens' X Foo
bar :: Lens' X Bar
製品レンズを構築する方法はありますか?
一般的に、これは不可能です。おそらく最も一般的なケースでは、記録の異なるフィールドにレンズがあると、レンズがばらばらになり、合法的なレンズを作ることができます。しかし、一般にそれは真実ではありません。これは、コンビネータがライブラリに用意されていないため、書くのは簡単です。
lensProd
とします。
_1 :: Lens' (a, b) a -- Simpler type
badLens :: Lens' (a, b) (a, a)
badLens = lensProd _1 _1
この場合、「あなたが入れたものを取り戻す」という法律は成立しません。それは次のようになります。
view badLens (set badLens (1, 2) (3, 4)) ≡ (1, 2)
しかし、それは二回view badLens pair
戻っていくつかの値として、trueにすることはできません。すべてのpair
のため(x, x)
。
@dfeuerは、lensProd
の定義方法の例を示しています。興味深いことに、デュアルも壊れています。あなたが見る、私たちはRight
に置くが、Left
を出すことができたよう
{-# 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
:一般的に、あなたは、プリズムの合法的 合計を持つことはできません。
phadejが説明したように、これを一般的に行う法的な方法はありません。しかし、とにかくやり直して、直交レンズにのみ適用するように注意することをユーザーに警告します。例えば
import Control.Lens
import Control.Arrow ((&&&))
fakeIt :: Lens' s x -> Lens' s y -> Lens' s (x,y)
fakeIt l1 l2 =
lens (view l1 &&& view l2)
(\s (x,y) -> set l1 x . set l2 y $ s)
:
Prelude Control.Lens A> set (fake _1 _2) (7,8) (1,2,3)
(7,8,3)
Prelude Control.Lens A> view (fake _1 _2) (1,2,3)
(1,2)
私が想像するcompdataのように、分離レベルの証明を得ることができます。そして、そのような証明を提供するコンディショナー – nicolas
は本当に二重のことですか? – dfeuer