[मैं "SYB रीलोडेड" कागज के लेखकों में से एक हूँ।]
टी एल; डॉ हम वास्तव में सिर्फ यह प्रयोग किया जाता है क्योंकि यह हमारे लिए अधिक सुंदर लग रहा था। कक्षा-आधारित Typeable
दृष्टिकोण अधिक व्यावहारिक है। Spine
व्यू को Typeable
कक्षा के साथ जोड़ा जा सकता है और यह Type
GADT पर निर्भर नहीं है।
कागज राज्यों इसके निष्कर्षों में इस:
हमारी कार्यान्वयन सामान्य प्रोग्रामिंग के दो केंद्रीय तत्व संभालती अलग ढंग से मूल SYB कागज से: हम के आधार पर अतिभारित कार्यों के बजाय स्पष्ट प्रकार तर्क के साथ अतिभारित कार्यों का उपयोग एक प्रकार-सुरक्षित कास्ट 1 या कक्षा-आधारित एक्स्टेंसिबल योजना [20]; और हम संयोजक-आधारित दृष्टिकोण के बजाय स्पष्ट रीढ़ व्यू का उपयोग करते हैं। दोनों परिवर्तन स्वतंत्र हैं एक दूसरे के हैं, और स्पष्टता के साथ दिमाग में किए गए हैं: हमें लगता है कि एसआईबी दृष्टिकोण की संरचना हमारी सेटिंग में अधिक दिखाई दे रही है, और संबंध पॉलीपी और जेनेरिक हास्केल के लिए स्पष्ट हो गए हैं। हमने खुलासा किया है कि रीढ़ की हड्डी जेनेरिक कार्यों के वर्ग में सीमित है, जिसे लिखा जा सकता है, यह है, जिसमें जीएडीटी समेत डेटा प्रकारों की एक बहुत बड़ी कक्षा के लिए लागू होता है।
हमारा दृष्टिकोण, एक पुस्तकालय के रूप में आसानी नहीं किया जा सकता क्योंकि अतिभारित स्पष्ट प्रकार तर्कों का उपयोग कार्यों की एन्कोडिंग कार्यों के इस तरह के toSpine रूप प्रकार का डेटा प्रकार तानाना की आवश्यकता है और। हालांकि, अधिभारित कार्यों को एन्कोड करने के लिए अभी भी SYB पेपर की तकनीकों का उपयोग करते हुए, एसआईबी लाइब्रेरी में स्पाइन को शामिल किया जा सकता है।
तो, प्रकार के प्रतिनिधित्व के लिए जीएडीटी का उपयोग करने की पसंद एक है जिसे हमने मुख्य रूप से स्पष्टता के लिए बनाया है। जैसा कि डॉन ने अपने उत्तर में कहा है, इस प्रतिनिधित्व में कुछ स्पष्ट फायदे हैं, अर्थात् यह किस प्रकार के प्रकार के प्रतिनिधित्व के बारे में स्थिर जानकारी बनाए रखता है, और यह हमें बिना किसी जादू के कलाकारों को लागू करने की अनुमति देता है, और विशेष रूप से उपयोग के बिना unsafeCoerce
का। प्रकार-अनुक्रमित कार्यों को प्रकार के पैटर्न मिलान का उपयोग करके और mkQ
या extQ
जैसे विभिन्न संयोजकों पर वापस गिरने के बिना सीधे लागू किया जा सकता है।
तथ्य यह है कि मैं (और मुझे लगता है कि सह-लेखक) Typeable
कक्षा का बहुत शौक नहीं थे। (वास्तव में, मैं अभी भी नहीं हूं, हालांकि अंत में यह थोड़ा और अनुशासित हो रहा है कि जीएचसी Typeable
के लिए स्वत: व्युत्पन्न जोड़ता है, इसे दयालु-पॉलिमॉर्फिक बनाता है, और आखिरकार आपके अपने उदाहरणों को परिभाषित करने की संभावना को हटा देगा।) इसके अलावा, Typeable
काफी स्थापित और व्यापक रूप से ज्ञात नहीं था क्योंकि यह शायद अब है, इसलिए यह GADT एन्कोडिंग का उपयोग करके इसे "समझा" करने के लिए अपील करता है। और इसके अलावा, यह वह समय था जब हम open datatypes को हास्केल में जोड़ने के बारे में सोच रहे थे, जिससे जीएडीटी बंद होने वाले प्रतिबंध को कम कर दिया गया।
तो संक्षेप में: यदि आपको वास्तव में बंद ब्रह्मांड के लिए गतिशील प्रकार की जानकारी की आवश्यकता है, तो मैं हमेशा जीएडीटी के लिए जाता हूं, क्योंकि आप प्रकार-अनुक्रमित कार्यों को परिभाषित करने के लिए पैटर्न मिलान का उपयोग कर सकते हैं, और आपको unsafeCoerce
और न ही उन्नत कंपाइलर जादू पर भरोसा करें। यदि ब्रह्मांड खुला है, हालांकि, सामान्य रूप से जेनेरिक प्रोग्रामिंग सेटिंग के लिए, आम तौर पर जीएडीटी दृष्टिकोण निर्देशक हो सकता है, लेकिन व्यावहारिक नहीं है, और Typeable
का उपयोग करने का तरीका है।
लेकिन, जैसा कि हम भी कागज के निष्कर्ष में राज्य, Type
Typeable
से अधिक की पसंद नहीं अन्य विकल्प हम अर्थात् Spine
दृश्य का उपयोग करने, कर रहे हैं, जो मुझे लगता है कि ज्यादा महत्वपूर्ण है के लिए एक शर्त है और वास्तव में कागज का मूल।
पेपर स्वयं ही (धारा 8 में) "Scrap your Boilerplate with Class" पेपर से प्रेरित एक भिन्नता दिखाता है, जो Spine
का उपयोग कक्षा की बाधा के साथ करता है। लेकिन हम एक और प्रत्यक्ष विकास भी कर सकते हैं, जो मैं निम्नलिखित में दिखाता हूं।इसके लिए हमें Data.Typeable
से Typeable
इस्तेमाल करेंगे, लेकिन हमारे अपने Data
वर्ग को परिभाषित है, जो सादगी के लिए, बस toSpine
विधि में शामिल हैं:
data Spine :: * -> * where
Constr :: a -> Spine a
(:<>:) :: (Data a) => Spine (a -> b) -> a -> Spine b
:
class Typeable a => Data a where
toSpine :: a -> Spine a
Spine
डेटाप्रकार अब Data
बाधा का उपयोग करता है
फ़ंक्शन fromSpine
अन्य प्रतिनिधित्व के साथ तुच्छ जैसा है:
fromSpine :: Spine a -> a
fromSpine (Constr x) = x
fromSpine (c :<>: x) = fromSpine c x
के लिए
उदाहरण ऐसे Int
के रूप में फ्लैट प्रकार के लिए तुच्छ हैं:
instance Data Int where
toSpine = Constr
और वे अभी भी इस तरह द्विआधारी पेड़ के रूप में संरचित प्रकार के लिए पूरी तरह से स्पष्ट कर रहे हैं:
data Tree a = Empty | Node (Tree a) a (Tree a)
instance Data a => Data (Tree a) where
toSpine Empty = Constr Empty
toSpine (Node l x r) = Constr Node :<>: l :<>: x :<>: r
कागज तो पर और परिभाषित करता चला जाता है विभिन्न सामान्य कार्य, जैसे mapQ
। ये परिभाषा शायद ही बदलती है। हम केवल Data a =>
के लिए वर्ग की कमी मिल जहां कागज Type a ->
के समारोह तर्क हैं:
mapQ :: Query r -> Query [r]
mapQ q = mapQ' q . toSpine
mapQ' :: Query r -> (forall a. Spine a -> [r])
mapQ' q (Constr c) = []
mapQ' q (f :<>: x) = mapQ' q f ++ [q x]
उच्चतर स्तर के कार्यों में इस तरह के everything
के रूप में भी सिर्फ अपने स्पष्ट प्रकार तर्क खो (और फिर वास्तव में बिल्कुल मूल SYB में जैसे ही दिखते हैं) :
everything :: (r -> r -> r) -> Query r -> Query r
everything op q x = foldl op (q x) (mapQ (everything op q) x)
जैसा कि मैंने ऊपर कहा, अगर हम अब एक सामान्य योग समारोह सभी Int
घटनाओं संक्षेप परिभाषित करना चाहते हैं, हम अब और नहीं पैटर्न मैच कर सकते हैं, लेकिन mkQ
में वापस आने का है, लेकिन mkQ
संदर्भ में विशुद्ध रूप से परिभाषित किया गया है 01 काऔर Spine
की पूरी तरह से स्वतंत्र: (बिल्कुल के रूप में मूल SYB में फिर से)
mkQ :: (Typeable a, Typeable b) => r -> (b -> r) -> a -> r
(r `mkQ` br) a = maybe r br (cast a)
और फिर:
sum :: Query Int
sum = everything (+) sumQ
sumQ :: Query Int
sumQ = mkQ 0 id
बाद में समाचार पत्र में सामान में से कुछ के लिए (जैसे, जोड़ने निर्माता जानकारी), एक थोड़ा और काम की जरूरत है, लेकिन यह सब किया जा सकता है। तो Spine
का उपयोग करके वास्तव में Type
का उपयोग करने पर निर्भर नहीं है।
यह एक समान दृष्टिकोण जैसा लगता है [यहां] (http://link.springer.com/chapter/10.1007%2F978-3-540-27764-4_4?LI=true#page-1) सार्वभौमिक ' यूनिवर्स 'टाइप, लेकिन मैंने केवल उस पेपर को स्किम किया है। – jberryman