टीएल; डीआर। इन चारों में से सभी कार्य केवल टाइपकास्ट हैं। वे रन-टाइम पर सभी नो-ऑप हैं। केवल उनके बीच के अंतर प्रकार हस्ताक्षर — है लेकिन यह प्रकार हस्ताक्षर कि पहली जगह में सभी सुरक्षा की गारंटी देता है लागू है!
ST
इकाई और IO
इकाई दोनों आप परिवर्तनशील राज्य दे।
IO
मोनड से बचने के लिए यह बेहद असंभव है। [ठीक है, नहीं, तुम अगर आप unsafePerformIO
उपयोग कर सकते हैं। ऐसा मत करो!] इस वजह से, सब मैं/हे कि अपने कार्यक्रम कभी प्रदर्शन एक विशाल IO
ब्लॉक में बंडल हो जाता है, इस प्रकार के संचालन पर एक वैश्विक आदेश को लागू करने। [कम से कम, जब तक आप forkIO
फोन है, लेकिन वैसे भी ...]
कारण unsafePerformIO
इतना असुरक्षित शापित है, है कि वहाँ , अगर कोई रास्ता नहीं वास्तव में जब यह पता लगाने की है या कितनी बार संलग्न मैं/हे ऑपरेशंस — होगा जो आमतौर पर बहुत बुरी चीज है।
ST
इकाई भी परिवर्तनशील राज्य प्रदान करता है, लेकिन यह करता बचने तंत्र — runST
समारोह है। यह आपको एक शुद्ध एक में एक अशुद्ध मूल्य बदलने देता है। लेकिन अब वहाँ कोई रास्ता नहीं गारंटी करने के लिए क्या आदेश अलग ST
ब्लॉकों में चलेंगे। क्रम पूरा तबाही को रोकने के लिए है, तो हम यह सुनिश्चित करें कि अलग ST
ब्लॉक एक दूसरे के साथ नहीं "हस्तक्षेप" कर सकते हैं की जरूरत है।
इसी कारण से, आप ST
मोनैड में कोई I/O संचालन नहीं कर सकते हैं। आप परिवर्तनीय स्थिति तक पहुंच सकते हैं, लेकिन उस राज्य को ST
ब्लॉक से बचने की अनुमति नहीं है।
IO
मोनड और ST
मोनड वास्तव में समान मोनैड हैं। और IORef
वास्तव में एक STRef
है, और इसी तरह। तो यह वास्तव में हंसमुख उपयोगी द्वारा कोड लिख सकते हैं और दोनों monads में इसका इस्तेमाल करने में सक्षम हो जाएगा। और आपके द्वारा बताए गए सभी चार कार्य प्रकार-प्रकार हैं जो आपको बिल्कुल ऐसा करने देते हैं।
खतरे को समझने के लिए, हमें यह समझने की आवश्यकता है कि ST
इसकी छोटी सी चाल कैसे प्राप्त करता है। यह सभी प्रकार के प्रेत में s
प्रकार में है। एक ST
ब्लॉक चलाने के लिए, यह सब संभव s
के लिए काम करने की जरूरत:
runST :: (forall s. ST s x) -> x
सभी परिवर्तनशील सामान प्रकार में s
रूप में अच्छी तरह है, और एक खुश दुर्घटना से, इसका मतलब है कि किसी भी प्रयास को बाहर परिवर्तनशील सामान वापस करने के लिए कि ST
मोनड बीमार टाइप किया जाएगा। (यह वास्तव में एक हैक का थोड़ा सा है, लेकिन यह बहुत पूरी तरह से काम करता है ...)
कम से कम, यदि आप runST
का उपयोग करते हैं तो यह खराब टाइप किया जाएगा। ध्यान दें कि ioToST
आपको ST RealWorld x
देता है। लगभग बोलते हुए, IO x
और लगभग; ST RealWorld x
। लेकिन runST
इनपुट के रूप में स्वीकार नहीं करेगा। तो आप I/O चलाने के लिए runST
का उपयोग नहीं कर सकते।
ioToST
आपको एक प्रकार देता है जिसे आप runST
के साथ उपयोग नहीं कर सकते हैं। लेकिन unsafeIOToST
आपको एक प्रकार देता है जो runST
के साथ ठीक काम करता है। एक अनुमान क्या चल रहा है ले
foobar = do
v <- unsafeSTToIO (newSTRef 42)
let w = runST (readSTRef v)
let x = runST (writeSTRef v 99)
print w
वाना:
unsafePerformIO = runST . ioToST
unsafeSTToIO
आप दूसरे में एक ST
ब्लॉक से बाहर परिवर्तनशील सामान पाने के लिए, और संभवतः अनुमति देता है: उस समय, आप मूल रूप से unsafePerformIO
को लागू किया है मुद्रित करने के लिए? क्योंकि बात यह है कि हमारे पास तीन ST
क्रियाएं हैं, जो बिल्कुल किसी भी क्रम में हो सकती हैं। readSTRef
writeSTRef
से पहले या उसके बाद होगा?
[वास्तव में, इस उदाहरण में, लेखन कभी नहीं होता है, क्योंकि हम x
के साथ कुछ भी नहीं करते हैं। लेकिन अगर मैं कोड के कुछ दूर, असंबद्ध हिस्से में x
पास करता हूं, और वह कोड इसका निरीक्षण करने के लिए होता है, अचानक हमारे आई/ओ ऑपरेशन कुछ अलग करता है। शुद्ध कोड ऐसा परिवर्तनशील सामान प्रभावित करने के लिए सक्षम नहीं होना चाहिए]
संपादित करें: ऐसा प्रतीत होता है मैं थोड़ा समय से पहले था। unsafeSTToIO
फ़ंक्शन आपको ST
मोनैड से एक म्यूटेबल मान लेने की अनुमति देता है, लेकिन ऐसा लगता है कि इसे पर एक दूसरी कॉल की आवश्यकता है ताकि म्यूटेबल चीज़ को ST
मोनड फिर से डाला जा सके। आप कुछ unsafeIOToST
में पाठ्यक्रम मिश्रण के रूप में अच्छी तरह कर सकता है (उस समय, दोनों कार्य IO
कार्रवाई, इसलिए उनके आदेश की गारंटी है कर रहे हैं।)
, लेकिन वास्तव में साबित नहीं होता कि unsafeSTToIO
से ही असुरक्षित है:
foobar = do
v <- unsafeSTToIO (newSTRef 42)
let w = runST (unsafeIOToST $ unsafeSTToIO $ readSTRef v)
let x = runST (unsafeIOToST $ unsafeSTToIO $ writeSTRef v 99)
print w
मैं इस के साथ चारों ओर खेला है, और मैं अभी तक इस प्रकार चेकर को समझाने के लिए मुझे कुछ provably असुरक्षित केवलunsafeSTToIO
का उपयोग कर करते हैं करने में कामयाब नहीं किया है। मुझे विश्वास है कि यह किया जा सकता है, और इस सवाल पर विभिन्न टिप्पणियां सहमत हैं, लेकिन मैं वास्तव में एक उदाहरण नहीं बना सकता। हालांकि आपको विचार मिलता है; प्रकारों को बदलें, और आपकी सुरक्षा टूट जाती है।
अंतर इस प्रकार में है।ioToST केवल 'एसटी रियलवर्ल्ड ए' उत्पन्न कर सकता है जिसे आप 'runST :: (forall s। एसटी एस) -> ए' तक नहीं पारित कर सकते हैं। – user2407038