अगर मैं दो लेंस है:दो लेंस के उत्पाद को कैसे बनाया जाए?
foobar :: Lens' X (Foo, Bar)
foobar = ... foo bar
या यह असंभव है:
foo :: Lens' X Foo
bar :: Lens' X Bar
वहाँ एक उत्पाद का लेंस के निर्माण के लिए कोई तरीका है?
अगर मैं दो लेंस है:दो लेंस के उत्पाद को कैसे बनाया जाए?
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
रिटर्न कुछ मूल्य दो बार के रूप में, सभी pair
रों लिए (x, x)
।
@dfeuer उदाहरण देता है कि lensProd
को कैसे परिभाषित किया जाए।
दिलचस्प बात यह है कि दोहरी भी टूटा हुआ है। सामान्य तौर पर आप चश्मे के वैध योग नहीं कर सकते हैं:
{-# 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
आप देख सकते हैं, हम Right
में डाल दिया, लेकिन Left
बाहर निकलना।
जैसा कि फ़ेडज ने समझाया, सामान्य रूप से ऐसा करने के लिए कोई कानून-पालन करने का तरीका नहीं है। हालांकि, आप इसे वैसे भी कर सकते हैं और अपने उपयोगकर्ताओं को चेतावनी देते हैं कि वे केवल ऑर्थोगोनल लेंस पर इसे लागू करने के लिए सावधान रहेंगे।
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)
हम कल्पना की एक प्रकार के स्तर का सबूत प्राप्त कर सकते हैं जैसा कि मैंने कल्पना की है, और इस तरह के सबूत प्रदान करने पर एक संयोजक – nicolas
कि वास्तव में दोहरी है? – dfeuer