क्या IO मोनाड तकनीकी रूप से गलत है?


12

हैस्केल विकी पर IO मोनड के सशर्त उपयोग का निम्न उदाहरण है (यहां देखें)

when :: Bool -> IO () -> IO ()
when condition action world =
    if condition
      then action world
      else ((), world)

ध्यान दें कि इस उदाहरण में, सब कुछ अधिक समझने के IO aलिए होने की परिभाषा ली गई है RealWorld -> (a, RealWorld)

यह स्निपेट सशर्त रूप से IO सनक में एक कार्रवाई को अंजाम देता है। अब, यह सोचते हैं कि conditionहै False, कार्रवाई actionकभी नहीं निष्पादित किया जाना चाहिए। आलसी शब्दार्थों का प्रयोग करना वास्तव में यही होगा। हालांकि, यहां यह ध्यान दिया जाता है कि हास्केल तकनीकी रूप से गैर-सख्त बोल रहा है। इसका मतलब यह है कि संकलक को अनुमति दी जाती है, उदाहरण के लिए, action worldएक अलग थ्रेड पर preemptively रन , और बाद में जब यह पता चलता है कि यह जरूरत नहीं है कि अभिकलन फेंक देते हैं। हालाँकि, उस बिंदु तक दुष्प्रभाव पहले ही हो चुके होंगे।

अब, कोई IO सनक को इस तरह से लागू कर सकता है कि साइड-इफेक्ट्स केवल तभी प्रचारित किए जाते हैं जब पूरा कार्यक्रम समाप्त हो जाता है, और हम जानते हैं कि कौन से साइड-इफेक्ट्स निष्पादित किए जाने चाहिए। हालांकि, यह मामला नहीं है, क्योंकि हास्केल में अनंत कार्यक्रम लिखना संभव है, जिसमें स्पष्ट रूप से मध्यवर्ती साइड-इफेक्ट्स हैं।

क्या इसका मतलब यह है कि आईओ सनक तकनीकी रूप से गलत है, या कुछ और है जो इसे होने से रोक रहा है?


कंप्यूटर विज्ञान में आपका स्वागत है ! यहां आपका प्रश्न ऑफ़-टॉपिक है: हम कंप्यूटर विज्ञान के प्रश्नों से निपटते हैं , प्रोग्रामिंग प्रश्नों से नहीं (हमारे FAQ देखें )। आपका सवाल स्टैक ओवरफ्लो पर ऑन-टॉपिक हो सकता है ।
डेकाए

2
मेरी राय में यह एक कंप्यूटर विज्ञान का प्रश्न है, क्योंकि यह हास्केल के सैद्धांतिक शब्दार्थों से संबंधित है, न कि व्यावहारिक प्रोग्रामिंग प्रश्न के साथ।
लास

4
मैं प्रोग्रामिंग भाषा सिद्धांत से बहुत परिचित नहीं हूं, लेकिन मुझे लगता है कि यह सवाल यहां विषय पर है। यदि आप यह स्पष्ट करते हैं कि यहाँ क्या 'गलत' का अर्थ है। आपको क्या लगता है कि आईओ सन्यासी के पास ऐसी संपत्ति है जो उसके पास नहीं होनी चाहिए?
छिपकली

1
यह कार्यक्रम अच्छी तरह से टाइप नहीं किया गया है। मुझे यकीन नहीं है कि आप वास्तव में क्या लिखना चाहते थे। की परिभाषा whenटाइप करने योग्य है, लेकिन इसमें वह प्रकार नहीं है जिसे आप घोषित करते हैं, और मैं यह नहीं देखता कि यह विशेष कोड क्या दिलचस्प बनाता है।
गिलेस एसओ- बुराई को रोकना

2
इस कार्यक्रम को सीधे ऊपर दिए गए हास्केल-विकी पृष्ठ से शब्दशः लिया गया है। यह वास्तव में टाइप नहीं करता है। ऐसा इसलिए है क्योंकि यह उस धारणा के तहत लिखा गया IO aहै जिसे RealWorld -> (a, RealWorld)IO के आंतरिक को अधिक पठनीय बनाने के लिए परिभाषित किया गया है ।
लास

जवाबों:


12

यह IOभिक्षु की एक सुझाई गई "व्याख्या" है । यदि आप इस "व्याख्या" को गंभीरता से लेना चाहते हैं, तो आपको "रियलवर्ल्ड" को गंभीरता से लेने की आवश्यकता है। यह अप्रासंगिक है कि action worldसट्टा का मूल्यांकन किया जाता है या नहीं, actionइसका कोई साइड-इफेक्ट नहीं है, इसके प्रभाव, यदि कोई हैं, तो ब्रह्मांड के एक नए राज्य को वापस करने के द्वारा नियंत्रित किया जाता है जहां उन प्रभावों को हुआ है, जैसे कि एक नेटवर्क पैकेट भेजा गया है। हालांकि, फ़ंक्शन का परिणाम है ((),world)और इसलिए ब्रह्मांड की नई स्थिति है world। हम नए ब्रह्माण्ड का उपयोग नहीं करते हैं जो हमारे पास सटिक रूप से पक्ष में मूल्यांकन किया जा सकता है। ब्रह्मांड की स्थिति है world

आपको शायद उस समय को गंभीरता से लेना चाहिए। ऐसे कई तरीके हैं जो सर्वोत्तम सतही विरोधाभासी और निरर्थक हैं। इस दृष्टिकोण के साथ विशेष रूप से गैर-स्पष्ट या पागल है।

"रुको, रुको," आप कहते हैं। " RealWorldसिर्फ एक 'टोकन' है। यह वास्तव में पूरे ब्रह्मांड की स्थिति नहीं है।" ठीक है, फिर यह "व्याख्या" कुछ भी नहीं समझाती है। फिर भी, एक कार्यान्वयन विवरण के रूप में , यह जीएचसी मॉडल कैसे है IO1 हालांकि, इसका मतलब है कि हमारे पास जादुई "कार्य" हैं जो वास्तव में दुष्प्रभाव हैं और यह मॉडल उनके अर्थ के लिए कोई मार्गदर्शन प्रदान नहीं करता है। और, चूंकि इन कार्यों के वास्तव में दुष्प्रभाव हैं, आप जो चिंता उठाते हैं वह पूरी तरह से बिंदु पर है। GHC है अपने रास्ते से हट जाने के लिए सुनिश्चित करने के लिए है RealWorldऔर इन विशेष कार्य तरीके कि कार्यक्रम का इरादा व्यवहार को बदलने में अनुकूलित नहीं कर रहे हैं।

व्यक्तिगत रूप से (जैसा कि शायद अब तक स्पष्ट है), मुझे लगता है कि यह "विश्व-पासिंग" मॉडल IOसिर्फ बेकार है और एक शैक्षणिक उपकरण के रूप में भ्रमित है। (क्या यह कार्यान्वयन के लिए उपयोगी है, मुझे नहीं पता। जीएचसी के लिए, मुझे लगता है कि यह एक ऐतिहासिक कलाकृतियों से अधिक है।)

एक वैकल्पिक दृष्टिकोण IOप्रतिक्रिया हैंडलर के साथ एक वर्णन अनुरोध के रूप में देखना है । इसे करने के कई तरीके हैं। संभवतः सबसे सुलभ एक मुक्त मोनाद निर्माण का उपयोग करना है, विशेष रूप से हम उपयोग कर सकते हैं:

data IO a = Return a | Request OSRequest (OSResponse -> IO a)

इसे और अधिक परिष्कृत बनाने के कई तरीके हैं और कुछ बेहतर गुण हैं, लेकिन यह पहले से ही एक सुधार है। इसे समझने के लिए वास्तविकता की प्रकृति के बारे में गहरी दार्शनिक मान्यताओं की आवश्यकता नहीं है। यह सब बताता है कि IOया तो एक तुच्छ कार्यक्रम है Returnजो कुछ भी नहीं करता है लेकिन एक मूल्य वापस करता है, या यह प्रतिक्रिया के लिए एक हैंडलर के साथ ऑपरेटिंग सिस्टम के लिए एक अनुरोध है। OSRequestकुछ इस तरह हो सकता है:

data OSRequest = OpenFile FilePath | PutStr String | ...

इसी तरह, OSResponseकुछ इस तरह हो सकता है:

data OSResponse = Errno Int | OpenSucceeded Handle | ...

(जो सुधार किए जा सकते हैं उनमें से एक है चीजों को और अधिक सुरक्षित बनाना ताकि आप जानते हैं कि आप अनुरोध OpenSucceededसे नहीं मिलेंगे PutStr।) यह मॉडल IOअनुरोधों का वर्णन करने के लिए है जो किसी प्रणाली द्वारा व्याख्या की जाती हैं ("असली" IOइस के लिए। हास्केल रनटाइम खुद), और फिर, शायद, वह सिस्टम उस हैंडलर को कहेगा जिसे हमने प्रतिक्रिया के साथ प्रदान किया है। यह, ज़ाहिर है, यह भी कोई संकेत नहीं देता है कि अनुरोध को कैसे PutStr "hello world"संभाला जाना चाहिए, लेकिन यह भी ढोंग नहीं करता है। यह स्पष्ट करता है कि यह किसी अन्य प्रणाली को सौंपा जा रहा है। यह मॉडल भी बहुत सटीक है। आधुनिक OSes में सभी उपयोगकर्ता कार्यक्रमों को कुछ भी करने के लिए OS से अनुरोध करने की आवश्यकता होती है।

यह मॉडल सही अंतर्ज्ञान प्रदान करता है। उदाहरण के लिए, कई शुरुआती लोग <-ऑपरेटर की तरह चीजों को "अलिखित" के रूप में देखते हैं IO, या (दुर्भाग्य से प्रबलित) यह मानते हैं कि IO Stringए, कहते हैं, एक "कंटेनर" है जिसमें " Stringएस " होता है (और फिर <-उन्हें बाहर निकालता है)। यह अनुरोध-प्रतिक्रिया दृश्य इस परिप्रेक्ष्य को स्पष्ट रूप से गलत बनाता है। अंदर कोई फ़ाइल हैंडल नहीं है OpenFile "foo" (\r -> ...)। इस पर जोर देने के लिए एक सामान्य सादृश्य यह है कि केक के लिए एक नुस्खा के अंदर कोई केक नहीं है (या शायद "चालान" इस मामले में बेहतर होगा)।

यह मॉडल संक्षिप्तता के साथ आसानी से काम करता है। हमारे पास आसानी से OSRequestजैसे के लिए एक कंस्ट्रक्टर हो सकता है Fork :: (OSResponse -> IO ()) -> OSRequestऔर फिर रनटाइम इस अतिरिक्त हैंडलर द्वारा उत्पादित अनुरोधों को सामान्य हैंडलर के साथ इंटरलेव कर सकता है, हालांकि इसे पसंद करता है। कुछ चतुराई के साथ आप इस (या संबंधित तकनीकों) का उपयोग वास्तव में संगोष्ठी जैसी चीजों को सीधे कहने के बजाय "हम ओएस के लिए एक अनुरोध करते हैं और चीजें होती हैं।" यह IOSpecपुस्तकालय कैसे काम करता है।

1 Hugs ने एक निरंतरता-आधारित कार्यान्वयन का उपयोग किया, IOजो कि स्पष्ट डेटा प्रकार के बजाय अपारदर्शी कार्यों के साथ मेरे द्वारा वर्णित वर्णन के समान है। एचबीसी ने पुराने अनुरोध-प्रतिक्रिया स्ट्रीम-आधारित IO पर जारी एक निरंतरता-आधारित कार्यान्वयन का भी उपयोग किया। NHC (और इस प्रकार YHC) ने थ्रक्स का उपयोग किया, अर्थात मोटे तौर पर IO a = () -> aहालांकि ()इसे बुलाया गया था World, लेकिन यह राज्य-पासिंग नहीं कर रहा है। जेएचसी और यूएचसी मूल रूप से जीएचसी के समान दृष्टिकोण का उपयोग करते थे।


आपके ज्ञानवर्धक उत्तर के लिए धन्यवाद, इससे वास्तव में मदद मिली। IO के आपके कार्यान्वयन ने मेरे दिमाग को चारों ओर लपेटने में कुछ समय लिया, लेकिन मैं मानता हूं कि यह अधिक सहज है। क्या आप दावा कर रहे हैं कि यह कार्यान्वयन साइड-इफेक्ट्स के साथ संभावित समस्याओं से ग्रस्त नहीं है जैसे कि RealWorld कार्यान्वयन करता है? मैं तुरंत कोई समस्या नहीं देख सकता, लेकिन यह मेरे लिए भी स्पष्ट नहीं है कि वे मौजूद नहीं हैं।
लास

एक टिप्पणी: ऐसा लगता है कि OpenFile "foo" (\r -> ...)वास्तव में होना चाहिए Request (OpenFile "foo") (\r -> ...)?
लास

@ लासेप हां, इसके साथ होना चाहिए था Request। आपके पहले प्रश्न का उत्तर देने के लिए, यह IOमूल्यांकन क्रम (मोडुलो बॉटम्स) के लिए स्पष्ट रूप से असंवेदनशील है क्योंकि यह एक अक्रिय मूल्य है। सभी मूल्य (यदि कोई हो) इस मूल्य की व्याख्या करने वाली चीज द्वारा किए जाएंगे। में whenउदाहरण के लिए, इससे कोई फर्क नहीं होता अगर actionका मूल्यांकन किया गया था, क्योंकि यह सिर्फ एक मूल्य की तरह होगा Request (PutStr "foo") (...)जो हम बात वैसे भी इन अनुरोधों की व्याख्या करने के लिए नहीं देंगे। यह सोर्स कोड की तरह है; इससे कोई फर्क नहीं पड़ता अगर आप इसे उत्सुकता या आलस से कम करते हैं, तब तक कुछ नहीं होता है जब तक कि यह एक दुभाषिया को नहीं दिया जाता है।
डेरेक एल्किन्स ने एसई

आह हाँ मैं वही देखता हूँ। यह वास्तव में चतुर परिभाषा है। पहले मैंने सोचा था कि पूरे कार्यक्रम को पूरा करने के बाद सभी साइड-इफ़ेक्ट ज़रूरी हो जाएंगे, क्योंकि इसकी व्याख्या करने से पहले आपको डेटस्ट्रक्चर का निर्माण करना होगा। लेकिन चूँकि अनुरोध में एक निरंतरता होती है, इसलिए आपको केवल Requestसाइड-इफ़ेक्ट देखना शुरू करने के लिए बहुत पहले डेटा का निर्माण करना होगा । निरंतरता का मूल्यांकन करते समय बाद के दुष्प्रभाव पैदा किए जा सकते हैं। चालाक!
लास
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.