सन्यासी क्या होता है?


1414

हाल ही में हास्केल को संक्षेप में देखने पर, एक संक्षिप्त, संक्षिप्त, व्यावहारिक स्पष्टीकरण क्या होगा जो अनिवार्य रूप से एक सनक है?

मुझे सबसे अधिक स्पष्टीकरण मिला है कि मैं काफी दुर्गम हो गया हूं और व्यावहारिक विस्तार में कमी है।


12
एरिक लिपर्ट ने इस सवाल का जवाब लिखा ( stackoverflow.com/questions/2704652/… ), जो कुछ मुद्दों के कारण एक अलग पेज में रहता है।
पी शेव्ड

70
यहाँ जावास्क्रिप्ट का उपयोग करके एक नया परिचय दिया गया है - मुझे यह बहुत पठनीय लगा।
बेंजोल



2
एक संन्यासी सहायक कार्यों के साथ कार्यों की एक सरणी है। इसका उत्तर
cibercitizen1

जवाबों:


1059

पहला: अगर आप गणितज्ञ नहीं हैं, तो मोनड शब्द थोड़ा खाली है। एक वैकल्पिक शब्द अभिकलन बिल्डर है जो वास्तव में उनके लिए उपयोगी होने का थोड़ा अधिक विवरणात्मक है।

आप व्यावहारिक उदाहरण के लिए पूछें:

उदाहरण 1: सूची समझ :

[x*2 | x<-[1..10], odd x]

यह अभिव्यक्ति 1 से 10. तक की सभी विषम संख्याओं के युगल को बहुत उपयोगी बताती है!

यह पता चला है कि यह सूची मोनाड के भीतर कुछ कार्यों के लिए वास्तव में सिर्फ वाक्यात्मक चीनी है। एक ही सूची समझ के रूप में लिखा जा सकता है:

do
   x <- [1..10]
   guard (odd x)
   return (x * 2)

या और भी:

[1..10] >>= (\x -> guard (odd x) >> return (x*2))

उदाहरण 2: इनपुट / आउटपुट :

do
   putStrLn "What is your name?"
   name <- getLine
   putStrLn ("Welcome, " ++ name ++ "!")

दोनों उदाहरणों में मोनाड्स, एकेए कम्प्यूटेशन बिल्डरों का उपयोग किया गया है। सामान्य विषय यह है कि कुछ विशिष्ट, उपयोगी तरीके से मोनाड चेन का संचालन होता है। सूची की समझ में, संचालन ऐसे जंजीरों में जकड़े हुए हैं कि यदि कोई ऑपरेशन सूची देता है, तो सूची में प्रत्येक आइटम पर निम्नलिखित संचालन किए जाते हैं । दूसरी ओर IO मोनाड क्रमिक रूप से संचालन करता है, लेकिन साथ में एक "छिपा हुआ चर" गुजरता है, जो "दुनिया की स्थिति" का प्रतिनिधित्व करता है, जो हमें शुद्ध कार्यात्मक तरीके से I / O कोड लिखने की अनुमति देता है।

यह पता चला है कि चेनिंग ऑपरेशन का पैटर्न काफी उपयोगी है और इसका उपयोग हास्केल में बहुत सी विभिन्न चीजों के लिए किया जाता है।

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

दोनों सूची-बोध वाक्यविन्यास और >>=संचालक का उपयोग करते हुए परिचालनों का संचालन करने के लिए संकेतन चीनी हैं । एक मोनाड मूल रूप से केवल एक प्रकार है जो >>=ऑपरेटर का समर्थन करता है ।

उदाहरण 3: एक तोता

यह एक बहुत ही सरल पार्सर है जो या तो एक उद्धृत स्ट्रिंग या संख्या को पार करता है:

parseExpr = parseString <|> parseNumber

parseString = do
        char '"'
        x <- many (noneOf "\"")
        char '"'
        return (StringValue x)

parseNumber = do
    num <- many1 digit
    return (NumberValue (read num))

संचालन char, digitआदि बहुत सरल कर रहे हैं। वे या तो मेल खाते हैं या मेल नहीं खाते। जादू एक ऐसा सन्यासी है जो नियंत्रण प्रवाह का प्रबंधन करता है: संचालन क्रमिक रूप से तब तक किया जाता है जब तक कि कोई मैच विफल न हो जाए, इस स्थिति में मोनाड नवीनतम पर वापस आ जाता है <|>और अगले विकल्प की कोशिश करता है। फिर, कुछ अतिरिक्त, उपयोगी शब्दार्थों के साथ संचालन का एक तरीका।

उदाहरण 4: अतुल्यकालिक प्रोग्रामिंग

उपरोक्त उदाहरण हास्केल में हैं, लेकिन यह F # को भी मोनाड्स का समर्थन करता है। यह उदाहरण डॉन सिम से चुराया गया है :

let AsyncHttp(url:string) =
    async {  let req = WebRequest.Create(url)
             let! rsp = req.GetResponseAsync()
             use stream = rsp.GetResponseStream()
             use reader = new System.IO.StreamReader(stream)
             return reader.ReadToEnd() }

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

अधिकांश अन्य भाषाओं में आपको स्पष्ट रूप से प्रतिक्रिया को संभालने वाली लाइनों के लिए एक अलग फ़ंक्शन बनाना होगा। asyncइकाई "विभाजन" करने के लिए अपने आप ही ब्लॉक में सक्षम है और उत्तरार्ध के निष्पादन को स्थगित। ( async {}सिंटैक्स इंगित करता है कि ब्लॉक में नियंत्रण प्रवाह को asyncमोनाड द्वारा परिभाषित किया गया है ।)

वे कैसे काम करते हैं

तो एक सन्यासी इन सभी फैंसी नियंत्रण-प्रवाह को कैसे कर सकता है? वास्तव में एक डो-ब्लॉक (या एक गणना अभिव्यक्ति के रूप में वे एफ # में कहा जाता है) में होता है, यह है कि प्रत्येक ऑपरेशन (मूल रूप से प्रत्येक पंक्ति) एक अलग अनाम फ़ंक्शन में लपेटा जाता है। इन कार्यों को तब bindऑपरेटर ( >>=हास्केल में वर्तनी ) का उपयोग करके संयोजित किया जाता है । चूंकि bindऑपरेशन कार्यों को जोड़ती है, इसलिए यह उन्हें निष्पादित कर सकता है क्योंकि यह फिट देखता है: क्रमिक रूप से, कई बार, रिवर्स में, कुछ को त्यागें, कुछ को एक अलग थ्रेड पर निष्पादित करें जब यह ऐसा लगता है और इसी तरह।

एक उदाहरण के रूप में, यह उदाहरण 2 से IO- कोड का विस्तारित संस्करण है:

putStrLn "What is your name?"
>>= (\_ -> getLine)
>>= (\name -> putStrLn ("Welcome, " ++ name ++ "!"))

यह बदसूरत है, लेकिन यह और भी स्पष्ट है कि वास्तव में क्या चल रहा है। >>=ऑपरेटर जादू घटक है: यह (दाईं ओर) एक समारोह के साथ (बाईं ओर) एक मूल्य है और यह जोड़ती है लेता है, एक नया मान उत्पादन करने के लिए। यह नया मान फिर अगले >>=ऑपरेटर द्वारा लिया जाता है और फिर से एक नए मूल्य का उत्पादन करने के लिए एक फ़ंक्शन के साथ जोड़ा जाता है। >>=एक मिनी-मूल्यांकनकर्ता के रूप में देखा जा सकता है।

ध्यान दें कि >>=विभिन्न प्रकारों के लिए अतिभारित है, इसलिए प्रत्येक मोनाड का अपना कार्यान्वयन है >>=। (श्रृंखला के सभी ऑपरेशनों को हालांकि एक ही मोनाड के प्रकार का होना चाहिए, अन्यथा >>=ऑपरेटर काम नहीं करेगा।)

बस का सरलतम संभव कार्यान्वयन >>=बाईं ओर मान लेता है और इसे दाईं ओर फ़ंक्शन पर लागू करता है और परिणाम लौटाता है, लेकिन जैसा कि पहले कहा गया है, जो पूरे पैटर्न को उपयोगी बनाता है वह यह है कि मोनाद के कार्यान्वयन में कुछ अतिरिक्त चल रहा है >>=

एक ऑपरेशन से दूसरे ऑपरेशन में मूल्यों को कैसे पारित किया जाता है, इसमें कुछ अतिरिक्त चतुराई है, लेकिन इसके लिए हास्केल प्रकार प्रणाली की गहन व्याख्या की आवश्यकता है।

उपसंहार

हास्केल-शब्दों में एक मोनाड एक मानकीकृत प्रकार है जो मोनाड प्रकार के वर्ग का एक उदाहरण है, जो >>=कुछ अन्य ऑपरेटरों के साथ परिभाषित करता है । आम आदमी की शर्तों में, एक मोनाड सिर्फ एक प्रकार है जिसके लिए >>=ऑपरेशन को परिभाषित किया जाता है।

अपने आप >>=में चाइनिंग फंक्शंस का एक बोझिल तरीका है, लेकिन "प्लंबिंग" को छिपाने वाली डू-नोटेशन की उपस्थिति के साथ, मोनैडिक ऑपरेशंस बहुत अच्छा और उपयोगी एब्सट्रैक्शन, भाषा में उपयोगी कई जगह, और उपयोगी हो जाता है। भाषा में अपनी लघु-भाषा बनाने के लिए।

भिक्षु कठिन क्यों होते हैं?

कई हास्केल-शिक्षार्थियों के लिए, मोनड्स एक बाधा है जिसे वे ईंट की दीवार की तरह मारते हैं। ऐसा नहीं है कि मोनैड्स स्वयं जटिल हैं, लेकिन यह कि कार्यान्वयन कई अन्य उन्नत हास्केल सुविधाओं पर निर्भर करता है जैसे कि मानकीकृत प्रकार, प्रकार की कक्षाएं, और इसी तरह। समस्या यह है कि हास्केल I / O भिक्षुओं पर आधारित है, और I / O संभवत: पहली चीजों में से एक है जिसे आप एक नई भाषा सीखते समय समझना चाहते हैं - आखिरकार, यह उन कार्यक्रमों को बनाने के लिए बहुत मजेदार नहीं है जो किसी भी चीज का उत्पादन नहीं करते हैं उत्पादन। मेरे पास इस चिकन और अंडे की समस्या का कोई तत्काल समाधान नहीं है, सिवाय इसके कि मैं / ओ जैसा "जादू यहां होता है" जब तक आपके पास भाषा के अन्य हिस्सों के साथ पर्याप्त अनुभव न हो। माफ़ करना।

भिक्षुओं पर उत्कृष्ट ब्लॉग: http://adit.io/posts/2013-04-17-functors,_applicatives,_and_monads_in_pictures.html


65
जैसा कि कोई है, जिसे भिक्षुओं को समझने में बहुत परेशानी होती है, मैं कह सकता हूं कि इस उत्तर ने मदद की .. थोड़ा। हालाँकि, अभी भी कुछ चीजें हैं जो मुझे समझ नहीं आ रही हैं। किस तरह से सूची एक साधु को समझती है? क्या उस उदाहरण का विस्तारित रूप है? एक और बात जो मुझे वास्तव में सबसे अधिक सनक के बारे में परेशान करती है, जिसमें यह भी शामिल है- कि क्या वे "एक सन्यासी है?" "क्या एक भिक्षु अच्छा है?" और "एक संन्यासी को कैसे लागू किया जाता है?"। जब आपने लिखा था कि "एक संन्यासी मूल रूप से >> = ऑपरेटर का समर्थन करने वाला एक प्रकार है।" जो मेरे पास था ...
ब्रेटन

82
इसके अलावा मैं आपके निष्कर्ष से असहमत हूं कि भिक्षु कठिन क्यों होते हैं। यदि मोनैड्स स्वयं जटिल नहीं हैं, तो आपको यह समझाने में सक्षम होना चाहिए कि वे सामान के एक गुच्छा के बिना क्या हैं। जब मैं सवाल पूछता हूं कि "मैं एक सन्यासी क्या हूं" तो मैं कार्यान्वयन के बारे में नहीं जानना चाहता हूं, मैं यह जानना चाहता हूं कि खुजली होने का क्या मतलब है। अब तक ऐसा लगता है कि इसका उत्तर है "क्योंकि हैस्केल के लेखक सैडोमोस्कोसिस्ट हैं और उन्होंने फैसला किया कि आपको सरल चीजों को पूरा करने के लिए कुछ बेवकूफी से जटिल काम करना चाहिए, इसलिए आपको हैक्सेल का उपयोग करने के लिए मोनाड्स सीखना होगा, न कि इसलिए कि वे किसी भी उपयोगी हैं। खुद "...
ब्रेटन

69
लेकिन .. यह सही नहीं हो सकता है? मुझे लगता है कि भिक्षु कठिन होते हैं क्योंकि किसी को यह पता नहीं लग सकता है कि कार्यान्वयन विवरण को भ्रमित करने के बिना उन्हें कैसे समझाया जाए। मेरा मतलब है .. एक स्कूल बस क्या है? यह सामने की ओर एक डिवाइस के साथ एक धातु प्लेटफॉर्म है जो एक चक्र में कुछ धातु पिस्टन में ड्राइव करने के लिए एक परिष्कृत पेट्रोलियम उत्पाद का उपभोग करता है, जो बदले में कुछ गियर से जुड़े एक क्रैंक शाफ्ट को घुमाता है जो कुछ पहियों को चलाता है। पहियों ने अपने चारों ओर रबर की थैलियों को फुलाया है, जो एक अगप की सतह के साथ इंटरफेस करती है जिससे आगे बढ़ने के लिए सीटों का संग्रह होता है। सीटें आगे बढ़ जाती हैं क्योंकि ...
ब्रेटन

130
मैं यह सब पढ़ता हूं और अभी भी नहीं जानता कि एक सन्यासी क्या है, इस तथ्य से अलग कि यह हास्केल प्रोग्रामर को समझाने के लिए पर्याप्त नहीं है। उदाहरण बहुत मदद नहीं करते हैं, यह देखते हुए कि ये सभी चीजें हैं जो बिना किसी मोनाड के कर सकते हैं, और यह उत्तर यह स्पष्ट नहीं करता है कि भिक्षु उन्हें कैसे आसान बनाते हैं, केवल और अधिक भ्रमित करते हैं। इस उत्तर का एक हिस्सा जो उपयोगी होने के करीब आया था, उदाहरण के # 2 के वाक्यविन्यास चीनी को हटा दिया गया था। मैं कहता हूं कि पहली पंक्ति से अलग होने के कारण, विस्तार मूल के किसी भी वास्तविक समानता को सहन नहीं करता है।
लॉरेंस गोंसाल्वेस

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

712

"क्या एक संन्यासी है" यह बताते हुए कि "संख्या क्या है?" हम हर समय संख्याओं का उपयोग करते हैं। लेकिन कल्पना कीजिए कि आप किसी ऐसे व्यक्ति से मिले जो संख्याओं के बारे में कुछ नहीं जानता था। कैसे बिल्ली आप की व्याख्या करता है क्या नंबर दिए गए हैं? और आप यह भी वर्णन करना शुरू करेंगे कि यह उपयोगी क्यों हो सकता है?

सन्यासी क्या होता है? संक्षिप्त उत्तर: यह एक साथ परिचालन संचालन का एक विशिष्ट तरीका है।

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

तो बाइंड फ़ंक्शन एक अर्धविराम की तरह है; यह एक प्रक्रिया में चरणों को अलग करता है। बाइंड फ़ंक्शन का काम आउटपुट को पिछले चरण से लेना है, और इसे अगले चरण में फीड करना है।

यह बहुत मुश्किल ध्वनि नहीं है, है ना? लेकिन एक से अधिक प्रकार के मोनाड हैं। क्यों? कैसे?

खैर, बाइंड फ़ंक्शन केवल एक कदम से परिणाम ले सकता है , और इसे अगले चरण में खिला सकता है। लेकिन अगर वह सब "मोनाड" करता है ... जो वास्तव में बहुत उपयोगी नहीं है। और यह समझना महत्वपूर्ण है: हर उपयोगी सन्यासी सिर्फ एक सन्यासी होने के अलावा कुछ और करता है । प्रत्येक उपयोगी मोनाड में एक "विशेष शक्ति" होती है, जो इसे अद्वितीय बनाती है।

(एक ऐसा सन्यासी, जो कुछ खास नहीं करता है, उसे "पहचान सन्यासी" कहा जाता है। पहचान समारोह की तरह, यह पूरी तरह से निरर्थक बात की तरह लगता है, फिर भी पता नहीं चलता है ... लेकिन यह एक और कहानी ™ है।)

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

  • यदि प्रत्येक चरण एक सफलता / विफलता संकेतक देता है, तो आप अगले चरण को केवल तभी निष्पादित कर सकते हैं जब पिछले वाला सफल हो गया हो। इस तरह, एक असफल कदम पूरे अनुक्रम को "स्वचालित रूप से" समाप्त कर देता है, बिना किसी सशर्त परीक्षण के। ( विफलता मोनाड ।)

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

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

  • एक चरण से दूसरे चरण में "परिणाम" पास करने के साथ-साथ, आप बाँध फ़ंक्शन पास के अतिरिक्त डेटा को भी पास कर सकते हैं । यह डेटा अब आपके स्रोत कोड में दिखाई नहीं देता है, लेकिन आप अभी भी इसे कहीं से भी एक्सेस कर सकते हैं, बिना इसे मैन्युअल रूप से हर फ़ंक्शन को पास करने के लिए। ( पाठक मोनाद ।)

  • आप इसे बना सकते हैं ताकि "अतिरिक्त डेटा" को बदला जा सके। यह आपको विनाशकारी अपडेट का अनुकरण करने की अनुमति देता है , वास्तव में विनाशकारी अपडेट किए बिना। ( स्टेट मोनाड और इसके चचेरे भाई लेखक मोनाड ।)

  • क्योंकि आप केवल विनाशकारी अद्यतनों का अनुकरण कर रहे हैं , आप वास्तविक विनाशकारी अद्यतनों के साथ असंभव काम कर सकते हैं । उदाहरण के लिए, आप पिछले अपडेट को पूर्ववत कर सकते हैं , या पुराने संस्करण में वापस ला सकते हैं ।

  • आप एक मोनाड बना सकते हैं जहां गणना को रोका जा सकता है , इसलिए आप अपने कार्यक्रम को रोक सकते हैं, आंतरिक स्थिति डेटा के साथ अंदर जा सकते हैं और फिर इसे फिर से शुरू कर सकते हैं।

  • आप एक मठ के रूप में "निरंतरता" को लागू कर सकते हैं। यह आपको लोगों के दिमाग को तोड़ने की अनुमति देता है !

यह और सब कुछ मठों के साथ संभव है। बेशक, यह सब बिना मोनाड के भी पूरी तरह से संभव है। भिक्षुओं का उपयोग करना बहुत आसान है


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

1
हास्केल में कम से कम, मोनाड्स के अधिकांश ओवरहेड को आशावादी द्वारा छीन लिया जाता है। तो मस्तिष्क की शक्ति में केवल वास्तविक "लागत" आवश्यक है। (यह महत्वपूर्ण नहीं है अगर "स्थिरता" वह चीज है जिसके बारे में आप परवाह करते हैं।) लेकिन आमतौर पर, मोनाड्स चीजों को आसान बनाते हैं , कठिन नहीं। (अन्यथा, आप क्यों परेशान होंगे?)
गणितीयऑक्रिड

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

15
एक गैर-गणित, गैर-कार्यात्मक प्रोग्रामिंग पृष्ठभूमि से आ रहा है, इस जवाब ने मुझे सबसे अधिक समझ में आया।
ज्राहली

10
यह पहला उत्तर है जिसने वास्तव में मुझे कुछ विचार दिया कि नरक क्या है। इसे समझाने का तरीका खोजने के लिए धन्यवाद!
रोबॉटमेय

186

दरअसल, मोनाड्स की आम समझ के विपरीत, उनका राज्य से कोई लेना-देना नहीं है। मोनाड बस चीजों को लपेटने का एक तरीका है और बिना लिपटे इसे लपेटे हुए सामान पर संचालन करने के तरीके प्रदान करते हैं।

उदाहरण के लिए, आप हास्केल में एक दूसरे को लपेटने के लिए एक प्रकार बना सकते हैं:

data Wrapped a = Wrap a

सामान लपेटने के लिए हम परिभाषित करते हैं

return :: a -> Wrapped a
return x = Wrap x

बिना किसी ऑपरेशन के प्रदर्शन करने के लिए, कहें कि आपके पास एक फ़ंक्शन है f :: a -> b, तो आप ऐसा कर सकते हैं कि लिपटे मूल्यों पर कार्य करने के लिए उस फ़ंक्शन को उठाएं :

fmap :: (a -> b) -> (Wrapped a -> Wrapped b)
fmap f (Wrap x) = Wrap (f x)

बस इतना ही समझना है। हालांकि, यह पता चला है कि इस उठाने के लिए एक अधिक सामान्य कार्य है , जो है bind:

bind :: (a -> Wrapped b) -> (Wrapped a -> Wrapped b)
bind f (Wrap x) = f x

bindसे थोड़ा अधिक कर सकते हैं fmap, लेकिन इसके विपरीत नहीं। वास्तव में, fmapकेवल के रूप में परिभाषित किया जा सकता है bindऔर return। इसलिए, जब एक साधु को परिभाषित करते हैं .. तो आप इसके प्रकार (यहां यह था Wrapped a) देते हैं और फिर कहते हैं कि इसके returnऔर bindसंचालन कैसे काम करते हैं।

अच्छी बात यह है कि यह एक सामान्य पैटर्न है कि यह सभी जगह पर पॉप अप होता है, शुद्ध तरीके से राज्य को घेरना केवल उनमें से एक है।

कार्यात्मक निर्भरता का परिचय देने के लिए और इस तरह मूल्यांकन के नियंत्रण आदेश का उपयोग कैसे किया जा सकता है, इस पर एक अच्छे लेख के लिए, जैसे कि हास्केल के आईओ मोनड में इसका उपयोग किया जाता है, आईओ इनसाइड देखें

भिक्षुओं को समझने के लिए, इसके बारे में बहुत ज्यादा चिंता न करें। उनके बारे में पढ़ें जो आपको दिलचस्प लगता है और चिंता न करें अगर आप अभी नहीं समझते हैं। तब हास्केल जैसी भाषा में सिर्फ डाइविंग करना ही रास्ता है। मोनाड इन चीजों में से एक है जहां अभ्यास द्वारा आपके मस्तिष्क में चाल को समझना, एक दिन जब आप अचानक महसूस करते हैं कि आप उन्हें समझते हैं।


-> राइट-एसोसिएटिव है, मिररिंग फंक्शन एप्लीकेशन है, जो लेफ्ट-एसोसिएटिव है, इसलिए कोष्ठकों को छोड़ देने से यहां कोई फर्क नहीं पड़ता है।
मथायस बेंकार्ड

1
मुझे नहीं लगता कि यह बिल्कुल अच्छी व्याख्या है। मोनाड्स बस एक तरीका है? ठीक है, कौन सा रास्ता? मैं एक सन्यासी के बजाय एक वर्ग का उपयोग क्यों नहीं करूंगा?
ब्रेटन

4
@ mb21: यदि आप केवल यह इंगित कर रहे हैं कि बहुत सारे ब्रैकेट हैं, तो ध्यान दें कि a-> b-> c वास्तव में केवल a -> (b-> c) के लिए कम है। इस विशेष उदाहरण को (- ए - बी) -> (टा -> टीबी) के रूप में लिखते हुए सख्ती से सिर्फ अकारण पात्रों को जोड़ते हुए बात की जाती है, लेकिन यह नैतिक रूप से "सही काम करने वाला" है क्योंकि यह इस बात पर जोर देता है कि फैंप मैप एक प्रकार का एक फ़ंक्शन -> b के प्रकार के एक समारोह में Ta -> Tb। और मूल रूप से, यह है कि श्रेणी सिद्धांत में फंक्शनलर्स क्या करते हैं और यही वह जगह है जहां से भिक्षु आते हैं।
निकोलज-के

1
यह उत्तर भ्रामक है। कुछ साधुओं में "रैपर" बिल्कुल नहीं होता है, ऐसे कार्य एक निश्चित मूल्य से होते हैं।

1
@DanMandel मोनाड्स डिज़ाइन पैटर्न हैं जो अपने स्वयं के डेटाटाइप आवरण की आपूर्ति करते हैं। मोनोड्स को बॉयलर बॉयलरप्लेट कोड को सार करने के लिए डिज़ाइन किया गया है। तो जैसा कि आप अपने कोड में एक मोनाड कहते हैं, यह पर्दे के सामान के पीछे करता है जिसके बारे में आप चिंता नहीं करना चाहते हैं। Nullable <T> या IEnumerable <T> के बारे में सोचो, वे पर्दे के पीछे क्या करते हैं? वह मोनाड।
स्कालजज

168

लेकिन, आप मोनाड्स का आविष्कार कर सकते थे!

सिगफ़ेप कहता है:

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

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

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


9
... सबसे अच्छा तरीका न केवल इंटरनेट पर, बल्कि कहीं भी। ( कार्यात्मक प्रोग्रामिंग के लिए वाडलर का मूल पेपर मोनाड्स, जिसका मैंने नीचे अपने उत्तर में उल्लेख किया है, वह भी अच्छा है।) ट्यूटोरियल-बाय- एनालॉग के कोई भी ज़िल्लोन करीब नहीं आते हैं।
श्रीवत्सआर

13
सिगफेप के पोस्ट का यह जावास्क्रिप्ट अनुवाद लोगों को सीखने के लिए सबसे अच्छा तरीका है, जो पहले से ही उन्नत हास्केल को ग्रो नहीं करते हैं!
सैम वाटकिंस

1
इस तरह मैंने सीखा कि एक सन्यासी क्या होता है। एक अवधारणा का आविष्कार करने की प्रक्रिया के माध्यम से पाठक चलना अक्सर अवधारणा को पढ़ाने का सबसे अच्छा तरीका है।
जॉर्डन

हालांकि, स्क्रीन फ़ंक्शन को तर्क के रूप में स्वीकार करने और संशोधित पाठ के साथ इसकी प्रतिलिपि वापस करने वाला एक फ़ंक्शन शुद्ध होगा।
दिमित्री जैतसेव

87

एक मोनाड एक डेटाटाइप है जिसमें दो ऑपरेशन होते हैं: >>=(उर्फ bind) और return(उर्फ unit)। returnएक मनमाना मूल्य लेता है और इसके साथ मठ का एक उदाहरण बनाता है। >>=मोनाड का एक उदाहरण लेता है और इस पर एक फ़ंक्शन मैप करता है। (आप पहले से ही देख सकते हैं कि एक मोनाड एक अजीब प्रकार का डेटाटाइप है, क्योंकि अधिकांश प्रोग्रामिंग भाषाओं में आप एक फ़ंक्शन नहीं लिख सकते हैं जो एक मनमाना मूल्य लेता है और इससे एक प्रकार का निर्माण करता है। मोनाड्स एक प्रकार के पैरामीट्रिक बहुरूपता का उपयोग करते हैं ।)

हास्केल संकेतन में, मोनाड इंटरफ़ेस लिखा गया है

class Monad m where
  return :: a -> m a
  (>>=) :: forall a b . m a -> (a -> m b) -> m b

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

मोनाड केवल राज्य और I / O के बारे में नहीं हैं: वे गणना के एक सामान्य पैटर्न को सार करते हैं जिसमें राज्य, I / O, अपवाद और गैर-नियतत्ववाद के साथ काम करना शामिल है। संभवतः समझने के लिए सबसे सरल मठ हैं सूचियां और विकल्प प्रकार:

instance Monad [ ] where
    []     >>= k = []
    (x:xs) >>= k = k x ++ (xs >>= k)
    return x     = [x]

instance Monad Maybe where
    Just x  >>= k = k x
    Nothing >>= k = Nothing
    return x      = Just x

जहां []और :सूची निर्माता ये हैं, ++संयोजन ऑपरेटर है, और Justऔर Nothingकर रहे हैं Maybeकंस्ट्रक्टर्स। ये दोनों मोनाड अपने संबंधित डेटा प्रकारों पर गणना के सामान्य और उपयोगी पैटर्न को नोट करते हैं (ध्यान दें कि न तो साइड इफेक्ट्स या आई / ओ के साथ कुछ करना है)।

आपको वास्तव में कुछ गैर-तुच्छ हास्केल कोड लिखने के लिए खेलना होगा, जो इस बात की सराहना करते हैं कि भिक्षुओं के बारे में क्या है और वे क्यों उपयोगी हैं।


"नक्शों का क्या मतलब है?"
केसबश

Casebash, मैं परिचय में जानबूझकर अनौपचारिक हो रहा हूं। "मैपिंग ए फंक्शन" की भावना पाने के लिए अंत के पास के उदाहरण देखें।
क्रिस कॉनवे

3
मोनाड एक डेटाटाइप नहीं है। यह रचना करने का नियम है: stackoverflow.com/a/37345315/1614973
दिमित्री जैतसेव

@DmitriZaitsev सही है, मोनाड्स वास्तव में अपने स्वयं के डेटा प्रकार प्रदान करते हैं, मोनड्स डेटा प्रकारों को
छोड़ते हैं

78

आपको सबसे पहले समझना चाहिए कि एक फनकार क्या है। इससे पहले, उच्च-क्रम के कार्यों को समझें।

एक उच्च-क्रम फ़ंक्शन केवल एक फ़ंक्शन है जो फ़ंक्शन को तर्क के रूप में लेता है।

एक फ़ंक्टर किसी भी प्रकार का निर्माण Tहै जिसके लिए एक उच्च-क्रम फ़ंक्शन मौजूद है, इसे कॉल करें map, जो फ़ंक्शन के प्रकार a -> b(किसी भी दो प्रकार ) aऔर bएक फ़ंक्शन में बदल देता है T a -> T b। इस mapफ़ंक्शन को भी पहचान और संरचना के नियमों का पालन करना चाहिए ताकि निम्नलिखित अभिव्यक्तियाँ सभी के लिए सही हों pऔर q(हास्केल संकेतन):

map id = id
map (p . q) = map p . map q

उदाहरण के लिए, एक प्रकार का कंस्ट्रक्टर जिसे कहा जाता है Listवह एक फ़नकार है यदि यह एक प्रकार के फ़ंक्शन से सुसज्जित है (a -> b) -> List a -> List bजो उपरोक्त कानूनों का पालन करता है। केवल व्यावहारिक कार्यान्वयन स्पष्ट है। परिणामी List a -> List bफ़ंक्शन दी गई सूची पर निर्भर (a -> b)करता है, प्रत्येक तत्व के लिए फ़ंक्शन को बुलाता है , और परिणामों की सूची लौटाता है।

एक इकाई मात्र हैं एक functor है Tदो अतिरिक्त तरीकों के साथ, join, प्रकार की T (T a) -> T aहै, और unit(कभी कभी कहा जाता है return, forkया pureप्रकार के) a -> T a। हास्केल में सूची के लिए:

join :: [[a]] -> [a]
pure :: a -> [a]

क्यों उपयोगी है? क्योंकि आप, उदाहरण के लिए, mapएक सूची के साथ एक सूची में जो एक सूची देता है। Joinसूचियों की परिणामी सूची लेता है और उन्हें संक्षिप्त करता है। Listएक भिक्षु है क्योंकि यह संभव है।

आप एक फ़ंक्शन लिख सकते हैं जो mapतब करता है join। इस फ़ंक्शन को कहा जाता है bind, या flatMap, या (>>=), या (=<<)। यह आम तौर पर हास्केल में एक मोनड उदाहरण दिया जाता है।

एक संन्यासी को कुछ कानूनों को संतुष्ट joinकरना पड़ता है , अर्थात् साहचर्य होना चाहिए। इसका मतलब है कि यदि आपके पास xप्रकार का मूल्य है [[[a]]]तो join (join x)बराबर होना चाहिए join (map join x)। और इस तरह के pureलिए एक पहचान होनी चाहिए ।joinjoin (pure x) == x


3
'उच्च क्रम फ़ंक्शन' को परिभाषित करने के लिए थोड़ा अतिरिक्त: वे OR RURURN फ़ंक्शन ले सकते हैं। इसलिए वे 'उच्च' हैं, क्योंकि वे चीजों को खुद से करते हैं।
केविन वोन

9
उस परिभाषा के अलावा, एक उच्च-क्रम फ़ंक्शन है। यह एक संख्या लेता है और एक फ़ंक्शन देता है जो उस संख्या को दूसरे में जोड़ता है। तो नहीं, उच्चतर ऑर्डर फ़ंक्शंस ऐसे फ़ंक्शंस हैं जिनके डोमेन में फ़ंक्शंस होते हैं।
Apocalisp

वीडियो ' ब्रायन बेकमैन: डन डरा द मोनाद ' तर्क की इसी पंक्ति का अनुसरण करता है।
icc97

48

[अस्वीकरण: मैं अभी भी पूरी तरह से भिक्षुओं को ग्रसने की कोशिश कर रहा हूं। निम्नलिखित सिर्फ वही है जो मैंने अब तक समझा है। अगर यह गलत है, तो उम्मीद है कि कोई जानकार मुझे कालीन पर बुलाएगा।]

अरनार ने लिखा:

मोनाड बस चीजों को लपेटने का एक तरीका है और बिना लिपटे इसे लपेटे गए सामान पर संचालन करने के तरीके प्रदान करते हैं।

ठीक यही है। विचार इस प्रकार है:

  1. आप किसी तरह का मूल्य लेते हैं और इसे कुछ अतिरिक्त जानकारी के साथ लपेटते हैं। जैसे मान एक निश्चित प्रकार का होता है (जैसे। पूर्णांक या स्ट्रिंग), तो अतिरिक्त जानकारी एक निश्चित प्रकार की होती है।

    उदाहरण के लिए, अतिरिक्त जानकारी एक Maybeया एक हो सकती है IO

  2. फिर आपके पास कुछ ऑपरेटर हैं जो आपको उस अतिरिक्त जानकारी के साथ ले जाने के दौरान लिपटे डेटा पर काम करने की अनुमति देते हैं। ये ऑपरेटर अतिरिक्त जानकारी का उपयोग यह तय करने के लिए करते हैं कि लिपटे मूल्य पर ऑपरेशन के व्यवहार को कैसे बदलना है।

    जैसे, Maybe Inta Just Intया हो सकता है Nothing। अब, यदि आप एक Maybe Intको जोड़ते हैं Maybe Int, तो ऑपरेटर यह देखने के लिए जाँच करेगा कि क्या वे दोनों Just Intअंदर हैं, और यदि ऐसा है, तो Intएस को अनफ्रेंड कर देंगे , उन्हें अतिरिक्त ऑपरेटर पास कर देंगे, परिणामस्वरूप रि-रैप Intको एक नया Just Int(जो एक मान्य हो) Maybe Int), और इस प्रकार वापसी Maybe Int। लेकिन अगर उनमें से एक Nothingअंदर था , तो यह ऑपरेटर बस तुरंत वापस आ जाएगा Nothing, जो फिर से वैध है Maybe Int। इस तरह, आप यह दिखावा कर सकते हैं कि आपके Maybe Ints सिर्फ सामान्य संख्या हैं और उन पर नियमित गणित करते हैं। यदि आप एक पाने के लिए थे Nothing, तो आपके समीकरण अभी भी सही परिणाम उत्पन्न करेंगे - आपके बिना Nothingहर जगह की जांच करने के लिए

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

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

और इसीलिए लोग भिक्षुओं को इतना भ्रामक पाते हैं: क्योंकि वे एक ऐसी सामान्य अवधारणा हैं। यह पूछने के लिए कि कोई चीज क्या बनाती है, यह वैसा ही अस्पष्ट है जैसा कि यह पूछना कि कोई चीज क्या पैटर्न बनाती है।

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

यही कारण है कि जो लोग भिक्षुओं को समझते हैं, उन्हें इतना उपयोगी लगता है : यह कुछ हाथी दांत टॉवर अवधारणा नहीं है जो बौद्धिक स्नोबॉल खुद को समझने पर गर्व करते हैं (ठीक है, वह भी बेशक, टीह), लेकिन वास्तव में कोड को सरल बनाता है।


12
कभी-कभी एक "शिक्षार्थी" (आप की तरह) से एक स्पष्टीकरण एक विशेषज्ञ से आने वाले स्पष्टीकरण की तुलना में दूसरे शिक्षार्थी के लिए अधिक प्रासंगिक है। शिक्षार्थियों को समान लगता है :)
एड्रियन

क्या कुछ बनाता है एक प्रकार्य के साथ एक समारोह का अस्तित्व है M (M a) -> M a। यह तथ्य कि आप इसे एक प्रकार में बदल सकते हैं, जो M a -> (a -> M b) -> M bउन्हें उपयोगी बनाता है।
जेरेमी सूची

"मोनाड" का मोटे तौर पर मतलब "पैटर्न" है ... नहीं।
धन्यवाद

44

बहुत प्रयास करने के बाद, मुझे लगता है कि मैं अंत में भिक्षु को समझता हूं। भारी मतदान के अपने स्वयं के लम्बे समालोचकों के पुनर्मिलन के बाद, मैं इस स्पष्टीकरण की पेशकश करूंगा।

तीन सवाल हैं जिनका जवाब साधुओं को समझने के लिए दिया जाना चाहिए:

  1. आपको एक सन्यासी की आवश्यकता क्यों है?
  2. सन्यासी क्या होता है?
  3. एक मोनाड को कैसे लागू किया जाता है?

जैसा कि मैंने अपनी मूल टिप्पणियों में उल्लेख किया है, बहुत सारे सनक स्पष्टीकरण प्रश्न संख्या 3 में पकड़े जाते हैं, बिना, और वास्तव में पर्याप्त रूप से प्रश्न 2, या प्रश्न 1 को कवर करने से पहले।

आपको एक सन्यासी की आवश्यकता क्यों है?

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

हालांकि, कुछ समस्याएं हैं जो प्रोग्रामिंग की इस शैली के साथ हल करने के लिए इतनी सीधी नहीं हैं। कंसोल प्रोग्रामिंग, और फ़ाइल i / o जैसी कुछ चीजें, एक विशेष क्रम में होने वाली चीजों की आवश्यकता होती हैं, या राज्य बनाए रखने की आवश्यकता होती हैं। इस समस्या से निपटने का एक तरीका यह है कि एक प्रकार की वस्तु बनाई जाए जो एक संगणना की स्थिति का प्रतिनिधित्व करती है, और कई प्रकार के कार्य जो राज्य वस्तु को इनपुट के रूप में लेते हैं, और एक नई संशोधित राज्य वस्तु वापस करते हैं।

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

consolestate MyConsole = new consolestate;

तो कंसोल प्रोग्रामिंग करने के लिए, लेकिन शुद्ध कार्यात्मक तरीके से, आपको प्रत्येक अभिभावक के अंदर बहुत सारे फ़ंक्शन कॉल करने की आवश्यकता होगी।

consolestate FinalConsole = print(input(print(myconsole, "Hello, what's your name?")),"hello, %inputbuffer%!");

इस तरह से प्रोग्रामिंग करने से "शुद्ध" कार्यात्मक शैली बनी रहती है, जबकि कंसोल में परिवर्तन एक विशेष क्रम में होने के लिए मजबूर करता है। लेकिन, हम शायद एक बार में केवल कुछ ऑपरेशनों से अधिक करना चाहते हैं, जैसे ऊपर दिए गए उदाहरण में। उस तरह से घोंसले के कार्य अनजाने में होने लगेंगे। हम जो चाहते हैं, वह कोड है जो अनिवार्य रूप से ऊपर के समान काम करता है, लेकिन इस तरह से थोड़ा अधिक लिखा जाता है:

consolestate FinalConsole = myconsole:
                            print("Hello, what's your name?"):
                            input():
                            print("hello, %inputbuffer%!");

यह वास्तव में इसे लिखने का एक अधिक सुविधाजनक तरीका होगा। हालांकि हम ऐसा कैसे करते हैं?

सन्यासी क्या होता है?

एक बार जब आपके पास एक प्रकार (जैसे कि consolestate) होता है, जिसे आप विशेष रूप से उस प्रकार पर काम करने के लिए डिज़ाइन किए गए कार्यों के एक समूह के साथ परिभाषित करते हैं, तो आप इन चीजों के पूरे पैकेज को "मोनड" में बदल सकते हैं, जैसे ऑपरेटर :(बाँध) को स्वचालित रूप से परिभाषित करके फ़ीड मानों को इसके बाईं ओर, फ़ंक्शन पैरामीटर में इसके दाईं ओर, और एक liftऑपरेटर जो सामान्य कार्यों को चालू करता है, उस विशिष्ट प्रकार के बाइंड ऑपरेटर के साथ काम करता है।

एक मोनाड को कैसे लागू किया जाता है?

अन्य उत्तर देखें, जो उस के विवरण में कूदने के लिए काफी स्वतंत्र लगते हैं।


साधु को परिभाषित करने का केवल एक ही कारण नहीं है। एक मोनाड कोई भी फ़नकार है जो बाँध कर वापस लौट जाता है। बाँध और वापसी आप अनुक्रमण देते हैं। लेकिन वे अन्य चीजें भी देते हैं। इसके अलावा, ध्यान दें कि आपकी पसंदीदा अनिवार्य भाषा प्रभावी रूप से ओओ वर्गों के साथ एक फैंसी आईओ मोनाद है। भिक्षुओं को परिभाषित करना आसान बनाने का मतलब है कि दुभाषिया पैटर्न का उपयोग करना आसान है - एक मठ के रूप में एक डीएसएल को परिभाषित करें और इसकी व्याख्या करें!
नौ


38

कुछ साल पहले इस सवाल का जवाब देने के बाद, मेरा मानना ​​है कि मैं उस प्रतिक्रिया को बेहतर बना सकता हूं और सरल बना सकता हूं ...

एक मोनाड एक फंक्शन कंपोजिशन तकनीक है, जो कंपोजिंग फंक्शन का उपयोग करके कुछ इनपुट परिदृश्यों के लिए ट्रीटमेंट को बाहरी बनाता है bind, कंपोजिशन के दौरान प्री-प्रोसेस इनपुट को।

सामान्य रचना में, फ़ंक्शन, compose (>>)अपने पूर्ववर्ती अनुक्रम में परिणाम के लिए रचित फ़ंक्शन को लागू करने के लिए उपयोग किया जाता है। महत्वपूर्ण रूप से, फंक्शन की रचना इसके इनपुट के सभी परिदृश्यों को संभालने के लिए आवश्यक है।

(x -> y) >> (y -> z)

इनपुट के पुनर्गठन से इस डिज़ाइन को बेहतर बनाया जा सकता है ताकि संबंधित राज्य अधिक आसानी से पूछताछ कर सकें। इसलिए, इसके बजाय केवल yमूल्य Mbऐसे बन सकते हैं , उदाहरण के लिए, (is_OK, b)यदि yवैधता की धारणा शामिल है।

उदाहरण के लिए, जब इनपुट केवल संभवतः एक संख्या होती है, तो एक स्ट्रिंग को वापस करने के बजाय जिसमें ड्यूटिटली रूप से एक संख्या हो सकती है या नहीं, आप टाइप कर सकते boolहैं एक वैध संख्या की उपस्थिति का संकेत और एक संख्या जैसे टुपल में bool * float। रचित कार्यों को अब यह निर्धारित करने के लिए इनपुट स्ट्रिंग को पार्स करने की आवश्यकता नहीं होगी कि क्या कोई संख्या मौजूद है, लेकिन केवल boolएक ट्यूपल के हिस्से का निरीक्षण कर सकता है ।

(Ma -> Mb) >> (Mb -> Mc)

यहां, फिर से, रचना स्वाभाविक रूप से होती है composeऔर इसलिए प्रत्येक फ़ंक्शन को अपने इनपुट के सभी परिदृश्यों को व्यक्तिगत रूप से संभालना चाहिए, हालांकि ऐसा करना अब बहुत आसान है।

हालाँकि, क्या होगा यदि हम उन समयों के लिए पूछताछ के प्रयास को समाप्त कर सकते हैं जहाँ एक परिदृश्य को संभालना दिनचर्या है। उदाहरण के लिए, यदि इनपुट के रूप में ठीक नहीं है तो हमारा प्रोग्राम कुछ भी नहीं करता is_OKहै false। यदि ऐसा किया गया, तो रचित कार्यों को स्वयं उस परिदृश्य को संभालने की आवश्यकता नहीं होगी, नाटकीय रूप से उनके कोड को सरल बनाने और पुन: उपयोग के दूसरे स्तर को प्रभावित करना होगा।

इस बाह्यकरण को प्राप्त करने के लिए हम एक फ़ंक्शन का उपयोग कर सकते हैं bind (>>=), compositionइसके बजाय प्रदर्शन करने के लिए compose। जैसे, एक फ़ंक्शन के आउटपुट से मूल्यों को केवल दूसरे के इनपुट में स्थानांतरित करने के बजाय, Bindके Mहिस्से का निरीक्षण करेंगे Maऔर यह तय करेंगे कि कंप्लीट किए गए फ़ंक्शन को कैसे और कैसे लागू किया जाए a। बेशक, फ़ंक्शन bindको विशेष Mरूप से हमारे विशेष रूप से परिभाषित किया जाएगा ताकि हम इसकी संरचना का निरीक्षण कर सकें और जो भी प्रकार का आवेदन करना चाहते हैं, कर सकें। बहरहाल, यह aतब से कुछ भी हो सकता है , जब यह आवश्यक अनुप्रयोग को निर्धारित करने के लिए bindकेवल aअछूता से रचित फ़ंक्शन में जाता है। इसके अतिरिक्त, स्वयं तैयार किए गए कार्यों को अब इससे निपटने की आवश्यकता नहीं हैMइनपुट संरचना का हिस्सा या तो, उन्हें सरल बनाना। इसलिये...

(a -> Mb) >>= (b -> Mc) या अधिक सफलतापूर्वक Mb >>= (b -> Mc)

संक्षेप में, एक मोनाड बाहरी हो जाता है और इस तरह कुछ इनपुट परिदृश्यों के उपचार के आसपास मानक व्यवहार प्रदान करता है, जब इनपुट उन्हें पर्याप्त रूप से उजागर करने के लिए डिज़ाइन किया जाता है। यह डिज़ाइन एक shell and contentमॉडल है जहाँ शेल में सम्‍मिलित फ़ंक्शन के अनुप्रयोग से संबंधित डेटा होता है और इसके द्वारा पूछताछ की जाती है और यह केवल bindफ़ंक्शन के लिए उपलब्ध रहता है।

इसलिए, एक सनक तीन चीजें हैं:

  1. Mमोनाड प्रासंगिक जानकारी रखने के लिए एक खोल,
  2. एक bindसमारोह सामग्री मूल्य के लिए बना कार्यों (रों) यह खोल के भीतर पाता है की अपने आवेदन में इस खोल जानकारी का उपयोग करने के लिए लागू है, और
  3. प्रपत्र के a -> Mbनिर्माण योग्य कार्य , ऐसे परिणाम तैयार करना जिनमें मोनैडिक प्रबंधन डेटा शामिल हैं।

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

इसके अतिरिक्त, monads में वे फ़ंक्शन शामिल हो सकते हैं , जो मान के aप्रकार में Ma, और सामान्य कार्यों में, मान a -> bकार्यों में, a -> Mbउनके परिणामों को अनुप्रयोग के बाद लपेटकर लपेटते हैं। बेशक, जैसे bind, इस तरह के रैप फ़ंक्शन विशिष्ट हैं M। एक उदाहरण:

let return a = [a]
let lift f a = return (f a)

bindफ़ंक्शन का डिज़ाइन अपरिवर्तनीय डेटा संरचनाओं को मानता है और शुद्ध कार्य अन्य चीजें जटिल हो जाती हैं और गारंटी नहीं दी जा सकती है। जैसे कि, वहाँ विवादास्पद कानून हैं:

दिया हुआ...

M_ 
return = (a -> Ma)
f = (a -> Mb)
g = (b -> Mc)

फिर...

Left Identity  : (return a) >>= f === f a
Right Identity : Ma >>= return    === Ma
Associative    : Ma >>= (f >>= g) === Ma >>= ((fun x -> f x) >>= g)

Associativityइसका मतलब यह है कि bindजब bindभी लागू किया जाता है , तब तक मूल्यांकन के क्रम को बनाए रखता है। यही है, Associativityऊपर की परिभाषा में , कोष्ठक bindingके प्रारंभिक मूल्यांकन के बल fऔर gकेवल एक फ़ंक्शन में परिणाम होगा जो Maपूरी होने की उम्मीद करता है bind। इसलिए मूल्यांकन का Maनिर्धारण उसके मूल्य पर लागू होने से पहले किया जाना चाहिए fऔर इसके परिणामस्वरूप लागू किया जाना चाहिए g


"... लेकिन मुझे आशा है कि दूसरों को यह उपयोगी लगता है" यह मेरे लिए वास्तव में उपयोगी था, सभी

यह मैंने कभी देखा / सुना / सुनाई जाने वाले भिक्षुओं का सबसे संक्षिप्त और स्पष्ट विवरण है। धन्यवाद!
जेम्स

मोनाड और मोनॉइड के बीच महत्वपूर्ण अंतर है। मोनाड विभिन्न प्रकारों के बीच "रचना" करने के लिए एक नियम है , इसलिए वे मोनिड्स के लिए आवश्यक के रूप में एक बाइनरी ऑपरेशन नहीं बनाते हैं, अधिक जानकारी के लिए यहां देखें: stackoverflow.com/questions/2704652/…
दिमित्री

हाँ। तुम सही हो। आपका लेख मेरे सिर पर था :)। हालाँकि, मैंने इस उपचार को बहुत उपयोगी पाया (और इसे दूसरों के लिए एक दिशा के रूप में अपने साथ जोड़ा)। अपने सिर को धन्यवाद: stackoverflow.com/a/7829607/1612190
जॉर्ज

2
आप श्रेणी सिद्धांत के साथ बीजगणितीय समूह सिद्धांत को भ्रमित कर सकते हैं जहां मोनाड आ रहा है। पूर्व बीजीय समूहों का सिद्धांत है, जो असंबंधित है।
दिमित्री ज़ैतसेव

37

एक मोनाड, प्रभावी रूप से, "टाइप ऑपरेटर" का एक रूप है। यह तीन काम करेगा। पहले यह "रैप" (या अन्यथा रूपांतरित करेगा) एक प्रकार के मूल्य को दूसरे प्रकार में (आमतौर पर "मोनडिक प्रकार" कहा जाता है)। दूसरी बात यह सभी ऑपरेशन (या फ़ंक्शंस) को मोनडिक प्रकार पर उपलब्ध अंतर्निहित प्रकार पर उपलब्ध कराएगी। अंत में यह एक समग्र मोनाड का उत्पादन करने के लिए अपने स्वयं को दूसरे मोनाड के साथ संयोजन के लिए समर्थन प्रदान करेगा।

विजुअल बेसिक / सी # में "शायद मोनड" मूल रूप से "अशक्त प्रकार" के बराबर है। यह एक गैर अशक्त प्रकार "T" लेता है और इसे "Nullable <T>" में परिवर्तित करता है, और फिर परिभाषित करता है कि सभी Nullable <T> पर बाइनरी ऑपरेटरों का क्या अर्थ है।

साइड इफेक्ट्स simillarly प्रतिनिधित्व कर रहे हैं। एक संरचना बनाई जाती है जो किसी फ़ंक्शन के रिटर्न मान के साथ साइड इफेक्ट्स का विवरण रखती है। "उठा हुआ" ऑपरेशन तब साइड इफेक्ट के आसपास कॉपी करता है क्योंकि मान फ़ंक्शन के बीच पारित हो जाते हैं।

उन्हें कई कारणों से "टाइप ऑपरेटर" के आसान नाम के बजाय "भिक्षु" कहा जाता है:

  1. मोनाड्स पर प्रतिबंध है कि वे क्या कर सकते हैं (विवरण के लिए निश्चित रूप देखें)।
  2. उन प्रतिबंधों के साथ, इस तथ्य के साथ कि तीन ऑपरेशन शामिल हैं, श्रेणी थ्योरी में एक सनद नामक चीज की संरचना के अनुरूप है, जो गणित की अस्पष्ट शाखा है।
  3. वे "शुद्ध" कार्यात्मक भाषाओं के समर्थकों द्वारा डिजाइन किए गए थे
  4. गणित की अस्पष्ट शाखाओं की तरह शुद्ध कार्यात्मक भाषाओं के समर्थकों
  5. क्योंकि गणित अस्पष्ट है, और मठ प्रोग्रामिंग की विशेष शैलियों के साथ जुड़े हुए हैं, लोग मोनड शब्द का उपयोग गुप्त हैंडशेक के रूप में करते हैं। इस वजह से किसी ने भी बेहतर नाम से निवेश करने की जहमत नहीं उठाई।

1
मोनाड्स को 'डिज़ाइन' नहीं किया गया था, उन्हें एक डोमेन (श्रेणी सिद्धांत) से दूसरे में (I / O विशुद्ध रूप से कार्यात्मक प्रोग्रामिंग भाषाओं में) लागू किया गया था। क्या न्यूटन ने 'कलन' डिजाइन किया था?
जारेड अपडाइक जूल

1
बिंदु 1 और 2 ऊपर सही और उपयोगी हैं। अंक 4 और 5 विज्ञापन गृहिणी की तरह हैं, भले ही कम या ज्यादा सच हो। वे वास्तव में भिक्षुओं को समझाने में मदद नहीं करते हैं।
जारेड अपडेटाइक जूल

13
पुन: 4, 5: "सीक्रेट हैंडशेक" चीज एक लाल हेरिंग है। प्रोग्रामिंग शब्दजाल से भरा है। हास्केल बस सामान को कॉल करने के लिए होता है जो कुछ को फिर से दिखाने का नाटक किए बिना होता है। यदि यह पहले से ही गणित में मौजूद है, तो इसके लिए एक नया नाम क्यों बनाया जाए? नाम वास्तव में कारण नहीं है कि लोगों को भिक्षु नहीं मिलते हैं; वे एक सूक्ष्म अवधारणा हैं। औसत व्यक्ति शायद इसके अलावा और गुणन को समझता है, उन्हें एबेलियन समूह की अवधारणा क्यों नहीं मिलती है? क्योंकि यह अधिक सारगर्भित और सामान्य है और उस व्यक्ति ने अवधारणा के चारों ओर अपना सिर लपेटने का काम नहीं किया है। नाम परिवर्तन से कोई मदद नहीं मिलेगी।
जारेड अपडाइक

16
आह ... मैं हास्केल पर हमला नहीं कर रहा हूं ... मैं मजाक बना रहा था। इसलिए, मुझे वास्तव में "विज्ञापन गृहिणी" होने के बारे में कुछ पता नहीं है। हां, पथरी "डिजाइन" की गई थी। इसीलिए, उदाहरण के लिए, कैलकुलस छात्रों को लिबनिज संकेतन पढ़ाया जाता है, न कि उपयोग किए गए इकी सामान नेट्वटन के बजाय। बेहतर डिजाइन। अच्छे नाम बहुत समझने में मदद करते हैं। अगर मैंने एबेलियन ग्रुप्स को "डिस्टल्ड रिंकल पॉड्स" कहा है, तो आपको मुझे समझने में परेशानी हो सकती है। आप कह सकते हैं "लेकिन यह नाम बकवास है", कोई भी उन्हें कभी भी फोन नहीं करेगा। उन लोगों के लिए जिन्होंने श्रेणी सिद्धांत "मोनाड" के बारे में कभी नहीं सुना है, बकवास लगता है।
स्कॉट विस्निव्स्की

4
@ टिप्पणी: क्षमा करें यदि मेरी व्यापक टिप्पणियों से ऐसा लगता है कि मैं हास्केल के बारे में रक्षात्मक हो रहा था। मैं गुप्त हाथ मिलाने के बारे में आपके हास्य का आनंद लेता हूं और आप ध्यान देंगे कि मैंने कहा कि यह कमोबेश सही है। :-) यदि आप एबेलियन ग्रुप्स को "डिस्टल्ड रिंकल पॉड्स" कहते हैं, तो आप मोनड्स को "बेहतर नाम" देने की कोशिश करने की एक ही गलती करेंगे (cf. F # "कम्प्यूटेशन एक्सप्रेशंस"): यह शब्द मौजूद है और जो लोग जानते हैं कि वे उस मॉर्ड्स को जानते हैं। हैं, लेकिन क्या नहीं "गर्म फजी बातें" (या "अभिकलन अभिव्यक्ति") हैं। यदि मैं "टाइप ऑपरेटर" शब्द के आपके उपयोग को सही ढंग से समझता हूं तो भिक्षुओं की तुलना में अन्य प्रकार के बहुत सारे ऑपरेटर हैं।
जारेड अपडेटाइक

35

(यह भी देखें कि एक सन्यासी क्या है? )

मोनाड्स के लिए एक अच्छी प्रेरणा सिगफ़े (डैन पिपोनी) की आप आविष्कारित मोनाड हो सकते हैं! (और शायद आप पहले से ही हैं)अन्य मोनाद ट्यूटोरियल के बहुत सारे हैं , जिनमें से कई गुमराह करने के लिए विभिन्न उपमाओं का उपयोग करते हुए "सरल शब्दों" में भिक्षुओं को समझाने की कोशिश की जाती है: यह मोनाद ट्यूटोरियल दोष है ; उनसे बचो।

जैसा कि DR MacIver हमें बताता है कि आपकी भाषा क्यों बेकार है :

इसलिए, हास्केल के बारे में मुझे जिन चीजों से नफरत है:

आइए स्पष्ट के साथ शुरू करते हैं। मोनाड ट्यूटोरियल। नहीं, सन्यासी नहीं। विशेष रूप से ट्यूटोरियल। वे अंतहीन हैं, अतिभारित हैं और प्रिय भगवान वे थकाऊ हैं। इसके अलावा, मैंने कभी कोई ठोस सबूत नहीं देखा कि वे वास्तव में मदद करें। कक्षा की परिभाषा पढ़ें, कुछ कोड लिखें, डरावने नाम पर जाएं।

आप कहते हैं कि आप शायद सन्यासी समझते हैं? अच्छा है, आप अपने रास्ते पर हैं। बस अन्य साधुओं का उपयोग करना शुरू करें और जल्द ही या बाद में आप समझ जाएंगे कि सामान्य रूप से कौन से भिक्षु हैं।

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

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


2
वाडलर के पेपर के साथ एकमात्र समस्या यह है कि नोटेशन अलग है, लेकिन मैं मानता हूं कि पेपर सुंदर सम्मोहक है और भिक्षुओं को लागू करने के लिए एक स्पष्ट संक्षिप्त प्रेरणा है।
जारेड अपडेटाइक जूल

"मोनड ट्यूटोरियल फॉलसी" के लिए +1। मोनडर्स पर ट्यूटोरियल पूर्णांक संख्याओं की अवधारणा को समझाने की कोशिश कर रहे कई ट्यूटोरियल होने के समान हैं। एक ट्यूटोरियल कहेगा, "1 एक सेब के समान है"; एक अन्य ट्यूटोरियल कहता है, "2 एक नाशपाती की तरह है"; एक तीसरा कहता है, "3 मूल रूप से एक नारंगी है"। लेकिन आपको कभी भी किसी भी एक ट्यूटोरियल से पूरी तस्वीर नहीं मिलती है। मैंने जो कुछ लिया है वह यह है कि भिक्षु एक अमूर्त अवधारणा है जिसका उपयोग कई अलग-अलग उद्देश्यों के लिए किया जा सकता है।
stakx -

@stakx: हाँ, सच। लेकिन मेरा मतलब यह नहीं था कि मठ एक अमूर्त है जिसे आप सीख नहीं सकते या नहीं सीखना चाहिए; केवल यह कि इसे सीखने के लिए सबसे अच्छा है कि आपने एक ही अंतर्निहित अमूर्तता का अनुभव करने के लिए पर्याप्त ठोस उदाहरण देखे हैं। मेरा दूसरा जवाब यहां देखें ।
श्रीवत्सआर

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

केवल टाइप कंस्ट्रक्टर का उल्लेख अधूरा है: stackoverflow.com/a/37345315/1614973
दिमित्री जैतसेव

23

मोनड्स प्रवाह को नियंत्रित करने के लिए हैं कि डेटा के सार तत्व क्या हैं।

दूसरे शब्दों में, कई डेवलपर्स सेट्स, लिस्ट्स, डॉक्स (या हैशिंग, या मैप्स) और पेड़ों के विचार से सहज हैं। उन डेटा प्रकारों के भीतर कई विशेष मामले हैं (उदाहरण के लिए InsertionOrderPreservesIdentityHashMap)।

हालाँकि, जब प्रोग्राम "प्रवाह" से सामना होता है, तो कई डेवलपर्स कई अन्य निर्माणों से उजागर नहीं होते हैं यदि, स्विच / केस, डू, जबकि, गोटो (जीआरआर), और (शायद) क्लोजर।

तो, एक मोनाड बस एक नियंत्रण प्रवाह निर्माण है। मोनाड को बदलने के लिए एक बेहतर वाक्यांश 'नियंत्रण प्रकार' होगा।

जैसे, एक मॉनड के पास नियंत्रण तर्क, या कथन या फ़ंक्शन के लिए स्लॉट हैं - डेटा संरचनाओं में समकक्ष यह कहना होगा कि कुछ डेटा संरचनाएं आपको डेटा जोड़ने, और इसे निकालने की अनुमति देती हैं।

उदाहरण के लिए, "अगर" भिक्षु:

if( clause ) then block

इसके सरलतम में दो स्लॉट हैं - एक खंड, और एक ब्लॉक। ifइकाई आमतौर पर खंड के परिणाम का मूल्यांकन करने के लिए बनाया गया है, और अगर गलत नहीं, ब्लॉक का मूल्यांकन। कई डेवलपर्स मोनड्स से परिचित नहीं होते हैं, जब वे 'अगर' सीखते हैं, और प्रभावी तर्क लिखने के लिए केवल मोनड्स को समझना आवश्यक नहीं है।

मोनाड्स अधिक जटिल हो सकते हैं, उसी तरह से कि डेटा संरचनाएं अधिक जटिल हो सकती हैं, लेकिन मोनाड की कई व्यापक श्रेणियां हैं जिनके समान शब्दार्थ हो सकते हैं, लेकिन कार्यान्वयन और वाक्यविन्यास अलग-अलग हो सकते हैं।

बेशक, उसी तरह से जिस पर डेटा संरचनाओं को पुनरावृत्त किया जा सकता है, या ट्रैवर्स किए गए, मोनडेस का मूल्यांकन किया जा सकता है।

कंपाइलर में उपयोगकर्ता-परिभाषित मोनड के लिए समर्थन हो सकता है या नहीं भी हो सकता है। हास्केल निश्चित रूप से करता है। Ioke में कुछ समान क्षमताएं हैं, हालांकि भाषा में मोनाड शब्द का उपयोग नहीं किया गया है।


14

मेरा पसंदीदा मोनाद ट्यूटोरियल:

http://www.haskell.org/haskellwiki/All_About_Monads

("मोनड ट्यूटोरियल" के लिए Google खोज पर 170,000 हिट्स में से!)

@Stu: मोनाड्स का बिंदु आपको अन्यथा शुद्ध कोड में (आमतौर पर) अनुक्रमिक शब्दार्थ जोड़ने की अनुमति देना है; आप यहां तक ​​कि मोनाड्स (मोनाड ट्रांसफॉर्मर्स का उपयोग करके) की रचना कर सकते हैं और उदाहरण के लिए त्रुटि से निपटने, साझा स्थिति और लॉगिंग के साथ पार्सिंग जैसे अधिक रोचक और जटिल संयुक्त शब्दार्थ प्राप्त कर सकते हैं। यह सब शुद्ध कोड में संभव है, मोनाड्स आपको इसे दूर करने और मॉड्यूलर पुस्तकालयों (हमेशा प्रोग्रामिंग में अच्छा) में इसका पुन: उपयोग करने की अनुमति देता है, साथ ही इसे अनिवार्य रूप से देखने के लिए सुविधाजनक सिंटैक्स प्रदान करता है।

हास्केल के पास पहले से ही ऑपरेटर ओवरलोडिंग है [1]: यह प्रकार की कक्षाओं का उपयोग करता है जिस तरह से जावा या सी # में इंटरफेस का उपयोग किया जा सकता है, लेकिन हास्केल बस ऐसा होता है कि गैर-अल्फ़ान्यूमेरिक टोकन जैसे + && और> को अनन्त पहचानकर्ता की अनुमति देता है। यदि आप "अर्धविराम को ओवरलोड कर रहे हैं तो इसका मतलब है कि इसे देखने के अपने तरीके से ओवरलोडिंग करना केवल ऑपरेटर है [2]। यह काले जादू की तरह लगता है और "सेमीकॉलन को अधिभारित करने के लिए परेशानी" के लिए पूछ रहा है (चित्र इस विचार का हवा हो रही पर्ल हैकर), लेकिन मुद्दा यह है कि बिना मोनाडेस के कोई अर्धविराम नहीं है, क्योंकि विशुद्ध रूप से कार्यात्मक कोड को स्पष्ट अनुक्रमण की आवश्यकता नहीं है या अनुमति नहीं है।

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

[१] यह भिक्षुओं का एक अलग मुद्दा है लेकिन भिक्षु हास्केल के ऑपरेटर ओवरलोडिंग फीचर का उपयोग करते हैं।

[२] यह भी एक निरीक्षण है क्योंकि मोनडिक क्रियाओं के लिए परिचालक >> = (उच्चारण "बाइंड") है, लेकिन इसमें सिन्सेटिक शुगर ("डू") है जो आपको ब्रेसिज़ और सेमीकोलन और / इंडेंटेशन और न्यूलाइन्स का उपयोग करने देता है।


9

मैं एक अलग तरीके से हाल ही में मोनाड्स के बारे में सोच रहा हूं। मैं उन्हें गणितीय तरीके से निष्पादन आदेश को अमूर्त करने के बारे में सोच रहा हूं , जो नए प्रकार के बहुरूपता को संभव बनाता है।

यदि आप एक अनिवार्य भाषा का उपयोग कर रहे हैं, और आप क्रम में कुछ अभिव्यक्ति लिखते हैं, तो कोड हमेशा उसी क्रम में चलता है।

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

और क्योंकि मोनाड्स बहुरूपिक हैं, इसलिए आपकी आवश्यकताओं के आधार पर, विभिन्न मोनाडों में समान कोड चलाना संभव है।

साथ ही, कुछ मामलों में, एक ही समय में कई विशेषताओं को प्राप्त करने के लिए (एक साथ ट्रांसफॉर्मर के साथ) मोनड को जोड़ना संभव है।


9

मैं अभी भी भिक्षुओं के लिए नया हूं, लेकिन मुझे लगा कि मैं एक लिंक साझा करूंगा, जिसमें मैंने पाया कि पढ़ने में बहुत अच्छा लगा (PICTURES के साथ !!): http://www.matusiak.eu/numerodix/blog/2012/3/11/ !! भिक्षुओं के लिए-आम आदमी / (कोई संबद्धता नहीं)

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

मुझे आशा है कि मुझे यह सही मिला, और इससे भी महत्वपूर्ण बात, आशा है कि लेख में भिक्षुओं पर एक मान्य दृष्टिकोण है। यदि और कुछ नहीं, तो इस लेख ने भिक्षुओं के बारे में अधिक जानने के लिए मेरी भूख को बढ़ाने में मदद की।


अजगर के उदाहरणों को समझना आसान हो गया! साझा करने के लिए धन्यवाद।
रयान एफेंडी

8

ऊपर दिए गए उत्कृष्ट उत्तरों के अलावा, मैं आपको निम्नलिखित लेख (पैट्रिक थॉमसन द्वारा) के लिए एक लिंक प्रदान करता हूं, जो जावास्क्रिप्ट लाइब्रेरी jQuery के लिए अवधारणा से संबंधित साधुओं को समझाता है (और डोम में हेरफेर करने के लिए "विधि का उपयोग करने का तरीका") : jQuery एक मोनाड है

JQuery प्रलेखन खुद "बिल्डर पैटर्न" जो शायद अधिक परिचित है के बारे में शब्द "इकाई" लेकिन वार्ता का उल्लेख नहीं करता। यह इस तथ्य को नहीं बदलता है कि आपके पास एक उचित मोनाड है शायद इसे साकार किए बिना भी।


यदि आप jQuery का उपयोग करते हैं, तो यह स्पष्टीकरण बहुत मददगार हो सकता है, खासकर यदि आपका हास्केल मजबूत नहीं है
by16lub

10
JQuery सशक्त रूप से एक सन्यासी नहीं है। जुड़ा हुआ लेख गलत है।
टोनी मोरिस

1
"जोरदार" होने के नाते बहुत आश्वस्त नहीं है। विषय पर कुछ उपयोगी चर्चा के लिए, देखें jQuery का एक मोनाद - स्टैक ओवरफ्लो
nealmcb

1
डगलस क्रैकफोर्ड के Google टॉक मोनाड्स और गोनाड्स और उनके जावास्क्रिप्ट कोड को मॉडैड्स करने के लिए भी देखें, AJAX लाइब्रेरीज़ एंड प्रोमिस के समान व्यवहार पर विस्तार: डगलसर्कॉकफ़ोर्ड / मोनाड ·
गीथब


7

एक मोनाड एक साथ संगणना के संयोजन का एक तरीका है जो एक सामान्य संदर्भ साझा करता है। यह पाइप के नेटवर्क के निर्माण जैसा है। नेटवर्क का निर्माण करते समय, इसके माध्यम से बहने वाला कोई डेटा नहीं है। लेकिन जब मैंने I बाइंड ’और then रिटर्न’ के साथ सभी बिट्स को एक साथ जोड़कर समाप्त कर दिया है, तो मैं कुछ ऐसा करता हूं runMyMonad monad dataऔर डेटा पाइप से बहता है।


1
यह मोनाड की तुलना में अधिक लागू है। मोनाड्स के साथ, आपको कनेक्ट करने के लिए अगला पाइप चुनने से पहले पाइप से डेटा प्राप्त करना होगा।
पीकर जूल

हां, आप आवेदक का वर्णन करते हैं, मोनाड का नहीं। मोनाद, मौके पर अगले पाइप खंड का निर्माण कर रहा है, जो उस बिंदु तक पहुंचने वाले डेटा के आधार पर पाइप के अंदर है।
Ness

6

व्यवहार में, मोनाड फंक्शन कंपोजिशन ऑपरेटर का एक कस्टम कार्यान्वयन है जो साइड इफेक्ट्स और असंगत इनपुट और रिटर्न वैल्यूज़ (चैनिंग के लिए) का ध्यान रखता है।


5

अगर मैंने सही तरीके से समझा है, तो IEnumerable मोनड्स से लिया गया है। मुझे आश्चर्य है कि अगर हम सी # दुनिया से उन लोगों के लिए दृष्टिकोण का एक दिलचस्प कोण हो सकता है?

इसके लायक क्या है, यहां ट्यूटोरियल के कुछ लिंक दिए गए हैं, जिन्होंने मेरी मदद की (और नहीं, मुझे अभी भी समझ नहीं आया है कि भिक्षु क्या हैं)।


5

वहाँ सीखने के दौरान जिन दो चीज़ों ने मेरी सबसे अच्छी मदद की:

अध्याय 8, "कार्यात्मक पार्सर्स," ग्राहम हटन की पुस्तक हास्केल में प्रोग्रामिंग से । यह वास्तव में मोनड्स का उल्लेख नहीं करता है, लेकिन यदि आप अध्याय के माध्यम से काम कर सकते हैं और वास्तव में इसमें सब कुछ समझ सकते हैं, विशेष रूप से कैसे बाँध संचालन के एक अनुक्रम का मूल्यांकन किया जाता है, तो आप भिक्षुओं के आंतरिक को समझेंगे। यह कई कोशिशें करने की अपेक्षा करें।

ट्यूटोरियल सभी मोनाड्स के बारे में । यह उनके उपयोग के कई अच्छे उदाहरण देता है, और मुझे यह कहना है कि एपेंडेक्स में सादृश्य मैंने मेरे लिए काम किया।


5

मोनॉइड कुछ ऐसा प्रतीत होता है जो यह सुनिश्चित करता है कि एक मोनॉइड और एक समर्थित प्रकार पर परिभाषित सभी ऑपरेशन हमेशा मोनॉइड के अंदर एक समर्थित प्रकार लौटाएंगे। जैसे, कोई संख्या + कोई भी संख्या = कोई संख्या, कोई त्रुटि नहीं।

जबकि विभाजन दो अंशों को स्वीकार करता है, और एक भिन्नात्मक रिटर्न देता है, जो कि हेकेल में इनफिनिटी के रूप में शून्य द्वारा परिभाषित विभाजन होता है, जो कि (जो आंशिक रूप से भिन्न होता है) ...

किसी भी स्थिति में, यह प्रतीत होता है कि मोनाड्स यह सुनिश्चित करने का एक तरीका है कि आपके संचालन की श्रृंखला एक पूर्वानुमेय तरीके से व्यवहार करती है, और एक फ़ंक्शन जो कि Num -> Num होने का दावा करता है, जो Num-> Num के किसी अन्य फ़ंक्शन के साथ बना है, जिसे x के साथ बुलाया गया है। कहते हैं, मिसाइलों आग।

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

हास्केल में, मुख्य प्रकार IO (), या IO [()] का है, आसक्ति अजीब है और मैं इस पर चर्चा नहीं करूंगा लेकिन यहां मैं जो सोचता हूं वह होता है:

यदि मेरे पास मुख्य है, तो मैं चाहता हूं कि यह कार्रवाई की एक श्रृंखला करे, जिस कारण से मैं कार्यक्रम चलाता हूं वह एक प्रभाव पैदा करता है - आमतौर पर हालांकि आईओ। इस प्रकार मैं मुख्य रूप से एक साथ IO परिचालनों की श्रृंखला बना सकता हूं - IO करें, और कुछ नहीं।

अगर मैं कुछ ऐसा करने की कोशिश करता हूं जो "आईओ वापस नहीं करता है", तो कार्यक्रम शिकायत करेगा कि श्रृंखला प्रवाह नहीं करती है, या मूल रूप से "यह कैसे संबंधित है जो हम करने की कोशिश कर रहे हैं - एक आईओ कार्रवाई", यह बल के लिए प्रकट होता है प्रोग्रामर ने बिना सोचे-समझे, मिसाइलों को फायर करने के बारे में, बिना छंटाई के एल्गोरिदम बनाते हुए, अपनी ट्रेन को रखने के लिए - जो प्रवाह नहीं करता है।

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

ऐसा प्रतीत होता है कि भिक्षु शुद्धता के बारे में नहीं हैं, न ही नियंत्रण के बारे में, बल्कि एक ऐसी श्रेणी की पहचान बनाए रखने के बारे में, जिस पर सभी व्यवहार अनुमानित और परिभाषित हैं, या संकलन नहीं करते हैं। जब आप कुछ करने की उम्मीद कर रहे हैं, तो आप कुछ नहीं कर सकते हैं, और यदि आप कुछ भी नहीं करने की उम्मीद कर रहे हैं तो आप कुछ नहीं कर सकते (दृश्यमान)।

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

"वास्तविक दुनिया" में सभी चीजें भिक्षुओं के रूप में दिखाई देती हैं, इस अर्थ में कि यह भ्रम को रोकने वाले निश्चित अवलोकन कानूनों द्वारा बाध्य है। इसका मतलब यह नहीं है कि हमें कक्षाओं को बनाने के लिए इस ऑब्जेक्ट के सभी कार्यों की नकल करना है, इसके बजाय हम बस "एक वर्ग एक वर्ग" कह सकते हैं, कुछ भी नहीं लेकिन एक वर्ग, यहां तक ​​कि एक आयत भी नहीं और न ही एक सर्कल, और "एक वर्ग का क्षेत्र है" इसकी मौजूदा आयामों में से एक की लंबाई अपने आप से कई गुना अधिक है। चाहे कोई भी वर्ग हो, अगर यह 2 डी अंतरिक्ष में एक वर्ग है, तो यह क्षेत्र बिल्कुल कुछ भी नहीं हो सकता है, लेकिन इसकी लंबाई चुकता है, यह साबित करने के लिए लगभग तुच्छ है। यह बहुत शक्तिशाली है क्योंकि हमें यह सुनिश्चित करने के लिए दावे करने की आवश्यकता नहीं है कि हमारी दुनिया जिस तरह से है, हम अपने कार्यक्रमों को रोकने के लिए वास्तविकता के निहितार्थ का उपयोग करते हैं।

Im बहुत ज्यादा गलत होने की गारंटी है, लेकिन मुझे लगता है कि इससे किसी को मदद मिल सकती है, इसलिए उम्मीद है कि यह किसी की मदद करेगा।


5

स्काला के संदर्भ में आपको सबसे सरल परिभाषा मिलेगी। मूल रूप से फ्लैटपाइप (या बाइंड) 'साहचर्य' है और एक पहचान मौजूद है।

trait M[+A] {
  def flatMap[B](f: A => M[B]): M[B] // AKA bind

  // Pseudo Meta Code
  def isValidMonad: Boolean = {
    // for every parameter the following holds
    def isAssociativeOn[X, Y, Z](x: M[X], f: X => M[Y], g: Y => M[Z]): Boolean =
      x.flatMap(f).flatMap(g) == x.flatMap(f(_).flatMap(g))

    // for every parameter X and x, there exists an id
    // such that the following holds
    def isAnIdentity[X](x: M[X], id: X => M[X]): Boolean =
      x.flatMap(id) == x
  }
}

उदाहरण के लिए

// These could be any functions
val f: Int => Option[String] = number => if (number == 7) Some("hello") else None
val g: String => Option[Double] = string => Some(3.14)

// Observe these are identical. Since Option is a Monad 
// they will always be identical no matter what the functions are
scala> Some(7).flatMap(f).flatMap(g)
res211: Option[Double] = Some(3.14)

scala> Some(7).flatMap(f(_).flatMap(g))
res212: Option[Double] = Some(3.14)


// As Option is a Monad, there exists an identity:
val id: Int => Option[Int] = x => Some(x)

// Observe these are identical
scala> Some(7).flatMap(id)
res213: Option[Int] = Some(7)

scala> Some(7)
res214: Some[Int] = Some(7)

नोट कड़ाई से एक की परिभाषा बोल कार्यात्मक प्रोग्रामिंग में इकाई एक की परिभाषा के समान नहीं है श्रेणी थ्योरी में इकाई , जिनमें से बदल जाता है में परिभाषित किया गया है mapऔर flatten। हालांकि वे कुछ मैपिंग के तहत समान हैं। यह प्रस्तुतियाँ बहुत अच्छी हैं: http://www.slideshare.net/samthemonad/monad-pretation-scala-as-a-category


5

यह उत्तर एक प्रेरक उदाहरण के साथ शुरू होता है, उदाहरण के माध्यम से काम करता है, एक साधु का उदाहरण प्राप्त करता है, और औपचारिक रूप से "मठ" को परिभाषित करता है।

Pseudocode में इन तीन कार्यों पर विचार करें:

f(<x, messages>) := <x, messages "called f. ">
g(<x, messages>) := <x, messages "called g. ">
wrap(x)          := <x, "">

fफॉर्म की एक ऑर्डर की गई जोड़ी लेता है <x, messages>और एक ऑर्डर की गई जोड़ी लौटाता है। यह पहले आइटम को अछूता छोड़ देता है और "called f. "दूसरे आइटम को जोड़ता है। उसी के साथ g

आप इन कार्यों की रचना कर सकते हैं और अपना मूल मूल्य प्राप्त कर सकते हैं, साथ ही एक स्ट्रिंग जो यह दिखाती है कि कार्यों को किस क्रम में बुलाया गया है:

  f(g(wrap(x)))
= f(g(<x, "">))
= f(<x, "called g. ">)
= <x, "called g. called f. ">

आप इस तथ्य को नापसंद करते हैं fऔर gपिछले लॉगिंग जानकारी के लिए अपने स्वयं के लॉग संदेशों को जोड़ने के लिए जिम्मेदार हैं। (केवल तर्क के लिए कल्पना करें कि तार जोड़ने के बजाय, fऔरg जोड़ी के दूसरे आइटम पर जटिल तर्क करना चाहिए। यह जटिल तर्क को दो - या अधिक - विभिन्न कार्यों में दोहराने के लिए एक दर्द होगा।)

आप सरल कार्य लिखना पसंद करते हैं:

f(x)    := <x, "called f. ">
g(x)    := <x, "called g. ">
wrap(x) := <x, "">

लेकिन जब आप उन्हें लिखें तो क्या होगा:

  f(g(wrap(x)))
= f(g(<x, "">))
= f(<<x, "">, "called g. ">)
= <<<x, "">, "called g. ">, "called f. ">

समस्या यह है कि एक जोड़ी को एक समारोह में पारित करना आपको वह नहीं देता है जो आप चाहते हैं। लेकिन क्या होगा अगर आप किसी फंक्शन में एक जोड़ी खिला सकते हैं :

  feed(f, feed(g, wrap(x)))
= feed(f, feed(g, <x, "">))
= feed(f, <x, "called g. ">)
= <x, "called g. called f. ">

feed(f, m)"फ़ीड mइन f" के रूप में पढ़ें । करने के लिए फ़ीड एक जोड़ी <x, messages>एक समारोह में fकरने के लिए है पारित x में f, मिल <y, message>के बाहर f, और वापसी <y, messages message>

feed(f, <x, messages>) := let <y, message> = f(x)
                          in  <y, messages message>

ध्यान दें कि जब आप अपने कार्यों के साथ तीन चीजें करते हैं तो क्या होता है:

पहला: यदि आप एक मूल्य लपेटते हैं और फिर परिणामस्वरूप जोड़ी को एक फ़ंक्शन में खिलाते हैं :

  feed(f, wrap(x))
= feed(f, <x, "">)
= let <y, message> = f(x)
  in  <y, "" message>
= let <y, message> = <x, "called f. ">
  in  <y, "" message>
= <x, "" "called f. ">
= <x, "called f. ">
= f(x)

यह फ़ंक्शन में मान को पारित करने के समान है।

दूसरा: यदि आप एक जोड़ी में खिलाते हैं wrap:

  feed(wrap, <x, messages>)
= let <y, message> = wrap(x)
  in  <y, messages message>
= let <y, message> = <x, "">
  in  <y, messages message>
= <x, messages "">
= <x, messages>

इससे जोड़ी नहीं बदलती।

तीसरा: यदि आप एक ऐसे फंक्शन को परिभाषित करते हैं जो लेता है xऔर उसमें फीड करता g(x)है f:

h(x) := feed(f, g(x))

और इसमें एक जोड़ी खिलाएं:

  feed(h, <x, messages>)
= let <y, message> = h(x)
  in  <y, messages message>
= let <y, message> = feed(f, g(x))
  in  <y, messages message>
= let <y, message> = feed(f, <x, "called g. ">)
  in  <y, messages message>
= let <y, message> = let <z, msg> = f(x)
                     in  <z, "called g. " msg>
  in <y, messages message>
= let <y, message> = let <z, msg> = <x, "called f. ">
                     in  <z, "called g. " msg>
  in <y, messages message>
= let <y, message> = <x, "called g. " "called f. ">
  in <y, messages message>
= <x, messages "called g. " "called f. ">
= feed(f, <x, messages "called g. ">)
= feed(f, feed(g, <x, messages>))

यह जोड़ी में gखिलाने और परिणामस्वरूप जोड़ी को खिलाने के समान है f

आपके पास अधिकांश एक सन्यासी है। अब आपको बस अपने प्रोग्राम के डेटा प्रकारों के बारे में जानना होगा।

किस प्रकार का मूल्य है <x, "called f. ">? खैर, यह इस बात पर निर्भर करता है कि मूल्य किस प्रकार का xहै। यदि xप्रकार है t, तो आपकी जोड़ी " tऔर स्ट्रिंग की जोड़ी" प्रकार का एक मूल्य है । उस प्रकार को बुलाओ M t

Mएक प्रकार का कंस्ट्रक्टर है: Mअकेला एक प्रकार को संदर्भित नहीं करता है, लेकिन M _एक प्रकार को संदर्भित करता है जब आप एक प्रकार के साथ रिक्त को भरते हैं। एक M intएक int और एक स्ट्रिंग की एक जोड़ी है। एक M stringएक स्ट्रिंग और एक स्ट्रिंग की एक जोड़ी है। आदि।

बधाई हो, आपने एक सन्यासी बनाया है!

औपचारिक रूप से, आपका मोद तुगलक है <M, feed, wrap>

एक मोदक एक टुपल है <M, feed, wrap>जहां:

  • M एक प्रकार का निर्माता है।
  • feedएक (समारोह है कि एक लेता है लेता है tऔर एक रिटर्न M u) और एक M tऔर रिटर्न एक M u
  • wrapएक लेता है vऔर एक रिटर्न देता है M v

t, uऔर vकोई भी तीन प्रकार हैं जो समान हो सकते हैं या नहीं भी हो सकते हैं। एक संन्यासी आपके विशिष्ट मठ के लिए आपके द्वारा सिद्ध किए गए तीन गुणों को संतुष्ट करता है:

  • दूध पिलाने की एक लिपटे tएक समारोह में रूप में ही है गुजर unwrapped tसमारोह में।

    औपचारिक रूप से: feed(f, wrap(x)) = f(x)

  • एक दूध पिलाने M tमें wrapकरने के लिए कुछ नहीं करता है M t

    औपचारिक रूप से: feed(wrap, m) = m

  • एक फ़ंक्शन में एक M t(यह कहते हैं m) खिला कि

    • गुजरता tमेंg
    • से M u(कॉल n) मिलता हैg
    • में खिलाती nहैf

    के समान है

    • खिला mमेंg
    • से हो रहा nहैg
    • खिला nमेंf

    औपचारिक रूप से: feed(h, m) = feed(f, feed(g, m))कहांh(x) := feed(f, g(x))

आमतौर पर, feedकहा जाता है bind( >>=हास्केल में AKA ) और wrapकहा जाता है return


5

मैं Monadहास्केल के संदर्भ में समझाने की कोशिश करूंगा ।

कार्यात्मक प्रोग्रामिंग में, फ़ंक्शन रचना महत्वपूर्ण है। यह हमारे कार्यक्रम को छोटे, आसानी से पढ़े जाने वाले कार्यों से मिलकर बना देता है।

मान लीजिए कि हमारे दो कार्य हैं: g :: Int -> Stringऔर f :: String -> Bool

हम कर सकते हैं (f . g) x, जो बस के रूप में ही है f (g x), जहां xएक Intमूल्य है।

रचना करते समय / एक फंक्शन का परिणाम दूसरे पर लागू करने के लिए, टाइप मैच होने महत्वपूर्ण है। उपरोक्त मामले में, परिणाम जिस प्रकार से लौटाया gजाना चाहिए वह उसी प्रकार होना चाहिए जिस प्रकार से स्वीकार किया जाता हैf

लेकिन कभी-कभी मूल्य संदर्भों में होते हैं, और यह प्रकारों को लाइन करने के लिए थोड़ा कम आसान बनाता है। (संदर्भों में मान होना बहुत उपयोगी है। उदाहरण के लिए, Maybe Intप्रकार एक Intमान का प्रतिनिधित्व करता है जो वहां नहीं हो सकता है, यह IO Stringप्रकार एक Stringमान का प्रतिनिधित्व करता है जो कुछ दुष्प्रभावों के प्रदर्शन के परिणामस्वरूप होता है।)

मान लीजिए कि अब हम करते हैं g1 :: Int -> Maybe Stringऔर f1 :: String -> Maybe Boolg1और f1बहुत समान हैं gऔरf क्रमशः।

हम (f1 . g1) xया नहीं कर सकते f1 (g1 x), जहां xएक Intमूल्य है। परिणाम जिस प्रकार से लौटा है g1वह f1उम्मीद नहीं है।

हम रचना कर सकते हैं fऔर ऑपरेटर के gसाथ ., लेकिन अब हम f1और g1साथ नहीं बना सकते .। समस्या यह है कि हम किसी फ़ंक्शन के संदर्भ में एक मान को सीधे मान नहीं सकते हैं जो किसी संदर्भ में एक मूल्य की अपेक्षा करता है।

क्या यह अच्छा नहीं होगा यदि हम एक ऑपरेटर को रचना के लिए पेश करें g1और f1, जैसे कि हम लिख सकते हैं (f1 OPERATOR g1) x? g1एक संदर्भ में एक मूल्य देता है। मान को संदर्भ से बाहर ले जाया जाएगा और लागू किया जाएगा f1। और हां, हमारे पास एक ऐसा ऑपरेटर है। यह है <=<

हमारे पास भी है >>= ऑपरेटर हमारे लिए सटीक समान काम करता है, हालांकि थोड़ा अलग वाक्यविन्यास में।

हम लिखते हैं g1 x >>= f1:। g1 xएक Maybe Intमूल्य है। >>=ऑपरेटर कि लेने में मदद करता है Int"शायद-नहीं-वहाँ" संदर्भ से बाहर मूल्य, और उसे लागू करने के f1। का परिणाम f1, जो एक है Maybe Bool, पूरे >>=ऑपरेशन का परिणाम होगा ।

और आखिरकार, क्यों Monadउपयोगी है? क्योंकि Monadएक प्रकार का वर्ग है जो >>=ऑपरेटर को परिभाषित करता है , बहुत ही उस Eqप्रकार का वर्ग है जो परिभाषित करता है ==और/= ऑपरेटर ऑपरेटरों ।

निष्कर्ष निकालने के लिए, Monadप्रकार वर्ग को परिभाषित करता है>>= ऑपरेटर है जो हमें एक संदर्भ में मानों को पारित करने की अनुमति देता है (हम इन मौद्रिक मूल्यों को उन कार्यों के लिए कहते हैं) जो संदर्भ में मूल्यों की अपेक्षा नहीं करते हैं। संदर्भ का ध्यान रखा जाएगा।

अगर यहां एक बात याद रखने की है, तो वह यह है कि Monadफ़ंक्शन संरचना को अनुमति दें जिसमें संदर्भों में मान शामिल हैं



IOW, मोनाद सामान्यीकृत फ़ंक्शन कॉल प्रोटोकॉल है।
विल नेस

आप का जवाब मेरी राय में सबसे ज्यादा मददगार है। हालांकि मुझे यह कहना है कि मुझे लगता है कि इस तथ्य पर जोर देने की आवश्यकता है कि जिन कार्यों को आप संदर्भित कर रहे हैं वे केवल संदर्भों में मूल्यों को शामिल नहीं करते हैं, वे सक्रिय रूप से संदर्भों में मूल्यों को डालते हैं। इसलिए उदाहरण के लिए, एक फ़ंक्शन, f :: ma -> mb बहुत आसानी से किसी अन्य फ़ंक्शन, g :: mb -> m c के साथ रचना करेगा। लेकिन मोनड्स (विशेष रूप से बाँध) हमें उन कार्यों को स्थायी रूप से बनाने की अनुमति देता है जो उनके इनपुट को उसी संदर्भ में रखते हैं, बिना हमें उस संदर्भ से पहले मूल्य निकालने की आवश्यकता होती है (जो प्रभावी रूप से मूल्य से जानकारी हटा देगा)
जेम्स

@ मुझे लगता है कि फंक्शंस के लिए जोर होना चाहिए?
जोनास

@ जोनास मुझे लगता है कि मैंने स्पष्ट रूप से नहीं बताया। जब मैं कहता हूं कि फ़ंक्शन संदर्भों में मान रखते हैं, तो मेरा मतलब है कि उनके पास टाइप (a -> mb) है। एक संदर्भ में एक मूल्य डालने के बाद से ये बहुत उपयोगी हैं, लेकिन इसमें नई जानकारी शामिल है, लेकिन आम तौर पर एक ((-> mb) और a (b -> mc) को एक साथ चेन करना मुश्किल होगा क्योंकि हम केवल मूल्य नहीं निकाल सकते हैं प्रसंग का। इसलिए हमें विशिष्ट संदर्भ के आधार पर इन कार्यों को एक साथ समझदार तरीके से करने के लिए कुछ जटिल प्रक्रिया का उपयोग करना होगा और केवल संदर्भों की परवाह किए बिना हमें एक सुसंगत तरीके से ऐसा करने की अनुमति देते हैं।
जेम्स

5

tl; डॉ

{-# LANGUAGE InstanceSigs #-}

newtype Id t = Id t

instance Monad Id where
   return :: t -> Id t
   return = Id

   (=<<) :: (a -> Id b) -> Id a -> Id b
   f =<< (Id x) = f x

प्रस्ताव

$कार्यों के अनुप्रयोग ऑपरेटर

forall a b. a -> b

विहित रूप से परिभाषित किया गया है

($) :: (a -> b) -> a -> b
f $ x = f x

infixr 0 $

हास्केल-आदिम फ़ंक्शन एप्लिकेशन f x( infixl 10) के संदर्भ में ।

संरचना .के संदर्भ में परिभाषित किया गया है $के रूप में

(.) :: (b -> c) -> (a -> b) -> (a -> c)
f . g = \ x -> f $ g x

infixr 9 .

और समकक्षों को संतुष्ट करता है forall f g h.

     f . id  =  f            :: c -> d   Right identity
     id . g  =  g            :: b -> c   Left identity
(f . g) . h  =  f . (g . h)  :: a -> d   Associativity

.साहचर्य है, और idइसकी दाईं और बाईं पहचान है।

क्लेली ट्रिपल

प्रोग्रामिंग में, एक मोनाड एक फनकार टाइप कंस्ट्रक्टर होता है जिसमें मोनैड टाइप क्लास होता है। परिभाषा और कार्यान्वयन के कई समतुल्य रूप हैं, प्रत्येक में मोनड अमूर्तता के बारे में थोड़ा अलग अंतर्ज्ञान है।

एक functor एक प्रकार निर्माता है fएक तरह से * -> *functor प्रकार वर्ग का एक उदाहरण के साथ।

{-# LANGUAGE KindSignatures #-}

class Functor (f :: * -> *) where
   map :: (a -> b) -> (f a -> f b)

वैधानिक रूप से लागू प्रकार प्रोटोकॉल का पालन करने के अलावा, फफूंद प्रकार वर्ग के उदाहरणों को बीजीय फफूंद कानूनों का पालन ​​करना चाहिए forall f g.

       map id  =  id           :: f t -> f t   Identity
map f . map g  =  map (f . g)  :: f a -> f c   Composition / short cut fusion

फन्नेटर कंप्यूटर्स के प्रकार होते हैं

forall f t. Functor f => f t

एक संगणना c rमें संदर्भ के भीतर परिणाम शामिल होते हैं ।r c

असमान मोनोडिक फ़ंक्शंस या क्लेज़ली तीरों का प्रकार होता है

forall m a b. Functor m => a -> m b

क्लेसी तीर ऐसे कार्य हैं जो एक तर्क लेते हैं aऔर एक मोनडिक अभिकलन वापस करते हैंm b

क्लेडिस ट्रिपल के संदर्भ में मोनोड को कैनोनिक रूप से परिभाषित किया गया है forall m. Functor m =>

(m, return, (=<<))

प्रकार वर्ग के रूप में लागू किया गया

class Functor m => Monad m where
   return :: t -> m t
   (=<<)  :: (a -> m b) -> m a -> m b

infixr 1 =<<

Kleisli पहचान return एक Kleisli तीर एक मूल्य को बढ़ावा देता है tmonadic संदर्भ में mएक्सटेंशन या क्लेसीली आवेदन एक संगणना के परिणामों के लिए =<<क्लेस्ली तीर लागू a -> m bकरता हैm a

क्लेसली रचना <=< को विस्तार के संदर्भ में परिभाषित किया गया है

(<=<) :: Monad m => (b -> m c) -> (a -> m b) -> (a -> m c)
f <=< g = \ x -> f =<< g x

infixr 1 <=<

<=< दो क्लीसली तीरों की रचना करता है, दाएं तीर के अनुप्रयोग के परिणामों के लिए बाएं तीर को लागू करता है।

मोनाद प्रकार के वर्ग के उदाहरणों को मोनाद कानूनों का पालन ​​करना चाहिए , जो कि ज्यादातर क्लेसीली रचना के संदर्भ में कहा गया है:forall f g h.

   f <=< return  =  f                :: c -> m d   Right identity
   return <=< g  =  g                :: b -> m c   Left identity
(f <=< g) <=< h  =  f <=< (g <=< h)  :: a -> m d   Associativity

<=<साहचर्य है, और returnइसकी दाईं और बाईं पहचान है।

पहचान

पहचान का प्रकार

type Id t = t

प्रकारों पर पहचान कार्य है

Id :: * -> *

एक फ़नकार के रूप में व्याख्या की गई,

   return :: t -> Id t
=      id :: t ->    t

    (=<<) :: (a -> Id b) -> Id a -> Id b
=     ($) :: (a ->    b) ->    a ->    b

    (<=<) :: (b -> Id c) -> (a -> Id b) -> (a -> Id c)
=     (.) :: (b ->    c) -> (a ->    b) -> (a ->    c)

विहित हास्केल में, पहचान मोनड को परिभाषित किया गया है

newtype Id t = Id t

instance Functor Id where
   map :: (a -> b) -> Id a -> Id b
   map f (Id x) = Id (f x)

instance Monad Id where
   return :: t -> Id t
   return = Id

   (=<<) :: (a -> Id b) -> Id a -> Id b
   f =<< (Id x) = f x

विकल्प

एक विकल्प प्रकार

data Maybe t = Nothing | Just t

सांकेतिक शब्दों में बदलना गणना है Maybe tकि जरूरी नहीं कि एक परिणाम देता है t, अभिकलन "विफल" हो सकता है। विकल्प मोनड को परिभाषित किया गया है

instance Functor Maybe where
   map :: (a -> b) -> (Maybe a -> Maybe b)
   map f (Just x) = Just (f x)
   map _ Nothing  = Nothing

instance Monad Maybe where
   return :: t -> Maybe t
   return = Just

   (=<<) :: (a -> Maybe b) -> Maybe a -> Maybe b
   f =<< (Just x) = f x
   _ =<< Nothing  = Nothing

a -> Maybe bएक परिणाम के लिए लागू होता है केवल अगर Maybe aएक परिणाम देता है।

newtype Nat = Nat Int

प्राकृतिक संख्याओं को उन पूर्णांकों के रूप में एन्कोड किया जा सकता है जो शून्य से अधिक या उसके बराबर हैं।

toNat :: Int -> Maybe Nat
toNat i | i >= 0    = Just (Nat i)
        | otherwise = Nothing

प्राकृतिक संख्या घटाव के तहत बंद नहीं होती हैं।

(-?) :: Nat -> Nat -> Maybe Nat
(Nat n) -? (Nat m) = toNat (n - m)

infixl 6 -?

विकल्प मोनाड अपवाद हैंडलिंग का एक मूल रूप शामिल करता है।

(-? 20) <=< toNat :: Int -> Maybe Nat

सूची

सूची प्रकार पर, सूची मोनाद

data [] t = [] | t : [t]

infixr 5 :

और इसके additive मोनॉयड ऑपरेशन "परिशिष्ट"

(++) :: [t] -> [t] -> [t]
(x : xs) ++ ys = x : xs ++ ys
[]       ++ ys = ys

infixr 5 ++

परिणामों की एक प्राकृतिक राशि उपज nonlinear संगणना सांकेतिक शब्दों में बदलना ।[t]0, 1, ...t

instance Functor [] where
   map :: (a -> b) -> ([a] -> [b])
   map f (x : xs) = f x : map f xs
   map _ []       = []

instance Monad [] where
   return :: t -> [t]
   return = (: [])

   (=<<) :: (a -> [b]) -> [a] -> [b]
   f =<< (x : xs) = f x ++ (f =<< xs)
   _ =<< []       = []

एक्सटेंशन =<<concatenates ++सभी सूचियों [b]अनुप्रयोगों से उत्पन्न f xएक Kleisli के तीर a -> [b]के तत्वों को [a]एक ही परिणाम सूची में[b]

एक सकारात्मक पूर्णांक के उचित विभाजक nहोने दें

divisors :: Integral t => t -> [t]
divisors n = filter (`divides` n) [2 .. n - 1]

divides :: Integral t => t -> t -> Bool
(`divides` n) = (== 0) . (n `rem`)

फिर

forall n.  let { f = f <=< divisors } in f n   =   []

मानद प्रकार वर्ग को परिभाषित करने में, विस्तार के बजाय =<<, हास्केल मानक अपने फ्लिप, बाइंड ऑपरेटर का उपयोग करता है >>=

class Applicative m => Monad m where
   (>>=) :: forall a b. m a -> (a -> m b) -> m b

   (>>) :: forall a b. m a -> m b -> m b
   m >> k = m >>= \ _ -> k
   {-# INLINE (>>) #-}

   return :: a -> m a
   return = pure

सादगी की खातिर, यह स्पष्टीकरण प्रकार श्रेणी पदानुक्रम का उपयोग करता है

class              Functor f
class Functor m => Monad m

हास्केल में, वर्तमान मानक पदानुक्रम है

class                  Functor f
class Functor p     => Applicative p
class Applicative m => Monad m

क्योंकि न केवल हर मोनाड एक फनकार है, बल्कि हर मादक एक फनकार है और हर मोनाड एक ऐक्यूटिव भी है।

सूची का उपयोग करते हुए मोनाड, अनिवार्य छद्मकोश

for a in (1, ..., 10)
   for b in (1, ..., 10)
      p <- a * b
      if even(p)
         yield p

मोटे तौर पर डो ब्लॉक में अनुवाद करता है ,

do a <- [1 .. 10]
   b <- [1 .. 10]
   let p = a * b
   guard (even p)
   return p

बराबर मोनाड की समझ ,

[ p | a <- [1 .. 10], b <- [1 .. 10], let p = a * b, even p ]

और अभिव्यक्ति

[1 .. 10] >>= (\ a ->
   [1 .. 10] >>= (\ b ->
      let p = a * b in
         guard (even p) >>       -- [ () | even p ] >>
            return p
      )
   )

नेशन बाइंड एक्सप्रेशन के लिए नोटेशन और मोनाड कॉम्प्रिहेंशन सिंटैक्टिक शुगर हैं। बाइंड ऑपरेटर का उपयोग स्थानीय नाम बाध्यकारी परिणामों के लिए किया जाता है।

let x = v in e    =   (\ x -> e)  $  v   =   v  &  (\ x -> e)
do { r <- m; c }  =   (\ r -> c) =<< m   =   m >>= (\ r -> c)

कहाँ पे

(&) :: a -> (a -> b) -> b
(&) = flip ($)

infixl 0 &

गार्ड फ़ंक्शन को परिभाषित किया गया है

guard :: Additive m => Bool -> m ()
guard True  = return ()
guard False = fail

जहां इकाई प्रकार या "खाली टपल"

data () = ()

Additive monads कि समर्थन विकल्प और विफलता एक प्रकार वर्ग का उपयोग करने पर निकाला जा सकता है

class Monad m => Additive m where
   fail  :: m t
   (<|>) :: m t -> m t -> m t

infixl 3 <|>

instance Additive Maybe where
   fail = Nothing

   Nothing <|> m = m
   m       <|> _ = m

instance Additive [] where
   fail = []
   (<|>) = (++)

जहाँ failऔर <|>एक मोनॉयड बनाते हैंforall k l m.

     k <|> fail  =  k
     fail <|> l  =  l
(k <|> l) <|> m  =  k <|> (l <|> m)

और failadditive भिक्षुओं के शून्य तत्व को अवशोषित / नष्ट करना है

_ =<< fail  =  fail

मैं फ़िन

guard (even p) >> return p

even pयह सच है, तब गार्ड , स्थानीय स्थिर फ़ंक्शन [()]की परिभाषा के अनुसार उत्पादन करता है , और>>

\ _ -> return p

परिणाम पर लागू होता है ()। यदि गलत है, तो गार्ड सूची मोनाद fail( []) का उत्पादन करता है , जो क्लेस्ली तीर के लिए कोई परिणाम नहीं देता >>है, ताकि इसे लागू किया जा सकेp पर छोड़ दिया जाता है।

राज्य

बदनाम रूप से, संन्यासी का उपयोग संस्थागत गणना को सांकेतिक करने के लिए किया जाता है।

एक राज्य प्रोसेसर एक फ़ंक्शन है

forall st t. st -> (t, st)

जो एक स्थिति का संक्रमण करता है stऔर एक परिणाम देता है tराज्य st में कुछ भी हो सकता है। कुछ नहीं, झंडा, गिनती, सरणी, संभाल, मशीन, दुनिया।

राज्य प्रोसेसर का प्रकार आमतौर पर कहा जाता है

type State st t = st -> (t, st)

राज्य प्रोसेसर इकाई kinded है * -> *functor State st। राज्य प्रोसेसर मोनाड के क्लेली तीर कार्य हैं

forall st a b. a -> (State st) b

कैनोनिकल हास्केल में, राज्य प्रोसेसर मोनाड का आलसी संस्करण परिभाषित किया गया है

newtype State st t = State { stateProc :: st -> (t, st) }

instance Functor (State st) where
   map :: (a -> b) -> ((State st) a -> (State st) b)
   map f (State p) = State $ \ s0 -> let (x, s1) = p s0
                                     in  (f x, s1)

instance Monad (State st) where
   return :: t -> (State st) t
   return x = State $ \ s -> (x, s)

   (=<<) :: (a -> (State st) b) -> (State st) a -> (State st) b
   f =<< (State p) = State $ \ s0 -> let (x, s1) = p s0
                                     in  stateProc (f x) s1

एक राज्य प्रोसेसर एक प्रारंभिक राज्य की आपूर्ति द्वारा चलाया जाता है:

run :: State st t -> st -> (t, st)
run = stateProc

eval :: State st t -> st -> t
eval = fst . run

exec :: State st t -> st -> st
exec = snd . run

राज्य पहुँच पुरातन द्वारा प्रदान की जाती है getऔर put, अधिक अमूर्त के तरीकों स्टेटफुल monads:

{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies #-}

class Monad m => Stateful m st m -> st where
   get :: m st
   put :: st -> m ()

m -> stभिक्षु पर राज्य प्रकार की कार्यात्मक निर्भरता की घोषणा करता है ; एक है कि , उदाहरण के लिए, राज्य प्रकार का निर्धारण हो जाएगा विशिष्ट।stmState tt

instance Stateful (State st) st where
   get :: State st st
   get = State $ \ s -> (s, s)

   put :: st -> State st ()
   put s = State $ \ _ -> ((), s)

इकाई प्रकार के साथ voidC में समान रूप से उपयोग किया जाता है।

modify :: Stateful m st => (st -> st) -> m ()
modify f = do
   s <- get
   put (f s)

gets :: Stateful m st => (st -> t) -> m t
gets f = do
   s <- get
   return (f s)

gets अक्सर रिकॉर्ड फ़ील्ड एक्सेसर्स के साथ उपयोग किया जाता है।

चर सूत्रण के बराबर राज्य मोनाद

let s0 = 34
    s1 = (+ 1) s0
    n = (* 12) s1
    s2 = (+ 7) s1
in  (show n, s2)

जहां s0 :: Int, समान रूप से पारदर्शी पारदर्शी है, लेकिन असीम रूप से अधिक सुरुचिपूर्ण और व्यावहारिक है

(flip run) 34
   (do
      modify (+ 1)
      n <- gets (* 12)
      modify (+ 7)
      return (show n)
   )

modify (+ 1)State Int ()इसके समान प्रभाव को छोड़कर, प्रकार की गणना है return ()

(flip run) 34
   (modify (+ 1) >>
      gets (* 12) >>= (\ n ->
         modify (+ 7) >>
            return (show n)
      )
   )

सहानुभूति के मोनड कानून के संदर्भ में लिखा जा सकता है >>= forall m f g.

(m >>= f) >>= g  =  m >>= (\ x -> f x >>= g)

या

do {                 do {                   do {
   r1 <- do {           x <- m;                r0 <- m;
      r0 <- m;   =      do {            =      r1 <- f r0;
      f r0                 r1 <- f x;          g r1
   };                      g r1             }
   g r1                 }
}                    }

अभिव्यक्ति-उन्मुख प्रोग्रामिंग (जैसे जंग) में, एक ब्लॉक का अंतिम बयान इसकी उपज का प्रतिनिधित्व करता है। बाइंड ऑपरेटर को कभी-कभी "प्रोग्रामेबल अर्धविराम" कहा जाता है।

संरचित अनिवार्य प्रोग्रामिंग से Iteration control संरचना प्राइमेटरी मोनोडिक रूप से अनुकरण की जाती है

for :: Monad m => (a -> m b) -> [a] -> m ()
for f = foldr ((>>) . f) (return ())

while :: Monad m => m Bool -> m t -> m ()
while c m = do
   b <- c
   if b then m >> while c m
        else return ()

forever :: Monad m => m t
forever m = m >> forever m

इनपुट आउटपुट

data World

I / O वर्ल्ड स्टेट प्रोसेसर मोनाड शुद्ध हास्केल और वास्तविक दुनिया का एक मेल है, जो कार्यात्मक संप्रदाय और अनिवार्य परिचालन शब्दार्थ का है। वास्तविक सख्त कार्यान्वयन का एक नजदीकी एनालॉग:

type IO t = World -> (t, World)

बातचीत को अशुद्ध आदिमियों द्वारा सुगम बनाया गया है

getChar         :: IO Char
putChar         :: Char -> IO ()
readFile        :: FilePath -> IO String
writeFile       :: FilePath -> String -> IO ()
hSetBuffering   :: Handle -> BufferMode -> IO ()
hTell           :: Handle -> IO Integer
. . .              . . .

कोड का उपयोग करने वाली अशुद्धता, IOस्थायी रूप से टाइप सिस्टम द्वारा प्रोटोकॉल है। क्योंकि पवित्रता भयानक है, इसमें क्या होता है IO, इसमें रहता है IO

unsafePerformIO :: IO t -> t

या, कम से कम, चाहिए।

हास्केल कार्यक्रम का प्रकार हस्ताक्षर

main :: IO ()
main = putStrLn "Hello, World!"

तक फैलता है

World -> ((), World)

एक फ़ंक्शन जो एक दुनिया को बदल देता है।

उपसंहार

जिस श्रेणी की वस्तुएं हास्केल प्रकार की होती हैं और हस्केल प्रकारों के बीच कार्य करता है, वह श्रेणी "तेज और ढीली" है Hask

एक फ़नकार Tएक श्रेणी से एक श्रेणी के Cलिए एक मानचित्रण है D; में प्रत्येक वस्तु के लिए Cमें एक वस्तुD

Tobj :  Obj(C) -> Obj(D)
   f :: *      -> *

और में प्रत्येक आकारिता के लिए Cमें एक आकारिताD

Tmor :  HomC(X, Y) -> HomD(Tobj(X), Tobj(Y))
 map :: (a -> b)   -> (f a -> f b)

जहाँ X, Yमें वस्तुएँ हैं CHomC(X, Y)है समरूपता वर्ग सभी morphisms की X -> Yमें C। फ़नकार को मॉर्फ़िज़्म आइडेंटिटी और कंपोज़िशन को संरक्षित करना चाहिए, जिसमें "स्ट्रक्चर" Cइन है D

                    Tmor    Tobj

      T(id)  =  id        : T(X) -> T(X)   Identity
T(f) . T(g)  =  T(f . g)  : T(X) -> T(Z)   Composition

एक श्रेणी की क्लेइस्ली श्रेणीC क्लेइस्ली ट्रिपल द्वारा दी गई है

<T, eta, _*>

एंडोफूनक्टर का

T : C -> C

( f), एक पहचान आकारिकी eta( return), और एक विस्तार ऑपरेटर *( =<<)।

प्रत्येक क्लेली मॉर्फिज़्म में Hask

      f :  X -> T(Y)
      f :: a -> m b

विस्तार ऑपरेटर द्वारा

   (_)* :  Hom(X, T(Y)) -> Hom(T(X), T(Y))
  (=<<) :: (a -> m b)   -> (m a -> m b)

Haskक्लेइस्ली श्रेणी में एक रूपवाद दिया जाता है

     f* :  T(X) -> T(Y)
(f =<<) :: m a  -> m b

क्लेस्ली श्रेणी में रचना .Tविस्तार के संदर्भ में दी गई है

 f .T g  =  f* . g       :  X -> T(Z)
f <=< g  =  (f =<<) . g  :: a -> m c

और श्रेणी स्वयंसिद्धों को संतुष्ट करता है

       eta .T g  =  g                :  Y -> T(Z)   Left identity
   return <=< g  =  g                :: b -> m c

       f .T eta  =  f                :  Z -> T(U)   Right identity
   f <=< return  =  f                :: c -> m d

  (f .T g) .T h  =  f .T (g .T h)    :  X -> T(U)   Associativity
(f <=< g) <=< h  =  f <=< (g <=< h)  :: a -> m d

जो, तुल्यता परिवर्तनों को लागू करना

     eta .T g  =  g
     eta* . g  =  g               By definition of .T
     eta* . g  =  id . g          forall f.  id . f  =  f
         eta*  =  id              forall f g h.  f . h  =  g . h  ==>  f  =  g

(f .T g) .T h  =  f .T (g .T h)
(f* . g)* . h  =  f* . (g* . h)   By definition of .T
(f* . g)* . h  =  f* . g* . h     . is associative
    (f* . g)*  =  f* . g*         forall f g h.  f . h  =  g . h  ==>  f  =  g

विस्तार के संदर्भ में विहित रूप से दिए गए हैं

               eta*  =  id                 :  T(X) -> T(X)   Left identity
       (return =<<)  =  id                 :: m t -> m t

           f* . eta  =  f                  :  Z -> T(U)      Right identity
   (f =<<) . return  =  f                  :: c -> m d

          (f* . g)*  =  f* . g*            :  T(X) -> T(Z)   Associativity
(((f =<<) . g) =<<)  =  (f =<<) . (g =<<)  :: m a -> m c

मोनाड्स को क्लेसीलियन एक्सटेंशन के नहीं, बल्कि muप्रोग्रामिंग में एक प्राकृतिक परिवर्तन के रूप में परिभाषित किया जा सकता है join। एक मोनाड को muएक श्रेणी के एक ट्रिपल के रूप में परिभाषित किया जाता है C, एक एंडोफ़नक्टर का

     T :  C -> C
     f :: * -> *

और दो प्राकृतिक ट्रांसफॉर्मेशन

   eta :  Id -> T
return :: t  -> f t

    mu :  T . T   -> T
  join :: f (f t) -> f t

समतुल्यता को संतुष्ट करना

       mu . T(mu)  =  mu . mu               :  T . T . T -> T . T   Associativity
  join . map join  =  join . join           :: f (f (f t)) -> f t

      mu . T(eta)  =  mu . eta       =  id  :  T -> T               Identity
join . map return  =  join . return  =  id  :: f t -> f t

मोनड प्रकार वर्ग तब परिभाषित किया गया है

class Functor m => Monad m where
   return :: t -> m t
   join   :: m (m t) -> m t

muविकल्प सनद के विहित कार्यान्वयन:

instance Monad Maybe where
   return = Just

   join (Just m) = m
   join Nothing  = Nothing

concatसमारोह

concat :: [[a]] -> [a]
concat (x : xs) = x ++ concat xs
concat []       = []

है joinसूची इकाई की।

instance Monad [] where
   return :: t -> [t]
   return = (: [])

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

के क्रियान्वयन joinतुल्यता का उपयोग कर विस्तार रूप से अनुवाद किया जा सकता

     mu  =  id*           :  T . T -> T
   join  =  (id =<<)      :: m (m t) -> m t

muएक्सटेंशन फॉर्म से रिवर्स ट्रांसलेशन द्वारा दिया गया है

     f*  =  mu . T(f)     :  T(X) -> T(Y)
(f =<<)  =  join . map f  :: m a -> m b

लेकिन प्रोग्रामिंग के लिए किसी सिद्धांत का इतना सार क्यों होना चाहिए?

उत्तर सरल है: कंप्यूटर वैज्ञानिकों के रूप में, हम अमूर्तता को महत्व देते हैं ! जब हम किसी सॉफ़्टवेयर घटक के लिए इंटरफ़ेस डिज़ाइन करते हैं, तो हम चाहते हैं कि यह कार्यान्वयन के बारे में जितना संभव हो उतना कम प्रकट हो। हम कार्यान्वयन को कई विकल्पों, एक ही 'अवधारणा' के कई अन्य 'उदाहरणों' के साथ बदलने में सक्षम होना चाहते हैं। जब हम कई प्रोग्राम पुस्तकालयों में एक सामान्य इंटरफ़ेस डिज़ाइन करते हैं, तो यह और भी महत्वपूर्ण है कि हम जो इंटरफ़ेस चुनते हैं, उसमें कई प्रकार के कार्यान्वयन हैं। यह मोनड अवधारणा की व्यापकता है जिसे हम बहुत अधिक महत्व देते हैं, ऐसा इसलिए है क्योंकि श्रेणी सिद्धांत इतना सार है कि इसकी अवधारणा प्रोग्रामिंग के लिए बहुत उपयोगी है।

यह, शायद ही आश्चर्य की बात है, कि हम नीचे प्रस्तुत भिक्षुओं के सामान्यीकरण का भी श्रेणी सिद्धांत से गहरा संबंध है। लेकिन हम इस बात पर जोर देते हैं कि हमारा उद्देश्य बहुत व्यावहारिक है: यह 'श्रेणी सिद्धांत को लागू करने' के लिए नहीं है, यह कॉम्बिनेटर पुस्तकालयों की संरचना के लिए एक अधिक सामान्य तरीका खोजना है। यह बस हमारा सौभाग्य है कि गणितज्ञों ने हमारे लिए बहुत काम किया है!

से तीर को Generalising monads जॉन ह्यूजेस द्वारा


4

दुनिया को एक और मोनाड ब्लॉग पोस्ट की आवश्यकता है, लेकिन मुझे लगता है कि यह जंगली में मौजूदा साधुओं की पहचान करने में उपयोगी है।

Sierpinski त्रिकोण

ऊपर Sierpinski त्रिभुज नामक एक भग्न है, एकमात्र भग्न जिसे मैं आकर्षित करना याद कर सकता हूं। फ्रैक्टल्स उपरोक्त त्रिभुज की तरह स्वयं-समान संरचना है, जिसमें भागों पूरे के समान हैं (इस मामले में मूल त्रिकोण के रूप में आधा पैमाने पर)।

मोनाड भग्न हैं। एक मौद्रिक डेटा संरचना को देखते हुए, इसके मूल्यों को डेटा संरचना का एक और मूल्य बनाने के लिए बनाया जा सकता है। यही कारण है कि यह प्रोग्रामिंग के लिए उपयोगी है, और यही कारण है कि यह कई स्थितियों में होता है।


3
क्या आपका मतलब है "दुनिया को क्या ज़रूरत नहीं है ..."? हालांकि अच्छा सादृश्य!
ग्रोवेबॉय

@ icc97 आप सही हैं - अर्थ पर्याप्त स्पष्ट है। सरकस्म अनायास ही, लेखक से माफी माँगता है।
ग्रोवेबॉय

दुनिया को क्या चाहिए एक और टिप्पणी धागा एक व्यंग्य की पुष्टि करता है, लेकिन अगर ध्यान से पढ़ा जाए तो मैंने लिखा है, लेकिन इसे स्पष्ट करना चाहिए।
यूजीन योकोटा

4

http://code.google.com/p/monad-tutorial/ वास्तव में इस प्रश्न का समाधान करने के लिए प्रगति पर काम कर रहा है।


5
देखें कि क्या इससे प्रोजेक्ट्स में
टोनी मॉरिस

Google कोड 2016-01-15 को बंद होने जा रहा है। अधिकांश परियोजनाएं अब केवल 2015-08-24 तक पढ़ी जाती हैं।
पीटर मॉर्टेंसन

4

नीचे " {| a |m}" मानदंड डेटा के कुछ टुकड़े का प्रतिनिधित्व करते हैं। एक डेटा प्रकार जो विज्ञापन देता है a:

        (I got an a!)
          /        
    {| a |m}

समारोह, fजानता है कि कैसे एक सनक बनाने के लिए, अगर केवल यह एक था a:

       (Hi f! What should I be?)
                      /
(You?. Oh, you'll be /
 that data there.)  /
 /                 /  (I got a b.)
|    --------------      |
|  /                     |
f a                      |
  |--later->       {| b |m}

यहां हम फ़ंक्शन देखते हैं, fएक मोनाड का मूल्यांकन करने की कोशिश करते हैं, लेकिन फटकार लगाते हैं।

(Hmm, how do I get that a?)
 o       (Get lost buddy.
o         Wrong type.)
o       /
f {| a |m}

Funtion, का उपयोग करके fनिकालने का एक तरीका ढूँढता है ।a>>=

        (Muaahaha. How you 
         like me now!?)       
    (Better.)      \
        |     (Give me that a.)
(Fine, well ok.)    |
         \          |
   {| a |m}   >>=   f

कम ही fजानता है, सन्यासी और >>=मिलीभगत में हैं।

            (Yah got an a for me?)       
(Yeah, but hey    | 
 listen. I got    |
 something to     |
 tell you first   |
 ...)   \        /
         |      /
   {| a |m}   >>=   f

लेकिन वे वास्तव में क्या बात करते हैं? ठीक है, यह मठ पर निर्भर करता है। केवल सार में बात करना सीमित उपयोग है; आपके पास समझ बढ़ाने के लिए विशेष साधुओं के साथ कुछ अनुभव होना चाहिए।

उदाहरण के लिए, डेटा प्रकार हो सकता है

 data Maybe a = Nothing | Just a

एक सनक उदाहरण है जो निम्नलिखित की तरह काम करेगा ...

जिसमें, यदि मामला है Just a

            (Yah what is it?)       
(... hm? Oh,      |
forget about it.  |
Hey a, yr up.)    | 
            \     |
(Evaluation  \    |
time already? \   |
Hows my hair?) |  |
      |       /   |
      |  (It's    |
      |  fine.)  /
      |   /     /    
   {| a |m}   >>=   f

लेकिन के मामले के लिए Nothing

        (Yah what is it?)       
(... There      |
is no a. )      |
  |        (No a?)
(No a.)         |
  |        (Ok, I'll deal
  |         with this.)
   \            |
    \      (Hey f, get lost.) 
     \          |   ( Where's my a? 
      \         |     I evaluate a)
       \    (Not any more  |
        \    you don't.    |
         |   We're returning
         |   Nothing.)   /
         |      |       /
         |      |      /
         |      |     /
   {| a |m}   >>=   f      (I got a b.)
                    |  (This is   \
                    |   such a     \
                    |   sham.) o o  \
                    |               o|
                    |--later-> {| b |m}

तो हो सकता है कि मोनाड एक संगणना को जारी रखने देता है यदि उसमें वास्तव में aयह विज्ञापित होता है, लेकिन यदि यह नहीं होता है तो अभिकलन को निरस्त कर देता है। परिणाम, हालांकि अभी भी एक मानद डेटा का टुकड़ा है, हालांकि आउटपुट नहीं हैf । इस कारण से, शायद मोनड का उपयोग विफलता के संदर्भ का प्रतिनिधित्व करने के लिए किया जाता है।

अलग-अलग संन्यासी अलग व्यवहार करते हैं। सूचियाँ अन्य प्रकार के डेटा हैं, जिसमें मोनडिक उदाहरण हैं। वे निम्नलिखित की तरह व्यवहार करते हैं:

(Ok, here's your a. Well, its
 a bunch of them, actually.)
  |
  |    (Thanks, no problem. Ok
  |     f, here you go, an a.)
  |       |
  |       |        (Thank's. See
  |       |         you later.)
  |  (Whoa. Hold up f,      |
  |   I got another         |
  |   a for you.)           |
  |       |      (What? No, sorry.
  |       |       Can't do it. I 
  |       |       have my hands full
  |       |       with all these "b" 
  |       |       I just made.) 
  |  (I'll hold those,      |
  |   you take this, and   /
  |   come back for more  /
  |   when you're done   / 
  |   and we'll do it   / 
  |   again.)          /
   \      |  ( Uhhh. All right.)
    \     |       /    
     \    \      /
{| a |m}   >>=  f  

इस मामले में, फ़ंक्शन जानता था कि यह इनपुट से एक सूची कैसे बना सकता है, लेकिन यह नहीं जानता कि अतिरिक्त इनपुट और अतिरिक्त सूचियों के साथ क्या करना है। बाँध >>=, fकई outputs के संयोजन से मदद की । मैं इस उदाहरण को यह दिखाने के लिए शामिल करता हूं कि >>=निकालने के लिए ज़िम्मेदार होने aके बावजूद, इसके अंतिम बाउंड आउटपुट तक भी पहुंच है f। वास्तव में, यह कभी भी किसी को नहीं निकालेगा aजब तक कि यह पता न हो कि आखिरकार उत्पादन का एक ही प्रकार का संदर्भ है।

अन्य संन्यासी हैं जो विभिन्न संदर्भों का प्रतिनिधित्व करने के लिए उपयोग किए जाते हैं। यहाँ कुछ और के लक्षण हैं। IOइकाई वास्तव में एक नहीं है a, लेकिन यह एक आदमी को जानता है और कहा कि मिल जाएगा aआप के लिए। State stइकाई की एक गुप्त गुप्त कोष है stकि यह करने के लिए पारित करेंगे fटेबल के नीचे है, भले ही fसिर्फ एक के लिए पूछ आया aReader rइकाई के समान है State st, हालांकि यह केवल की सुविधा देता है, fपर देखो r

इस सब में बिंदु यह है कि किसी भी प्रकार का डेटा जो खुद को मोनाड घोषित करता है, वह मोनाड से मूल्य निकालने के आसपास किसी तरह का संदर्भ घोषित कर रहा है। इस सब से बड़ा फायदा? खैर, यह आसान है कि किसी प्रकार के संदर्भ के साथ गणना को काउच किया जाए। यह गड़बड़ हो सकता है, हालांकि, जब एक साथ कई संदर्भ लादेन गणना करते हैं। मोनाद संचालन संदर्भ की बातचीत को हल करने का ध्यान रखता है ताकि प्रोग्रामर को न हो।

ध्यान दें, कि >>=स्वायत्तता से कुछ दूर ले जाकर आसानी से एक गड़बड़ का उपयोग करता है fNothingउदाहरण के लिए, उपरोक्त मामले में , fअब यह तय नहीं किया जाता है कि मामले में क्या करना है Nothing; इसमें एन्कोड किया गया है >>=। यह व्यापार बंद है। यदि यह जरूरी हो गया था के लिए fतय करने के लिए क्या करने के मामले में क्या करना Nothingहै, तो fसे एक समारोह किया जाना चाहिए था Maybe aकरने के लिए Maybe b। इस मामले में, Maybeएक सन्यासी होना अप्रासंगिक है।

ध्यान दें, हालांकि, कभी-कभी एक डेटा प्रकार यह निर्यात करने वालों को निर्यात नहीं करता है (आप पर ध्यान केंद्रित करते हुए IO), और यदि हम विज्ञापित मूल्य के साथ काम करना चाहते हैं तो हमारे पास बहुत कम विकल्प हैं लेकिन इसके साथ काम करना है।


3

एक सनक एक ऐसी चीज है जिसका उपयोग वस्तुओं को बदलने के लिए किया जाता है जिनकी बदलती स्थिति होती है। यह अक्सर उन भाषाओं में सामना किया जाता है जो अन्यथा आपको परिवर्तनीय स्थिति (जैसे, हास्केल) की अनुमति नहीं देते हैं।

एक उदाहरण I / O फ़ाइल के लिए होगा।

आप फ़ाइल I / O के लिए एक सनक का उपयोग करने में सक्षम होंगे जो बदलते राज्य की प्रकृति को केवल उस कोड को अलग करने के लिए जो मोनाड का उपयोग करता है। मोनाड के अंदर का कोड मोनाड के बाहर की दुनिया की बदलती स्थिति को प्रभावी ढंग से अनदेखा कर सकता है - इससे आपके कार्यक्रम के समग्र प्रभाव के बारे में तर्क करना बहुत आसान हो जाता है।


3
जैसा कि मैं समझता हूं, भिक्षु इससे अधिक हैं। एक "शुद्ध" कार्यात्मक भाषाओं में उत्परिवर्तनीय राज्य को एनकैप्सुलेट करना केवल एक आवेदन है।
thSoft
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.