2016-04-09 7 views

उत्तर

9

सामान्य मामले में, यह असंभव है। संभवतः सबसे आम मामला जब आपके पास रिकॉर्ड के विभिन्न क्षेत्रों में लेंस होते हैं, तो लेंस अलग होते हैं, इसलिए आप एक वैध लेंस बना सकते हैं। लेकिन सामान्य रूप से यह सच नहीं है। यही कारण है कि पुस्तकालयों में संयोजक प्रदान नहीं किया जाता है, यहां तक ​​कि लिखना आसान होगा।

मान लें 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 बाहर निकलना।

+0

कि वास्तव में दोहरी है? – dfeuer

7

जैसा कि फ़ेडज ने समझाया, सामान्य रूप से ऐसा करने के लिए कोई कानून-पालन करने का तरीका नहीं है। हालांकि, आप इसे वैसे भी कर सकते हैं और अपने उपयोगकर्ताओं को चेतावनी देते हैं कि वे केवल ऑर्थोगोनल लेंस पर इसे लागू करने के लिए सावधान रहेंगे।

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) 
+2

हम कल्पना की एक प्रकार के स्तर का सबूत प्राप्त कर सकते हैं जैसा कि मैंने कल्पना की है, और इस तरह के सबूत प्रदान करने पर एक संयोजक – nicolas

संबंधित मुद्दे