टेम्पलेट हास्केल का परिचय। भाग 1. आवश्यक न्यूनतम

यह पाठ बुलैट जिगंशिन द्वारा लिखित टेम्प्लेट हास्केल प्रलेखन का अनुवाद है। संपूर्ण पाठ का अनुवाद धारणा को सुविधाजनक बनाने के लिए कई तार्किक भागों में विभाजित किया गया है। पाठ में आगे के इटैलिक्स अनुवादक के नोट्स हैं।



टेम्पलेट हास्केल (इसके बाद TH) मेटा-प्रोग्रामिंग के लिए हास्केल एक्सटेंशन है। यह संकलन चरण पर कार्यक्रम के एल्गोरिथम निर्माण को सक्षम करता है। यह डेवलपर को विभिन्न प्रोग्रामिंग तकनीकों का उपयोग करने की अनुमति देता है जो हास्केल में ही उपलब्ध नहीं हैं, जैसे कि मैक्रो जैसे एक्सटेंशन, उपयोगकर्ता द्वारा निर्देशित अनुकूलन (जैसे, इनलाइनिंग), सामान्यीकृत प्रोग्रामिंग (पॉलीटिपिक प्रोग्रामिंग), मौजूदा डेटा संरचनाओं की पीढ़ी और मौजूदा लोगों से कार्य। उदाहरण के लिए, कोड
yell file line = fail ($(printf "Error in file %s line %d") file line) 

TH का उपयोग करके परिवर्तित किया जा सकता है
 yell file line = fail ((\x1 x2 -> "Error in file "++x1++" line "++show x2) file line) 

एक और उदाहरण कोड
 data T = A Int String | B Integer | C $(deriveShow ''T) 

में परिवर्तित किया जा सकता है
 data T = A Int String | B Integer | C instance Show T show (A x1 x2) = "A "++show x1++" "++show x2 show (B x1) = "B "++show x1 show C = "C" 

टीएच में, हास्केल कोड सामान्य हास्केल फ़ंक्शन (जिसे मैं स्पष्टता के लिए टेम्पलेट्स कहूंगा) द्वारा उत्पन्न किया जाता है। TH का उपयोग करने के लिए आपको जो न्यूनतम जानना आवश्यक है वह निम्नलिखित विषय हैं:
  1. हास्केल कोड को टेम्प्लेट में कैसे दर्शाया जाता है (TH फ़ंक्शन)
  2. नामों को एकजुट करने के लिए कैसे प्रशस्ति पत्र का उपयोग किया जाता है
  3. प्रोग्राम में जेनरेट किया गया TH-कोड कैसे डाला जाता है


हास्केल कोड टेम्प्लेट में कैसे प्रस्तुत किया जाता है


टेम्पलेट हास्केल में, पारंपरिक बीजगणितीय डेटा प्रकारों का उपयोग करके हास्केल कोड के टुकड़ों का प्रतिनिधित्व किया जाता है। ये प्रकार हास्केल सिंटैक्स के अनुसार बनाए गए हैं और एक विशेष कोड के सार सिंटैक्स ट्री (एएसटी - एब्सट्रैक्ट सिंटैक्स ट्री) का प्रतिनिधित्व करते हैं। अभिव्यक्ति का प्रतिनिधित्व करने के लिए एक प्रकार है, Pat लिए पैटर्न, Lit लिए लीटर, घोषणा के लिए आयु, Type लिए प्रकार, आदि। इन सभी प्रकारों की परिभाषाएँ Language.Haskell.TH.Syntax मॉड्यूल के दस्तावेज़ में पाई जा सकती हैं। वे हास्केल सिंटैक्स के नियमों के अनुसार जुड़े हुए हैं, इसलिए उनका उपयोग करके आप हेल्स कोड के किसी भी टुकड़े का प्रतिनिधित्व करने वाले मूल्यों का निर्माण कर सकते हैं। यहाँ कुछ सरल उदाहरण दिए गए हैं:
हमारे जीवन को सरल बनाने के लिए, टाइप E के सभी कंस्ट्रक्टर्स के नाम E में समाप्त होते हैं, P में टाइप Pat एंड के कंस्ट्रक्टर्स के नाम आदि। ऊपर उपयोग किया जाने वाला mkName फ़ंक्शन एक नाम के रूप में अपनी सामग्री के साथ एक नियमित स्ट्रिंग ( String ) से प्रकार के Name (पहचानकर्ताओं का प्रतिनिधित्व) बनाता है।
इसलिए, हास्केल कोड बनाने के लिए, एक TH फ़ंक्शन को केवल टाइप Exp (आप Dec , Pat या Type का भी उपयोग कर सकते हैं) का निर्माण और वापसी करना चाहिए, जो कि कोड के इस टुकड़े के लिए एक प्रतिनिधित्व है। वास्तव में, आपको इन प्रकारों के उपकरण का पूरी तरह से अध्ययन करने की आवश्यकता नहीं है ताकि यह पता चल सके कि उनमें आवश्यक हास्केल कोड कैसे प्रस्तुत किया जाए - डिबगिंग अनुभाग में मैं आपको बताऊंगा कि हास्कस कोड के एक विशिष्ट टुकड़े का टीएच-प्रतिनिधित्व कैसे प्राप्त करें।

नामों को एकजुट करने के लिए कैसे प्रशस्ति पत्र का उपयोग किया जाता है


हालाँकि, टेम्पलेट शुद्ध कार्य नहीं हैं जो टाइप Exp का एक साधारण मान लौटाते हैं। इसके बजाय, वे एक विशेष Q मोनैड (" newName " कहा जाता है) में गणना कर रहे हैं, जो आपको स्वचालित रूप से newName फ़ंक्शन newName नाम का उपयोग करके चर के लिए अद्वितीय नाम उत्पन्न करने की अनुमति देता है :: String -> Q Name । हर बार जब इसे बुलाया जाता है, तो इस उपसर्ग के साथ एक नया अनूठा नाम उत्पन्न होता है। इस नाम का उपयोग पैटर्न के भाग के रूप में किया जा सकता है ( VarP :: Name -> Pat constructor) या एक्सप्रेशन ( VarE :: Name -> Exp )।
आइए एक सरल उदाहरण लिखते हैं - tupleReplicate टेम्प्लेट, जिसका उपयोग निम्न प्रकार से किया जाता है: “$(tupleReplicate n) x" , सभी पदों पर तत्व x साथ एक n-जगह टपल लौटाएगा (सूचियों के लिए replicate फ़ंक्शन के समान)। टेम्पलेट का तर्क है, और x उत्पन्न अनाम फ़ंक्शन (लंबोदर एक्सप्रेशन) का तर्क है। मैं इस टेम्पलेट की परिभाषा वाले मॉड्यूल का कोड देता हूं ( Language.Haskell.TH मॉड्यूल TH के साथ काम करने के लिए आवश्यक सभी उपकरण प्रदान करता है):

 module TupleReplicate where import Language.Haskell.TH tupleReplicate :: Int -> Q Exp tupleReplicate n = do id <- newName "x" return $ LamE [VarP id] (TupE $ replicate n $ VarE id) 

उदाहरण के लिए, " tupleReplicate 3 " को कॉल करना, Haskell अभिव्यक्ति के बराबर एक tupleReplicate 3 मूल्य लौटाएगा " (\x -> (x,x,x)) "।

प्रोग्राम में जेनरेट किया गया TH-कोड कैसे डाला जाता है


पेस्ट (ब्याह) " $x " के रूप में लिखा जाता है, जहां x पहचानकर्ता है, या " $(...) " के रूप में, जहां दीर्घवृत्त का अर्थ है संबंधित अभिव्यक्ति। यह महत्वपूर्ण है कि $ चरित्र और पहचानकर्ता या कोष्ठक के बीच कोई स्थान नहीं है। $ का यह उपयोग इस अक्षर के मूल्य को एक infix ऑपरेटर के रूप में ओवरराइड करता है, जैसे कि योग्य नाम Mx फ़ंक्शन रचना ऑपरेटर के मूल्य को ओवरराइड करता है . " "। यदि आपको एक ऑपरेटर की आवश्यकता है, तो आपको रिक्त स्थान के साथ चरित्र को घेरने की आवश्यकता है।
पेस्ट दिखाई दे सकता है

आपको यह भी पता होना चाहिए

एक मॉड्यूल का एक उदाहरण जो हमारे tupleReplicate टेम्पलेट का उपयोग करता है:

 {-# LANGUAGE TemplateHaskell #-} module Test where import TupleReplicate main = do print ($(tupleReplicate 2) 1) --  (1,1) print ($(tupleReplicate 5) "x") --  ("x","x","x","x","x") 

जारी रखा जाए


निम्नलिखित अनुभाग अधिक रोचक और उन्नत विषयों को कवर करेंगे:
  1. प्रशस्ति पत्र मोनाड
  2. कोष्ठक का उद्धरण
  3. भौतिककरण (संशोधन)
  4. त्रुटि संदेश और पुनर्प्राप्ति
  5. डिबगिंग
और शुरुआत में उल्लिखित printf और deriveShow उदाहरणों को deriveShow जाता deriveShow

PS यह मेरा पहला अनुवाद है, इसलिए मैं रचनात्मक आलोचना और लेख के विषय पर एक महत्वपूर्ण चर्चा की उम्मीद करता हूं।

अद्यतन:
भाग 2. कोड उपकरण का हवाला देते हुए
भाग 3. टीएच के अन्य पहलू

Source: https://habr.com/ru/post/In131998/


All Articles