एक साधु को देखने के विभिन्न तरीके


29

हास्केल सीखते समय, मैंने बहुत सारे ट्यूटोरियल का सामना करने की कोशिश की है जो यह समझाने की कोशिश कर रहे हैं कि हास्केल में मोनाड्स और मोनाड्स क्यों महत्वपूर्ण हैं। उनमें से प्रत्येक ने सादृश्य का उपयोग किया ताकि अर्थ को पकड़ना आसान हो। दिन के अंत में, मेरे पास 3 अलग-अलग दृष्टिकोण हैं जो एक सनक है:

दृश्य 1: एक लेबल के रूप में मोनाड

कभी-कभी मुझे लगता है कि एक विशिष्ट प्रकार के लेबल के रूप में एक सनक। उदाहरण के लिए, प्रकार का एक कार्य:

myfunction :: IO Int

myfunction एक फ़ंक्शन है जिसे जब भी किया जाता है तो यह एक Int मान प्राप्त करेगा। परिणाम का प्रकार Int नहीं है, बल्कि IO Int है। इसलिए, आईओ इंट वैल्यू का एक लेबल है जो उपयोगकर्ता को यह जानने के लिए चेतावनी देता है कि इंट वैल एक प्रक्रिया का परिणाम है जहां एक आईओ कार्रवाई की गई है।

नतीजतन, इस Int मान को IO के साथ एक प्रक्रिया से आए मान के रूप में चिह्नित किया गया है इसलिए यह मान "गंदा" है। आपकी प्रक्रिया अब शुद्ध नहीं है।

दृश्य 2: मोनाद एक निजी स्थान के रूप में जहाँ बुरा काम हो सकता है।

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

दृश्य 3: श्रेणी सिद्धांत के रूप में मोनाड

यह वह दृश्य है जिसे मैं पूरी तरह से नहीं समझता। एक मोनाड एक ही श्रेणी या एक उप-श्रेणी के लिए एक फ़नकार है। उदाहरण के लिए, आपके पास Int मान हैं और एक उपश्रेणी IO Int के रूप में, IO प्रक्रिया के बाद उत्पन्न मान हैं।

क्या ये विचार सही हैं? कौन सा अधिक सटीक है?


5
# 2 वह नहीं है जो सामान्य रूप से एक सनक है। वास्तव में, यह IO के लिए बहुत सीमित है, और एक उपयोगी दृश्य नहीं है (cf. क्या एक मोनाड नहीं है )। इसके अलावा, "सख्त" आम तौर पर एक संपत्ति के नाम के लिए लिया जाता है हास्केल के पास नहीं है (अर्थात् सख्त मूल्यांकन)। वैसे, मोनाड्स या तो नहीं बदलते हैं (फिर से, देखें कि एक मोनाड क्या नहीं है)।

3
तकनीकी रूप से, केवल तीसरा एक सही है। मोनाड एंडोफ़ुन्क्टर है, जो विशेष ऑपरेशन के लिए परिभाषित किया गया है - पदोन्नति और बंधन। मोनाड कई हैं - मोनाड्स के पीछे अंतर्ज्ञान प्राप्त करने के लिए एक सूची मोनाड एक आदर्श उदाहरण है। रीड की सुविधाएं और भी बेहतर हैं। पर्याप्त रूप से आश्चर्यचकित करते हुए, संन्यासी के रूप में उपयोग किए जाने योग्य हैं जो शुद्ध रूप से कार्यात्मक भाषा में राज्य को पिरोते हैं। यह भिक्षुओं की एक परिभाषित संपत्ति नहीं है: यह संयोग है, कि राज्य सूत्रण को उनकी शर्तों में लागू किया जा सकता है। वही IO पर लागू होता है।
पर्क्रेरा

भाषा के हिस्से के रूप में कॉमन लिस्प का अपना कंपाइलर है। हास्केल के पास मोनाड्स हैं।
विल नेस

जवाबों:


33

दृश्य # 1 और # 2 सामान्य रूप से गलत हैं।

  1. किसी भी प्रकार का डेटा- * -> *लेबल लेबल के रूप में काम कर सकता है, मोनैड्स इससे कहीं अधिक हैं।
  2. ( IOमोनाड के अपवाद के साथ ) एक सन्यासी के भीतर गणना अशुद्ध नहीं है। वे केवल उन संगणनाओं का प्रतिनिधित्व करते हैं जिन्हें हम साइड इफेक्ट्स के रूप में देखते हैं, लेकिन वे शुद्ध हैं।

ये दोनों गलतफहमी IOमोनाड पर ध्यान केंद्रित करने से आती हैं , जो वास्तव में थोड़ा खास है।

यदि संभव हो तो श्रेणी सिद्धांत में शामिल किए बिना, मैं # 3 पर थोड़ा विस्तार करने की कोशिश करूंगा।


मानक अभिकलन

एक कार्यात्मक प्रोग्रामिंग भाषा में सभी संगणना को स्रोत प्रकार और लक्ष्य प्रकार के साथ कार्यों के रूप में देखा जा सकता है f :: a -> b:। यदि किसी फ़ंक्शन में एक से अधिक तर्क हैं, तो हम इसे करीने से एक-तर्क फ़ंक्शन में बदल सकते हैं ( हास्केल विकी भी देखें )। और अगर हम सिर्फ एक मूल्य है x :: a(0 तर्क के साथ एक समारोह), हम इसे एक समारोह है कि का एक तर्क लेता है में बदल सकते हैं इकाई प्रकार : (\_ -> x) :: () -> a

हम .ऑपरेटर का उपयोग करके इस तरह के कार्यों की रचना करके अधिक जटिल कार्यक्रमों को सरल बना सकते हैं । उदाहरण के लिए, यदि हमारे पास है f :: a -> bऔर g :: b -> cहम प्राप्त करते हैं g . f :: a -> c। ध्यान दें कि यह हमारे रूपांतरित मूल्यों के लिए भी काम करता है: यदि हमारे पास है x :: aऔर इसे हमारे प्रतिनिधित्व में बदल देता है, तो हम प्राप्त करते हैं f . ((\_ -> x) :: () -> a) :: () -> b

इस प्रतिनिधित्व के कुछ बहुत महत्वपूर्ण गुण हैं, अर्थात्:

  • हमारे पास एक विशेष कार्य है - प्रत्येक प्रकार के लिए पहचान समारोह । यह सम्मान के साथ एक पहचान तत्व है : दोनों के लिए और बराबर है ।id :: a -> aa.ff . idid . f
  • समारोह रचना ऑपरेटर .है साहचर्य

मोनडिक संगणनाएँ

मान लीजिए कि हम कुछ विशेष श्रेणी की संगणनाओं के साथ चयन और काम करना चाहते हैं, जिनके परिणाम में केवल एकल रिटर्न मान से अधिक कुछ है। हम निर्दिष्ट नहीं करना चाहते हैं कि "कुछ और" का क्या मतलब है, हम चीजों को यथासंभव सामान्य रखना चाहते हैं। "कुछ और" का प्रतिनिधित्व करने का सबसे सामान्य तरीका एक प्रकार के फ़ंक्शन के रूप में प्रतिनिधित्व कर रहा है - एक प्रकार mका * -> *(यानी यह एक प्रकार को दूसरे में परिवर्तित करता है)। इसलिए प्रत्येक श्रेणी की संगणना के लिए, जिसके साथ हम काम करना चाहते हैं, हमारे पास कुछ प्रकार के कार्य होंगे m :: * -> *। (में हास्केल, mहै [], IO, Maybe, आदि) और श्रेणी इच्छा प्रकार के सभी कार्यों में शामिल है a -> m b

अब हम इस तरह की श्रेणी में कार्यों के साथ उसी तरह काम करना चाहेंगे जैसे कि मूल मामले में। हम इन कार्यों की रचना करने में सक्षम होना चाहते हैं, हम चाहते हैं कि रचना सहयोगी हो, और हम एक पहचान बनाना चाहते हैं। ज़रुरत है:

  • एक ऑपरेटर के लिए (चलो इसे कॉल करें <=<) जो फ़ंक्शन f :: a -> m bऔर g :: b -> m cकुछ के रूप में रचना करता है g <=< f :: a -> m c। और, यह सहयोगी होना चाहिए।
  • प्रत्येक प्रकार के लिए कुछ पहचान कार्य करने के लिए, आइए इसे कॉल करें return। हम भी चाहते हैं कि f <=< returnजैसा fऔर जैसा है, वैसा ही हो return <=< f

कोई भी m :: * -> *जिसके लिए हमारे पास ऐसे कार्य हैं returnऔर <=<उसे एक मोनाड कहा जाता है । यह हमें सरल मामलों से जटिल गणनाएँ बनाने की अनुमति देता है, जैसे कि मूल मामले में, लेकिन अब रिटर्न वैल्यूज़ के प्रकारों को बदल दिया जाता है m

(वास्तव में, मैंने यहां शब्द श्रेणी का थोड़ा दुरुपयोग किया है। श्रेणी-सिद्धांत अर्थ में हम अपने निर्माण को एक श्रेणी कह सकते हैं, जब हम जानते हैं कि यह इन कानूनों का पालन करता है।)

हास्केल में मठ

हास्केल (और अन्य कार्यात्मक भाषाओं) में हम ज्यादातर मूल्यों के साथ काम करते हैं, न कि प्रकारों के कार्यों के साथ () -> a। इसलिए <=<प्रत्येक मोनाड को परिभाषित करने के बजाय , हम एक फ़ंक्शन को परिभाषित करते हैं (>>=) :: m a -> (a -> m b) -> m b। ऐसी वैकल्पिक परिभाषा समतुल्य है, हम इसका >>=उपयोग <=<और इसके विपरीत व्यक्त कर सकते हैं (एक अभ्यास के रूप में प्रयास करें, या स्रोतों को देखें )। सिद्धांत अब कम स्पष्ट है, लेकिन यह समान है: हमारे परिणाम हमेशा प्रकार के होते हैं m aऔर हम प्रकारों के कार्यों की रचना करते हैं a -> m b

हमारे द्वारा बनाए गए प्रत्येक मोनाड के लिए, हमें यह जांचना नहीं भूलना चाहिए returnऔर हमारे <=<पास आवश्यक गुण हैं: सहानुभूति और बाएं / दाएं पहचान। का उपयोग करके व्यक्त किया गया returnऔर >>=उन्हें मोनाड कानून कहा जाता है

एक उदाहरण - सूचियाँ

यदि हम mहोना चुनते हैं [], तो हमें प्रकार के कार्यों की एक श्रेणी मिलती है a -> [b]। ऐसे कार्य गैर-नियतात्मक संगणनाओं का प्रतिनिधित्व करते हैं, जिनके परिणाम एक या अधिक मूल्य हो सकते हैं, लेकिन यह भी कोई मूल्य नहीं है। यह तथाकथित सूची मोनाद को जन्म देता है । की संरचना f :: a -> [b]और g :: b -> [c]निम्नानुसार काम करती है: प्रकार के g <=< f :: a -> [c]सभी संभावित परिणामों की गणना करने का मतलब है [b], gउनमें से प्रत्येक पर लागू होता है, और सभी परिणामों को एक सूची में इकट्ठा करता है। हास्केल में व्यक्त किया

return :: a -> [a]
return x = [x]
(<=<) :: (b -> [c]) -> (a -> [b]) -> (a -> [c])
g (<=<) f  = concat . map g . f

या उपयोग कर रहा है >>=

(>>=) :: [a] -> (a -> [b]) -> [b]
x >>= f  = concat (map f x)

ध्यान दें कि इस उदाहरण में रिटर्न प्रकार इस प्रकार थे [a]कि यह संभव था कि उनके पास किसी प्रकार का मूल्य न हो a। वास्तव में, एक सन्यासी के लिए ऐसी कोई आवश्यकता नहीं होती है कि रिटर्न प्रकार में ऐसे मान होने चाहिए। कुछ साधुओं के पास हमेशा (जैसे IOया State) होते हैं, लेकिन कुछ पसंद नहीं करते हैं []या जैसे होते हैं Maybe

आईओ मोनद

जैसा कि मैंने उल्लेख किया है, IOसन्यासी कुछ विशेष है। प्रकार के मूल्य का IO aअर्थ है aकार्यक्रम के वातावरण के साथ बातचीत करके निर्मित प्रकार का मूल्य । इसलिए (सभी अन्य साधुओं के विपरीत), हम IO aकुछ शुद्ध निर्माण का उपयोग करके प्रकार के मूल्य का वर्णन नहीं कर सकते हैं । यहां IOकेवल एक टैग या एक लेबल है जो पर्यावरण के साथ बातचीत करने वाले कम्प्यूटेशंस को अलग करता है। यह (एकमात्र मामला) है जहां विचार # 1 और # 2 सही हैं।

के लिए IOइकाई:

  • संरचना f :: a -> IO bऔर g :: b -> IO cसाधन: गणना fजो पर्यावरण के साथ सहभागिता करता है, और फिर गणना gकरता है जो मूल्य का उपयोग करता है और पर्यावरण के साथ बातचीत करने वाले परिणाम की गणना करता है।
  • returnबस IO"टैग" को मूल्य में जोड़ता है (हम पर्यावरण को बरकरार रखते हुए परिणाम को "गणना" करते हैं)।
  • संन्यासी द्वारा मोनाड कानूनों (संघात्मकता, पहचान) की गारंटी दी जाती है।

कुछ नोट:

  1. चूंकि मोनाडिक अभिकलन में हमेशा परिणाम प्रकार होता है m a, इसलिए कोई तरीका नहीं है कि कैसे IOमोनाड से "बच" जाए । अर्थ यह है: एक बार एक संगणना पर्यावरण के साथ सहभागिता करती है, आप उससे एक अभिकलन का निर्माण नहीं कर सकते।
  2. जब एक कार्यात्मक प्रोग्रामर कुछ नहीं जानता कि कैसे शुद्ध तरीके से कुछ बनाना है, तो वह ( अंतिम उपाय के रूप में ) IOमोनाड के भीतर कुछ स्टेटफुल कम्प्यूटेशन द्वारा कार्य को कर सकता है । यही कारण है कि IOअक्सर एक प्रोग्रामर के पाप बिन कहा जाता है ।
  3. ध्यान दें कि एक अशुद्ध दुनिया में (कार्यात्मक प्रोग्रामिंग के अर्थ में) एक मान पढ़ने से पर्यावरण भी बदल सकता है (जैसे उपयोगकर्ता के इनपुट का उपभोग करना)। इसीलिए जैसे कार्यों getCharका एक परिणाम प्रकार होना चाहिए IO something

3
बहुत बढ़िया जवाब। मैं स्पष्ट करूँगा कि IOकिसी भाषा के दृष्टिकोण से विशेष शब्दार्थ नहीं है। यह विशेष नहीं है , यह किसी भी अन्य कोड की तरह व्यवहार करता है। केवल रनटाइम लाइब्रेरी कार्यान्वयन विशेष है। इसके अलावा, भागने का एक विशेष-उद्देश्य है ( unsafePerformIO)। मुझे लगता है कि यह महत्वपूर्ण है क्योंकि लोग अक्सर IOएक विशेष भाषा तत्व या एक घोषणात्मक टैग के रूप में सोचते हैं । यह नहीं।
usr

2
@usr अच्छा बिंदु। मैं जोड़ना होगा कि unsafePerformIO वास्तव में है असुरक्षित और केवल विशेषज्ञों द्वारा किया जाना चाहिए। यह आपको सब कुछ तोड़ने की अनुमति देता है, उदाहरण के लिए, आप एक फ़ंक्शन बना सकते हैं coerce :: a -> bजो किसी भी दो प्रकारों को परिवर्तित करता है (और ज्यादातर मामलों में आपके प्रोग्राम को क्रैश कर सकता है)। इस उदाहरण को देखें - आप किसी फ़ंक्शन को Intआदि में भी बदल सकते हैं
पेट्र पुडलक

एक और "विशेष जादू" मोनड एसटी होगा, जो आपको स्मृति के संदर्भों की घोषणा करने की अनुमति देता है जिसे आप पढ़ सकते हैं और जैसा कि आप फिट देखते हैं (हालांकि केवल मठ के भीतर) लिख सकते हैं, और फिर आप कॉल करके एक परिणाम निकाल सकते हैंrunST :: (forall s. GHC.ST.ST s a) -> a
सारा

5

दृश्य 1: एक लेबल के रूप में मोनाड

"नतीजतन, इस Int मान को IO के साथ एक प्रक्रिया से आए मूल्य के रूप में चिह्नित किया गया है इसलिए यह मान" गंदा "है।"

"आईओ इंट" सामान्य रूप से एक इंट वैल्यू नहीं है (हालांकि यह कुछ मामलों में हो सकता है जैसे "रिटर्न 3")। यह एक ऐसी प्रक्रिया है जो कुछ इंट वैल्यू को आउटपुट करती है। इस "प्रक्रिया" के विभिन्न निष्पादन अलग-अलग Int मान प्राप्त कर सकते हैं।

एक मोनड एम, एक एम्बेडेड (अनिवार्य) "प्रोग्रामिंग भाषा" है: इस भाषा के भीतर कुछ "प्रक्रियाओं" को परिभाषित करना संभव है। एक मौद्रिक मूल्य (प्रकार मा का), इस "प्रोग्रामिंग भाषा" में एक प्रक्रिया है जो प्रकार के मान का आउटपुट करता है।

उदाहरण के लिए:

foo :: IO Int

कुछ प्रक्रिया है जो Int के प्रकार का मान उत्पन्न करती है।

फिर:

bar :: IO (Int, Int)
bar = do
  a <- foo
  b <- foo
  return (a,b)

कुछ प्रक्रिया है जो दो (संभवतः अलग) इनट्स को आउटपुट करती है।

ऐसी हर "भाषा" कुछ कार्यों का समर्थन करती है:

  • दो प्रक्रियाएँ (मा और mb) "संक्षिप्त" हो सकती हैं: आप पहले एक के बाद एक बड़ी प्रक्रिया (ma >> mb) बना सकते हैं, फिर दूसरा;

  • पहले एक का अधिक उत्पादन (ए) दूसरे को प्रभावित कर सकता है (मा >> = \ a -> ...);

  • एक प्रक्रिया (रिटर्न x) कुछ निरंतर मान (x) प्राप्त कर सकती है।

अलग-अलग एम्बेडेड प्रोग्रामिंग भाषाएं उन चीजों पर भिन्न होती हैं जिनका वे समर्थन करते हैं:

  • यादृच्छिक मूल्यों की उपज;
  • "फोर्किंग" ([] मोनड);
  • अपवाद (थ्रो / कैच) (या तो ई मोनड);
  • स्पष्ट निरंतरता / कॉलक समर्थन;
  • अन्य "एजेंटों" को संदेश भेजना / प्राप्त करना;
  • वैरिएबल (इस प्रोग्रामिंग भाषा के लिए स्थानीय) (एसटी मोनाड) बनाएं, सेट करें और पढ़ें।

1

भिक्षु वर्ग के साथ एक राक्षसी प्रकार को भ्रमित न करें।

एक मोनैडिक प्रकार (यानी एक प्रकार का मोनड क्लास का उदाहरण) एक विशेष समस्या को हल करेगा (सिद्धांत रूप में, प्रत्येक मोनैडिक प्रकार एक अलग हल करता है): स्टेट, रैंडम, शायद, आईओ। वे सभी संदर्भ के साथ प्रकार हैं (जिसे आप "लेबल" कहते हैं, लेकिन ऐसा नहीं है जो उन्हें एक सनक बनाता है)।

उन सभी के लिए, "विकल्प के साथ संचालन का पीछा" की आवश्यकता है (एक ऑपरेशन पिछले के परिणाम पर निर्भर करता है)। यहाँ मोनड क्लास खेलने के लिए आता है: आपके प्रकार (दी गई समस्या को हल करना) एक प्रकार का मोनड क्लास हो सकता है और चैनिंग की समस्या हल हो जाती है।

देखें कि सन्यासी वर्ग क्या हल करता है?

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