राज्य, ST, IORef और MVar के बीच अंतर


91

मैं 48 घंटे (मैं लगभग 85 घंटे तक रहा हूं) में योरसेल्फ स्कीम के माध्यम से काम कर रहा हूं और मैंने वेरिएबल्स और असाइनमेंट को जोड़ने के बारे में भाग लिया है । इस अध्याय में एक बड़ी वैचारिक छलांग है, और मेरी इच्छा है कि यह दो चरणों में किया गया था, बल्कि बीच में एक अच्छा रिफैक्टिंग करने के बाद सीधे अंतिम समाधान पर कूद गया था। वैसे भी ...

मुझे लगता है कि इसी उद्देश्य को पूरा करने लगते हैं विभिन्न वर्गों की संख्या के साथ खो दिया है मिल गया है: State, ST, IORef, और MVar। पाठ में पहले तीन का उल्लेख किया गया है, जबकि अंतिम में पहले तीन के बारे में ढेर सारे स्टैकऑवरफ्लो प्रश्नों के पसंदीदा उत्तर दिए गए हैं। वे सभी लगातार आक्रमणों के बीच एक राज्य को ले जाने लगते हैं।

इनमें से प्रत्येक क्या है और वे एक दूसरे से कैसे भिन्न हैं?


विशेष रूप से इन वाक्यों का कोई मतलब नहीं है:

इसके बजाय, हम स्टेट थ्रेड्स नामक एक सुविधा का उपयोग करते हैं , जिससे हास्केल हमारे लिए समग्र राज्य का प्रबंधन करता है। इससे हम परिवर्तनशील चर का इलाज कर सकते हैं, जैसा कि हम किसी अन्य प्रोग्रामिंग भाषा में करते हैं, चर प्राप्त करने या सेट करने के लिए फ़ंक्शन का उपयोग करते हैं।

तथा

IORef मॉड्यूल आपको IO मोनड के भीतर स्टेटफुल वैरिएबल का उपयोग करने देता है ।

यह सब लाइन को type ENV = IORef [(String, IORef LispVal)]भ्रमित करता है - दूसरा क्यों IORef? अगर मैं type ENV = State [(String, LispVal)]इसके बजाय लिखूंगा तो क्या टूट जाएगा ?

जवाबों:


119

द स्टेट मोनड: म्यूटेबल स्टेट का एक मॉडल

राज्य मोनाद एक साधारण एपीआई के साथ राज्य के कार्यक्रमों के लिए विशुद्ध रूप से कार्यात्मक वातावरण है:

  • प्राप्त
  • डाल

एमटीएल पैकेज में प्रलेखन ।

नियंत्रण के एक ही धागे में राज्य की आवश्यकता होने पर आमतौर पर राज्य का उपयोग किया जाता है। यह वास्तव में इसके कार्यान्वयन में उत्परिवर्तनीय स्थिति का उपयोग नहीं करता है। इसके बजाय, कार्यक्रम को राज्य मान द्वारा परिचालित किया जाता है (अर्थात राज्य सभी गणनाओं के लिए एक अतिरिक्त पैरामीटर है)। राज्य केवल एक ही धागे में उत्परिवर्तित होता है (और थ्रेड के बीच साझा नहीं किया जा सकता है)।

एसटी मोनाड और एसटीआरएफ

एसटी मोनाड, आईओ मोनद का प्रतिबंधित चचेरा भाई है।

यह मशीन पर वास्तविक परिवर्तनशील स्मृति के रूप में कार्यान्वित मनमाने ढंग से उत्परिवर्तित अवस्था की अनुमति देता है । API को साइड-इफ़ेक्ट-फ्री प्रोग्राम्स में सुरक्षित बनाया गया है, क्योंकि रैंक -2 प्रकार का पैरामीटर उन मानों को रोकता है जो कि किसी भी अन्य स्थिति से बचने के लिए उत्परिवर्तनीय स्थिति पर निर्भर करते हैं।

इस प्रकार यह अन्यथा शुद्ध कार्यक्रमों में नियंत्रित परिवर्तनशीलता की अनुमति देता है।

आमतौर पर उत्परिवर्तित सरणियों और अन्य डेटा संरचनाओं के लिए उपयोग किया जाता है जो कि उत्परिवर्तित होते हैं, फिर जमे हुए होते हैं। यह भी बहुत कुशल है, क्योंकि उत्परिवर्तनीय स्थिति "हार्डवेयर त्वरित" है।

प्राथमिक API:

  • Control.Monad.ST
  • रनस्ट - एक नया मेमोरी-इफेक्ट कम्प्यूटेशन शुरू करें।
  • और स्ट्राइफ : पॉइंटर्स टू (लोकल) म्यूटेबल सेल।
  • ST- आधारित सरणियाँ (जैसे वेक्टर) भी आम हैं।

इसे आइओ मोनाड की कम खतरनाक सहोदर मानते हैं। या आईओ, जहां आप केवल मेमोरी के लिए पढ़ और लिख सकते हैं।

IORef: IO में स्ट्रिप्स

ये IO सनद में स्ट्राइफ्स (ऊपर देखें) हैं। उनके पास स्थानीयता के बारे में STRefs के समान सुरक्षा गारंटी नहीं है।

MVars: ताले के साथ IORefs

स्ट्रॉफ या आईओआरएफ की तरह, लेकिन कई थ्रेड्स से सुरक्षित समवर्ती पहुंच के लिए, एक लॉक संलग्न के साथ । IORefs और STRefs केवल बहु-थ्रेडेड सेटिंग में सुरक्षित होते हैं जब atomicModifyIORef(एक तुलना-और-स्वैप परमाणु संचालन) का उपयोग करते हैं। MVars सुरक्षित रूप से उत्परिवर्तनीय स्थिति साझा करने के लिए एक अधिक सामान्य तंत्र हैं।

आमतौर पर, हास्केल में, एमवीआर या टीवीर्स (एसटीएम-आधारित म्यूटेबल सेल) का उपयोग करते हैं, एसटीआरएफ या आईओआरएफ पर।


3
टीवी में एमवी और टी में एम क्या करता है? मैं "म्यूटेबल", "ट्रांसेक्शनल" का अनुमान लगा रहा हूं। दिलचस्प है कि एसटी का मतलब स्टेट थ्रेड कैसे है।
CMCDragonkai

10
आप ऐसा क्यों कहते हैं कि MVarइसे प्राथमिकता दी जानी चाहिए STRef? STRefगारंटी देता है कि केवल एक धागा इसे उत्परिवर्तित कर सकता है (और यह कि अन्य प्रकार के IO नहीं हो सकते हैं) - निश्चित रूप से यह बेहतर है अगर मुझे उत्परिवर्ती राज्य तक समवर्ती पहुंच की आवश्यकता नहीं है?
बेंजामिन हॉजसन

@CMCDragonkai मैंने हमेशा माना है कि M म्यूटेक्स के लिए खड़ा है, लेकिन मैं इसे कहीं भी प्रलेखित नहीं कर सकता।
एंड्रयू थैडियस मार्टिन

37

ठीक है, मैं साथ शुरू करूँगा IORefIORefएक मान प्रदान करता है जो IO मोनड में परिवर्तनशील है। यह केवल कुछ डेटा का संदर्भ है, और किसी भी संदर्भ की तरह, ऐसे फ़ंक्शन हैं जो आपको उस डेटा को बदलने की अनुमति देते हैं जो इसे संदर्भित करता है। हास्केल में, उन सभी कार्यों का संचालन होता है IO। आप इसे एक डेटाबेस, फ़ाइल, या अन्य बाहरी डेटा स्टोर की तरह सोच सकते हैं - आप इसमें डेटा प्राप्त कर सकते हैं और सेट कर सकते हैं, लेकिन ऐसा करने के लिए IO से गुजरने की आवश्यकता होती है। IO का कारण बिल्कुल आवश्यक है क्योंकि हास्केल शुद्ध है ; कंपाइलर को यह जानने के लिए एक तरीका चाहिए कि किसी भी समय संदर्भ बिंदुओं को कौन सा डेटा पढ़ता है ( सिगफेप के "आपने मोनाड्स का आविष्कार किया हो सकता है" ब्लॉगपोस्ट)।

MVars मूल रूप से एक IORef के समान हैं, दो बहुत महत्वपूर्ण अंतरों को छोड़कर। MVarएक संगामिति आदिम है, इसलिए इसे कई थ्रेड से एक्सेस के लिए डिज़ाइन किया गया है। दूसरा अंतर यह है कि MVarएक बॉक्स है जो पूर्ण या खाली हो सकता है। इसलिए जहां IORef Intहमेशा एक Int(या नीचे है), एक MVar Intहो सकता है Intया यह खाली हो सकता है। यदि कोई थ्रेड किसी रिक्त से मान को पढ़ने का प्रयास करता है MVar, तो यह तब तक अवरुद्ध MVarहो जाएगा जब तक कि भरा हुआ (दूसरे थ्रेड द्वारा) नहीं हो जाता। मूल रूप MVar aसे एक IORef (Maybe a)अतिरिक्त अर्थ के साथ समतुल्य है जो संगामिति के लिए उपयोगी है।

Stateएक सन्यासी है जो पारस्परिक रूप से राज्य प्रदान करता है, जरूरी नहीं कि आईओ के साथ। वास्तव में, यह शुद्ध संगणना के लिए विशेष रूप से उपयोगी है। यदि आपके पास एक एल्गोरिथ्म है जो राज्य का उपयोग करता है लेकिन नहीं IO, एक Stateसनक अक्सर एक सुरुचिपूर्ण समाधान होता है।

राज्य का एक मोनाड ट्रांसफॉर्मर संस्करण भी है StateT। यह अक्सर अनुप्रयोगों में प्रोग्राम कॉन्फ़िगरेशन डेटा, या "गेम-वर्ल्ड-स्टेट" प्रकार के स्टेट को होल्ड करने के लिए उपयोग किया जाता है।

STकुछ अलग है। में मुख्य डेटा संरचना STहै STRef, जो कि IORefएक अलग मोनाड की तरह है। STइकाई का उपयोग करता है प्रकार प्रणाली प्रवंचना ( "राज्य धागे 'डॉक्स का उल्लेख) सुनिश्चित करना है कि परिवर्तनशील डेटा इकाई बच नहीं सकते; यही है, जब आप एसटी अभिकलन चलाते हैं तो आपको शुद्ध परिणाम मिलता है। एसटी का कारण दिलचस्प है कि यह आईओ की तरह एक आदिम मोनाड है, जो उप-स्तर और बिंदुओं पर निम्न-स्तरीय जोड़तोड़ करने के लिए अभिकलन की अनुमति देता है। इसका मतलब है कि STम्यूटेबल डेटा पर निम्न-स्तरीय संचालन का उपयोग करते हुए एक शुद्ध इंटरफ़ेस प्रदान कर सकता है, जिसका अर्थ है कि यह बहुत तेज़ है। कार्यक्रम के दृष्टिकोण से, यह ऐसा है जैसे STगणना थ्रेड-स्थानीय भंडारण के साथ एक अलग थ्रेड में चलती है।


17

दूसरों ने मुख्य बातें की हैं, लेकिन प्रत्यक्ष प्रश्न का उत्तर देने के लिए:

यह सब लाइन प्रकार को ENV = IORef [(String, IORef LispVal)] भ्रमित करता है। दूसरा IORef क्यों? अगर मैं इसके type ENV = State [(String, LispVal)]बजाय क्या टूट जाएगा ?

लिस्प एक परिवर्तनशील भाषा है जिसमें परिवर्तनशील स्थिति और लेक्सिकल स्कोप होता है। कल्पना कीजिए कि आपने एक परिवर्तनशील परिवर्तनशील पर बंद कर दिया है। अब आपको इस चर का संदर्भ किसी अन्य फ़ंक्शन के अंदर लटका हुआ है - कहते हैं (हैसेल-स्टाइल स्यूडोकोड में) (printIt, setIt) = let x = 5 in (\ () -> print x, \y -> set x y)। अब आपके पास दो कार्य हैं - एक प्रिंट x, और एक इसका मान सेट करता है। जब आप मूल्यांकन करते हैं printIt, तो आप शुरुआती परिवेश में x के नाम को देखना चाहते हैं जिसमें printItपरिभाषित किया गया था, लेकिन आप उस मान को देखना चाहते हैं जो नाम उस वातावरण में बंधा हुआ printItहै जिसे कहा जाता है (बाद setItमें किसी भी संख्या में कॉल किया जा सकता है) )।

ऐसा करने के लिए दो IORefs के पास तरीके हैं, लेकिन आपको निश्चित रूप से आपके द्वारा प्रस्तावित बाद के प्रकार से अधिक की आवश्यकता है, जो आपको उन मूल्यों को बदलने की अनुमति नहीं देता है जो नाम एक lexically-scoped फ़ैशन में बंधे हैं। Google बहुत सारे दिलचस्प प्रागितिहास के लिए "फंगल की समस्या" है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.