2013-05-08 10 views
25

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

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

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

+10

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

+1

@ टिखोन जेल्विस: मुझे नहीं लगता कि "अधिक से अधिक उन्नत हास्केलर्स मुझे कुछ डिग्री के लिए आवेदन के पक्ष में पता है।" जिन चीजों को मैं सबसे अधिक ध्यान में देख रहा हूं वे विशेष रूप से आवेदक से संबंधित नहीं हैं। एक उदाहरण के रूप में, [जिस पर मैं काम कर रहा हूं] (http://hackage.haskell.org/package/free-operational) का उपयोग करने के लिए, मैं न्याय करता हूं कि मुफ़्त मोनैड अभी भी नि: शुल्क आवेदकों की तुलना में अधिक ब्याज का आदेश देते हैं। हालांकि, नि: शुल्क आवेदकों पर ब्याज हाल ही में बढ़ रहा है। –

+5

जहां तक ​​मुझे याद है, मोडैड को वाडलर द्वारा लोकप्रिय किया गया था, और उस समय आईओओ को थकाऊ सीपीएस के बिना और स्पष्ट राज्य गुजरने के बिना पार्सिंग का विचार भारी बिकने वाले अंक थे; यह एक बेहद रोमांचक समय था। एएफएआईआईआर, हास्केल ने कन्स्ट्रक्टर कक्षाएं नहीं कीं, लेकिन गोफर (हग्स के पिता) ने किया। वाडलर ने मोनैड के लिए ओवरलोडिंग सूची समझ का प्रस्ताव दिया, इसलिए बाद में नोटेशन आया। एक बार आईओ monadic था, monads शुरुआती के लिए एक बड़ा सौदा बन गया, उन्हें grok करने के लिए एक प्रमुख बात के रूप में cementing। जब आप कर सकते हैं तो आवेदन बहुत अच्छे होते हैं, और तीर अधिक सामान्य होते हैं, लेकिन वे बाद में आए, और आईओ मोनैड को बेचता है। – AndrewC

उत्तर

28

मुझे संदेह है कि कई अन्य लोगों पर इस विशेष प्रकार के वर्ग (Monad) को असमान रूप से बड़ा ध्यान दिया जाता है, जो मुख्य रूप से एक ऐतिहासिक झलक है। लोग अक्सर IOMonad के साथ संबद्ध करते हैं, हालांकि दोनों स्वतंत्र रूप से उपयोगी विचार हैं (as are list reversal and bananas)। क्योंकि IO जादुई है (कार्यान्वयन है लेकिन कोई संकेत नहीं है) और Monad अक्सर IO से जुड़ा हुआ है, Monad के बारे में जादुई सोच में पड़ना आसान है।

(एक तरफ:।? यह संदेहास्पद है कि क्या IO यहां तक ​​कि एक इकाई है इकाई कानूनों पकड़ क्या क्या कानून भी IO के लिए, मतलब है यानी, क्या समानता मतलब है नोट problematic association with the state monad?।)

+0

हे, केला लिंक बहुत मनोरंजक है। कोरआउट-आधारित व्याख्या के बारे में क्या एडवर्ड Kmett आपके दूसरे लिंक में उल्लेख है? –

+6

वाक्यांश "मैजिकल" का अर्थ है "मेरे कार्यान्वयन के साथ" कोई कार्यान्वयन नहीं है लेकिन कोई संकेत नहीं है "। –

+0

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

5

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

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

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

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

+2

विभिन्न चीजें हैं, जिन्हें फंक्टर या आवेदक के साथ व्यक्त किया जा सकता है, लेकिन मोनाड के साथ नहीं। हास्केल प्रोग्रामर अभी भी मोनाड्स के साथ ज्यादा मोहक क्यों हैं? http://stackoverflow.com/a/7220548/2361979 – qznc

+0

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

+0

@qznc - 'फ़ैक्टर' या 'आवेदक' इंटरफेस द्वारा व्यक्त किया जा सकता है जिसे 'मोनाड' इंटरफ़ेस द्वारा व्यक्त नहीं किया जा सकता है। 'मोनाद' कड़ाई से अधिक शक्तिशाली है। आपका लिंक इंटरफेस को लागू करने के बारे में है, जो दूसरी दिशा है। निस्संदेह कम शक्तिशाली इंटरफेस में अधिक कार्यान्वयन (या बराबर, लेकिन इस मामले में नहीं) संभव कार्यान्वयन है। – Carl

12

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

लेकिन हाँ, मोनैड बेहद लोकप्रिय हैं। इसका एक हिस्सा है नोटेशन; बहुत सारे मोनोइड्स मोनाड उदाहरण प्रदान करते हैं जो केवल चल रहे संचयक (अनिवार्य रूप से एक निहित लेखक) को मूल्य जोड़ते हैं। ब्लेज़-एचटीएमएल लाइब्रेरी एक अच्छा उदाहरण है। कारण, मुझे लगता है, प्रकार हस्ताक्षर (>>=) :: Monad m => m a -> (a -> m b) -> m b की शक्ति है। जबकि एफएमएपी और मैपेंड उपयोगी हैं, वे क्या कर सकते हैं काफी कम सीमित है। बाध्य, हालांकि, विभिन्न प्रकार की चीजें व्यक्त कर सकते हैं। यह निश्चित रूप से आईओ मोनैड में कैनोनाइज्ड है, शायद धाराओं और एफआरपी से पहले आईओ के लिए सबसे अच्छा शुद्ध कार्यात्मक दृष्टिकोण (और अभी भी सरल कार्यों और परिभाषित घटकों के लिए उनके बगल में उपयोगी)।लेकिन यह अंतर्निहित राज्य (रीडर/राइटर/एसटी) भी प्रदान करता है, जो कुछ बहुत ही थकाऊ परिवर्तनीय गुजरने से बच सकता है। विभिन्न राज्य मोनैड, विशेष रूप से, महत्वपूर्ण हैं क्योंकि वे गारंटी देते हैं कि राज्य एकल थ्रेडेड है, जो संलयन से पहले शुद्ध (गैर-आईओ) कोड में परिवर्तनीय संरचनाओं को अनुमति देता है। लेकिन बाइंड में कुछ और विदेशी उपयोग हैं, जैसे नेस्टेड डेटा स्ट्रक्चर (सूची और सेट मोनैड) को फ़्लैटन करना, दोनों ही उनके स्थान पर काफी उपयोगी हैं (और मैं आमतौर पर उन्हें डिस्क्लेड, लिफ्टएम या (>> =) को स्पष्ट रूप से इस्तेमाल करता हूं, इसलिए यह नोटेशन का मामला नहीं है)। इसलिए फेंक्टर और मोनॉयड (और कुछ दुर्लभ फोल्डबल, वैकल्पिक, ट्रैवर्सबल, और अन्य) एक काफी सरल कार्य करने के लिए एक मानक इंटरफ़ेस प्रदान करते हैं, मोनाड का बांध काफी लचीलापन है।

संक्षेप में, मुझे लगता है कि आपके सभी कारणों में कुछ भूमिका है; मोनैड की लोकप्रियता ऐतिहासिक दुर्घटना (नोटेशन और आवेदक की देरी परिभाषा) और उनके बिजली और सामान्यता (मज़दूरों, मोनोइड्स, और इसी तरह के संबंध) और समझदारी (तीरों के सापेक्ष) के संयोजन के कारण है।

14

हैं एक प्रकार m :: * -> * में Monad उदाहरण है, आपको a -> m b प्रकार के साथ फ़ंक्शंस की ट्यूरिंग-पूर्ण संरचना मिलती है। यह एक शानदार रूप से उपयोगी संपत्ति है। आपको विभिन्न ट्यूरिंग-पूर्ण नियंत्रण को अमूर्त करने की क्षमता विशिष्ट अर्थों से दूर बहती है। यह एक न्यूनतम संरचना पैटर्न है जो इसका समर्थन करने वाले प्रकारों के साथ काम करने के लिए किसी भी नियंत्रण प्रवाह को सारणीकरण का समर्थन करता है।

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

संपादित करें: लोकप्रिय मांग करके, यहाँ कुछ Monad वर्ग का उपयोग कर कार्य हैं:

ifM :: Monad m => m Bool -> m a -> m a -> m a 
ifM c x y = c >>= \z -> if z then x else y 

whileM :: Monad m => (a -> m Bool) -> (a -> m a) -> a -> m a 
whileM p step x = ifM (p x) (step x >>= whileM p step) (return x) 

(*&&) :: Monad m => m Bool -> m Bool -> m Bool 
x *&& y = ifM x y (return False) 

(*||) :: Monad m => m Bool -> m Bool -> m Bool 
x *|| y = ifM x (return True) y 

notM :: Monad m => m Bool -> m Bool 
notM x = x >>= return . not 

के साथ उन लोगों का मेल करना वाक्य रचना (या कच्चे >>= ऑपरेटर) आप बाध्यकारी नाम देता है, अनिश्चितकालीन पाशन, और पूर्ण बूलियन तर्क। यह ट्यूरिंग पूर्णता देने के लिए पर्याप्त प्राइमेटिव का एक प्रसिद्ध सेट है। ध्यान दें कि सरल मूल्यों के बजाय, मोनाडिक मानों पर काम करने के लिए सभी कार्यों को कैसे हटाया गया है। सभी monadic प्रभाव केवल तभी बंधे होते हैं जब केवल ifM की चुनी हुई शाखा के प्रभाव इसके अंतिम मूल्य में बंधे होते हैं। *&& और *|| दोनों संभव होने पर उनके दूसरे तर्क को अनदेखा करते हैं। और इतने पर ..

अब, उन प्रकार के हस्ताक्षर में प्रत्येक monadic ऑपरेंड के लिए कार्यों को शामिल नहीं किया जा सकता है, लेकिन यह सिर्फ एक संज्ञानात्मक सरलीकरण है।बोतलों को अनदेखा करते हुए कोई अर्थपूर्ण अंतर नहीं होगा, यदि सभी गैर-कार्य तर्क और परिणाम में बदल दिए गए थे। उपयोगकर्ताओं को उस संज्ञानात्मक ओवरहेड को अनुकूलित करने के लिए यह सिर्फ मित्रवत है।

अब, देखते हैं कि Applicative इंटरफ़ेस के साथ उन कार्यों के साथ क्या होता है।

ifA :: Applicative f => f Bool -> f a -> f a -> f a 
ifA c x y = (\c' x' y' -> if c' then x' else y') <$> c <*> x <*> y 

ठीक है, ओह। यह एक ही प्रकार के हस्ताक्षर मिला। लेकिन यहां पहले से ही एक बड़ी समस्या है। एक्स और वाई दोनों के प्रभाव रचनात्मक संरचना में बंधे हैं, भले ही किसी का मूल्य चुना गया हो।

whileA :: Applicative f => (a -> f Bool) -> (a -> f a) -> a -> f a 
whileA p step x = ifA (p x) (whileA p step <$> step x) (pure x) 

ठीक है, ठीक है, कि जैसे कि यह ठीक हो जाएगा तथ्य यह है कि यह एक अनंत लूप है, क्योंकि ifA हमेशा दोनों शाखाओं को निष्पादित करेंगे ... सिवाय यह भी है कि बंद नहीं है के अलावा लगता है। pure x में f a है। whileA p step <$> step x में f (f a) है। यह एक अनंत लूप भी नहीं है। यह संकलन त्रुटि है। आइए पुनः प्रयास करें ..

whileA :: Applicative f => (a -> f Bool) -> (a -> f a) -> a -> f a 
whileA p step x = ifA (p x) (whileA p step <*> step x) (pure x) 

अच्छी तरह से शूट करें। अब तक भी मत जाओ। whileA p step में a -> f a है। यदि आप इसे <*> के पहले तर्क के रूप में उपयोग करने का प्रयास करते हैं, तो शीर्ष प्रकार कन्स्ट्रक्टर के लिए , f पर Applicative उदाहरण प्राप्त करता है। हाँ, यह या तो काम नहीं करेगा।

वास्तव में, मेरे Monad उदाहरणों का एकमात्र कार्य Applicative इंटरफेस के साथ काम करेगा notM। यह विशेष कार्य वास्तव में केवल Functor इंटरफ़ेस के साथ ठीक काम करता है। बाकी? वे असफल हैं।

बेशक यह उम्मीद की जा सकती है कि आप Monad इंटरफ़ेस का उपयोग करके कोड लिख सकते हैं कि आप Applicative इंटरफ़ेस के साथ नहीं कर सकते हैं। यह सब के बाद सख्ती से अधिक शक्तिशाली है। लेकिन दिलचस्प क्या है जो आप खो देते हैं। आप उन कार्यों को लिखने की क्षमता खो देते हैं जो उनके इनपुट पर आधारित प्रभावों को बदलते हैं। यही है, आप कुछ नियंत्रण-प्रवाह पैटर्न लिखने की क्षमता खो देते हैं जो a -> f b प्रकारों के साथ फ़ंक्शंस लिखते हैं।

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

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

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

+2

ट्यूरिंग-पूर्णता के साथ पृथ्वी पर क्या करना है? (ध्यान दें कि ट्यूरिंग-पूर्ण नहीं होने वाली भाषाएं मोनैड्स, सीएफ। एजडा का उपयोग करने में पूरी तरह सक्षम हैं) –

+0

@ बेनमिलवुड एग्डा आपको कई संरचनाओं का उपयोग करने की अनुमति देती है जो सामान्य रूप से ट्यूरिंग-पूर्ण होते हैं, जब तक आप साबित करते हैं कि उनका उनका विशिष्ट उपयोग गैर-संरचनात्मक रिकर्सन की तरह समाप्त हो जाएगा। मुद्दा यह है कि मोनैड इंटरफ़ेस आपको ट्यूरिंग-पूर्ण पैटर्न का वर्णन करने की अनुमति देता है, न कि आपको इसका उपयोग करने की आवश्यकता होती है। ऐसा इसलिए है क्योंकि '= << 'आपको अपने पहले ऑपरेंड द्वारा उपयोग की जाने वाली रिकर्सन संरचना को दूसरे ऑपरेंड के मान पर निर्भर करता है। अगले निकटतम संरचना ऑपरेटर, '<*>' 'आवेदक 'से, यह आवश्यक है कि रिकर्सन संरचना दूसरे ऑपरेंड के मूल्य पर निर्भर न हो। – Carl

+2

मुझे अभी भी लगता है कि 'आवेदक' और 'मोनाद' के बीच का अंतर ट्यूरिंग-पूर्णता के साथ कुछ भी नहीं है। मैं नहीं देखता कि अवधारणाएं कैसे संबंधित हैं - ट्यूरिंग-पूर्णता का मतलब है, लगभग "एक ट्यूरिंग मशीन अनुकरण करने में सक्षम है, और इसे एक द्वारा अनुकरण किया जा सकता है"। स्वाभाविक रूप से बाद की स्थिति यहां चर्चा के तहत सब कुछ के लिए रखती है। क्या कार्यों की monadic संरचना 'a -> m b' एक ट्यूरिंग मशीन अनुकरण कर सकते हैं? यह ऐसा करने का प्रयास कैसे करेगा? –

0

मोनैड do नोटेशन के कारण विशेष हैं, जो आपको एक कार्यात्मक भाषा में अनिवार्य कार्यक्रम लिखने देता है। मोनाड अमूर्त है जो आपको छोटे, पुन: प्रयोज्य घटकों (जो स्वयं अनिवार्य कार्यक्रम हैं) से अनिवार्य कार्यक्रमों को एक साथ बांटने की अनुमति देता है। मोनाड ट्रांसफार्मर विशेष हैं क्योंकि वे नई सुविधाओं के साथ एक अनिवार्य भाषा को बढ़ाने का प्रतिनिधित्व करते हैं।

संबंधित मुद्दे