कम से कम 4 पुस्तकालय हैं जिन्हें मैं लेंस प्रदान करने से अवगत हूं।
एक लेंस की धारणा यह है कि यह कुछ आइसोमॉर्फिक प्रदान करता है
data Lens a b = Lens (a -> b) (b -> a -> a)
दो कार्य प्रदान करना: एक गेटटर, और एक सेटर
get (Lens g _) = g
put (Lens _ s) = s
तीन कानूनों के अधीन:
सबसे पहले, अगर आप कुछ डालते हैं, तो आप इसे वापस निकाल सकते हैं
get l (put l b a) = b
दूसरा जो मिलना और फिर सेट करना उत्तर नहीं बदलता है
put l (get l a) a = a
और तीसरा, दो बार डालना एक बार डालने के समान है, या यों कहें कि दूसरा डाल जीतता है।
put l b1 (put l b2 a) = put l b1 a
ध्यान दें, कि आपके लिए इन कानूनों की जाँच करने के लिए टाइप सिस्टम पर्याप्त नहीं है, इसलिए आपको यह सुनिश्चित करने की आवश्यकता है कि आप चाहे जो भी लेंस का उपयोग करें।
इन पुस्तकालयों में से कई शीर्ष पर अतिरिक्त कॉम्बिनेटरों का एक समूह भी प्रदान करते हैं, और आमतौर पर टेम्पलेट हैस्केल मशीनरी के कुछ प्रकार सरल रिकॉर्ड प्रकारों के क्षेत्रों के लिए स्वचालित रूप से लेंस उत्पन्न करते हैं।
इसे ध्यान में रखते हुए, हम विभिन्न कार्यान्वयनों की ओर रुख कर सकते हैं:
क्रियान्वयन
fclabels
fclabels शायद लेंस पुस्तकालयों के बारे में सबसे आसानी से तर्क दिया गया है, क्योंकि इसका a :-> b
सीधे उपरोक्त प्रकार से अनुवाद किया जा सकता है। यह के लिए एक श्रेणी उदाहरण प्रदान करता है(:->)
जिसके लिए यह उपयोगी है क्योंकि यह आपको लेंस की रचना करने की अनुमति देता है। यह एक अराजक Point
प्रकार भी प्रदान करता है जो यहां इस्तेमाल किए गए लेंस की धारणा को सामान्य करता है, और आइसोमोर्फिज्म से निपटने के लिए कुछ प्लंबिंग करता है।
गोद लेने में एक बाधा यह fclabels
है कि मुख्य पैकेज में टेम्पलेट-हैसेल पाइपलाइन शामिल है, इसलिए पैकेज हस्केल 98 नहीं है, और इसके लिए (काफी गैर-विवादास्पद) भी आवश्यकता होती हैTypeOperators
एक्सटेंशन की ।
डेटा-एक्सेसर
[संपादित करें: data-accessor
अब इस प्रतिनिधित्व का उपयोग नहीं कर रहा है, लेकिन इसके समान एक रूप में स्थानांतरित हो गया हैdata-lens
। मैं इस टिप्पणी को रख रहा हूं, हालांकि।]
डेटा-एक्सेसरfclabels
भाग की तुलना में कुछ अधिक लोकप्रिय है , क्योंकि यह है हास्केल 98. हालांकि, आंतरिक प्रतिनिधित्व के अपनी पसंद मुझे मेरे मुंह में एक छोटा सा ऊपर फेंक बनाता है।
T
लेंस का प्रतिनिधित्व करने के लिए यह जिस प्रकार का उपयोग करता है उसे आंतरिक रूप से परिभाषित किया गया है
newtype T r a = Cons { decons :: a -> r -> (a, r) }
नतीजतन, get
लेंस के मूल्य के लिए, आपको 'a' तर्क के लिए अपरिभाषित मान जमा करना होगा! यह मुझे एक अविश्वसनीय रूप से बदसूरत और तदर्थ कार्यान्वयन के रूप में प्रभावित करता है।
उस ने कहा, हेनिंग ने एक अलग ' डेटा-एक्सेसर-टेम्प्लेट ' पैकेज में आपके लिए एक्सेसर्स को स्वचालित रूप से उत्पन्न करने के लिए टेम्प्लेट-हैस्केल प्लंबिंग को शामिल किया है ।
यह एक बड़े पैमाने पर संकुल का लाभ है जो पहले से ही इसे नियोजित करता है, हास्केल 98, और सर्व-महत्वपूर्ण प्रदान करता है Category
उदाहरण , इसलिए यदि आप इस बात पर ध्यान नहीं देते हैं कि सॉसेज कैसे बनाया जाता है, तो यह पैकेज वास्तव में बहुत ही उचित विकल्प है ।
लेंस
इसके बाद, लेंस पैकेज होता है, जो देखता है कि एक लेंस दो राज्य मठों के बीच एक राज्य मोनड होमोमोर्फिज्म प्रदान कर सकता है, लेंस को सीधे ऐसे मोनड होमोमोर्फिज्म के रूप में परिभाषित करता है।
अगर यह वास्तव में अपने लेंस के लिए एक प्रकार प्रदान करने के लिए परेशान है, तो उनके पास रैंक -2 प्रकार होगा:
newtype Lens s t = Lens (forall a. State t a -> State s a)
नतीजतन, मुझे यह दृष्टिकोण पसंद नहीं है, क्योंकि यह बेवजह आपको हास्केल 98 से बाहर कर देता है (यदि आप सार में अपने लेंस को प्रदान करने के लिए एक प्रकार चाहते हैं) और आपको Category
लेंस के लिए उदाहरण से वंचित करता है , जो आपको देगा। उनके साथ रचना करें .
। कार्यान्वयन के लिए बहु-पैरामीटर प्रकार की कक्षाओं की आवश्यकता होती है।
ध्यान दें, यहां वर्णित अन्य सभी लेंस लाइब्रेरी कुछ कॉम्बिनेटर प्रदान करते हैं या इसका उपयोग उसी राज्य फोकलकरण प्रभाव प्रदान करने के लिए किया जा सकता है, इसलिए आपके लेंस को इस फैशन में सीधे एन्कोडिंग द्वारा कुछ भी प्राप्त नहीं होता है।
इसके अलावा, शुरुआत में बताई गई साइड-कंडीशन की वास्तव में इस रूप में अच्छी अभिव्यक्ति नहीं है। 'Fclabels' के रूप में यह सीधे मुख्य पैकेज में रिकॉर्ड प्रकार के लिए लेंस उत्पन्न करने के लिए टेम्पलेट-हैस्केल विधि प्रदान करता है।
Category
उदाहरण की कमी के कारण , मुख्य पैकेज में बारोक एन्कोडिंग और टेम्पलेट-हैस्केल की आवश्यकता है, यह मेरा पसंदीदा पसंदीदा कार्यान्वयन है।
डेटा लेंस
[संपादित करें: 1.8.0 तक, ये कोमोनॉड-ट्रांसफॉर्मर पैकेज से डेटा-लेंस में चले गए हैं]
मेरा data-lens
पैकेज स्टोर कोमोनड के संदर्भ में लेंस प्रदान करता है ।
newtype Lens a b = Lens (a -> Store b a)
कहाँ पे
data Store b a = Store (b -> a) b
विस्तारित यह इसके बराबर है
newtype Lens a b = Lens (a -> (b, b -> a))
आप इसे पुनः प्राप्त करने वाले के रूप में देख सकते हैं कि गेटर और सेटर से आम तर्क को जोड़ा जाता है, जिसमें तत्व को पुनः प्राप्त करने के परिणाम के साथ एक जोड़ी होती है, और एक नया मान वापस लाने के लिए एक सेटर। यह कम्प्यूटेशनल लाभ प्रदान करता है कि 'सेटर'। यहाँ मूल्य को प्राप्त करने के लिए उपयोग किए जाने वाले कुछ कार्यों को पुन: चक्रित किया जा सकता है, जिससे fclabels
परिभाषा की तुलना में अधिक कुशल 'संशोधित' संचालन के लिए , विशेषकर जब एक्सेसरों को जंजीर में बांध दिया जाता है।
इस प्रतिनिधित्व के लिए एक अच्छा सैद्धांतिक औचित्य भी है, क्योंकि 'लेंस' मूल्यों का सबसेट जो इस प्रतिक्रिया की शुरुआत में बताए गए 3 कानूनों को संतुष्ट करता है, ठीक वे लेंस हैं जिनके लिए लिपटे फ़ंक्शन स्टोर कोमोनड के लिए एक 'कोमोनॉड कोलजेब्रा' है। । यह एक लेंस के लिए 3 बालों वाले कानूनों l
को 2 अच्छे पॉइंटफ्री समकक्षों में बदल देता है:
extract . l = id
duplicate . l = fmap l . l
यह दृष्टिकोण पहले उल्लेख किया और रसेल ओ'कॉनर के में वर्णित किया गया Functor
है Lens
के रूप में Applicative
करने के लिए है Biplate
: पेश Multiplate किया गया था और एक प्रीप्रिंट के आधार पर के बारे में ब्लॉग जेरेमी गिबन्स द्वारा।
इसमें लेंस के साथ कड़ाई से काम करने के लिए कई प्रकार के कॉम्बिनेटर और कंटेनर के लिए कुछ स्टॉक लेंस भी शामिल हैं, जैसे कि Data.Map
।
तो लेंस data-lens
एक Category
( lenses
पैकेज के विपरीत ) के रूप में, हास्केल 98 ( fclabels
/ के विपरीत lenses
) हैं, साने हैं (पीछे के अंत के विपरीत data-accessor
) और थोड़ा अधिक कुशल कार्यान्वयन data-lens-fd
प्रदान करते हैं , बाहर कदम रखने के इच्छुक लोगों के लिए मोनास्टस्टेट के साथ काम करने की कार्यक्षमता प्रदान करते हैं। हास्केल 98, और टेम्पलेट-हैस्केल मशीनरी अब उपलब्ध है data-lens-template
।
अद्यतन 6/28/2012: अन्य लेंस कार्यान्वयन रणनीतियाँ
आइसोमोर्फिज्म लेंस
दो अन्य लेंस एनकोडिंग हैं जो विचार करने लायक हैं। पहले एक लेंस को क्षेत्र के मूल्य में एक संरचना को तोड़ने के तरीके के रूप में देखने के लिए एक अच्छा सैद्धांतिक तरीका देता है, और 'बाकी सब कुछ'।
समरूपता के लिए एक प्रकार को देखते हुए
data Iso a b = Iso { hither :: a -> b, yon :: b -> a }
ऐसे वैध सदस्य संतुष्ट हों hither . yon = id
, औरyon . hither = id
हम एक लेंस का प्रतिनिधित्व कर सकते हैं:
data Lens a b = forall c. Lens (Iso a (b,c))
ये मुख्य रूप से लेंस के अर्थ के बारे में सोचने के तरीके के रूप में उपयोगी हैं, और हम अन्य लेंस को समझाने के लिए एक तर्क उपकरण के रूप में उपयोग कर सकते हैं।
वैन लाहरोवेन लेंस
हम लेंस मॉडल कर सकते हैं ऐसी है कि वे साथ हो सकती हैं (.)
और id
यहां तक कि एक के बिना Category
उपयोग कर उदाहरण
type Lens a b = forall f. Functor f => (b -> f b) -> a -> f a
हमारे लेंस के प्रकार के रूप में।
फिर एक लेंस को परिभाषित करना उतना ही आसान है:
_2 f (a,b) = (,) a <$> f b
और आप स्वयं के लिए यह सत्यापित कर सकते हैं कि फ़ंक्शन रचना लेंस संरचना है।
मैंने हाल ही में लिखा है कि आप लेंस परिवारों को प्राप्त करने के लिए वैन लाहरोवेन लेंस को और कैसे सामान्य कर सकते हैं जो कि उनके हस्ताक्षर को सामान्य करके, खेतों के प्रकारों को बदल सकते हैं
type LensFamily a b c d = forall f. Functor f => (c -> f d) -> a -> f b
इसका दुर्भाग्यपूर्ण परिणाम यह है कि लेंस के बारे में बात करने का सबसे अच्छा तरीका रैंक 2 बहुरूपता का उपयोग करना है, लेकिन लेंस को परिभाषित करते समय आपको सीधे उस हस्ताक्षर का उपयोग करने की आवश्यकता नहीं है।
Lens
मैं के लिए ऊपर परिभाषित _2
वास्तव में एक है LensFamily
।
_2 :: Functor f => (a -> f b) -> (c,a) -> f (c, b)
मैंने एक पुस्तकालय लिखा है जिसमें लेंस, लेंस परिवार और गेटर्स, सेटरर्स, फोल्ड्स और ट्रैवर्सल्स सहित अन्य सामान्यीकरण शामिल हैं। यह lens
पैकेज के रूप में हैकेज पर उपलब्ध है ।
फिर से, इस दृष्टिकोण का एक बड़ा फायदा यह है कि लाइब्रेरी मेंटेनर वास्तव में आपकी लाइब्रेरी में इस शैली में लेंस बना सकते हैं, बिना किसी लेंस लाइब्रेरी निर्भरता के बिना, केवल Functor f => (b -> f b) -> a -> f a
विशेष प्रकार के 'ए' और 'बी' के लिए कार्यों की आपूर्ति करके । यह गोद लेने की लागत को बहुत कम करता है।
चूंकि आपको नए लेंस को परिभाषित करने के लिए वास्तव में पैकेज का उपयोग करने की आवश्यकता नहीं है, इसलिए लाइब्रेरी हस्केल 98 को रखने के बारे में मेरी पहले की चिंताओं से बहुत दबाव पड़ता है।
lens
पैकेज में सबसे अमीर कार्यक्षमता और प्रलेखन है, इसलिए यदि आप इसकी जटिलता और निर्भरता पर ध्यान नहीं देते हैं, तो यह जाने का तरीका है।