2011-12-09 7 views
19

मैंने हमेशा एक मकसद के सापेक्ष एक मोनैड की शक्ति के निम्नलिखित अंतर्ज्ञानी स्पष्टीकरण का आनंद लिया है: एक मोनड आकार बदल सकता है; एक मजेदार नहीं कर सकता।एक फंक्टर के विपरीत, एक मोनाड आकार बदल सकता है?

उदाहरण के लिए: length $ fmap f [1,2,3] हमेशा 3 के बराबर है।

एक मोनड के साथ, हालांकि, length $ [1,2,3] >>= g अक्सर 3 के बराबर नहीं होगा। उदाहरण के लिए, यदि g परिभाषित किया गया है के रूप में:

g :: (Num a) => a -> [a] 
g x = if x==2 then [] else [x] 

तो [1,2,3] >>= g[1,3] के बराबर है।

जो चीज़ मुझे थोड़ा परेशान करती है, वह g का प्रकार हस्ताक्षर है। यह इस तरह के रूप में एक सामान्य monadic प्रकार के साथ एक समारोह जो इनपुट के आकार में परिवर्तन को परिभाषित करने के लिए असंभव लगता है:

h :: (Monad m, Num a) => a -> m a 

MonadPlus या MonadZero प्रकार कक्षाएं [] के बजाय का उपयोग करने के लिए प्रासंगिक शून्य तत्व है, लेकिन अब हम एक मोनड से कुछ और है।

क्या मैं सही हूँ? यदि हां, तो क्या इस सूक्ष्मता को हास्केल में नवागंतुक को व्यक्त करने का कोई तरीका है। मैं अपने प्यारे "monads आकार बदल सकते हैं" वाक्यांश बनाना चाहते हैं, बस एक स्पर्श अधिक ईमानदार; अगर जरूरत हो।

उत्तर

16

मैंने हमेशा एक मकसद के सापेक्ष एक मोनाड की शक्ति के निम्नलिखित अंतर्ज्ञानी स्पष्टीकरण का आनंद लिया है: एक मोनड आकार बदल सकता है; एक मजेदार नहीं कर सकता।

आप रास्ते में थोड़ा सा सूक्ष्मता खो रहे हैं। शब्दावली के लिए, मैं Functor को हास्केल अर्थ में तीन हिस्सों में विभाजित कर दूंगा: पैरामीटर द्वारा निर्धारित पैरामीट्रिक घटक और fmap पर संचालित, State में टुपल कन्स्ट्रक्टर जैसे अपरिवर्तनीय हिस्सों, और "आकार" कुछ और के रूप में, जैसे कि रचनाकारों के बीच विकल्प (उदाहरण के लिए, Nothing बनाम Just) या अन्य प्रकार के पैरामीटर शामिल हैं (उदाहरण के लिए, Reader में वातावरण)।

Functor अकेले पैरामीट्रिक भाग पर मानचित्रण कार्यों तक ही सीमित है।

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

यह अनिवार्य रूप से Applicative उनके बीच फिट बैठता है - यह आपको बाद में प्रभाव को प्रभावित किए बिना दो Functors स्वतंत्र रूप से आकार और पैरामीट्रिक मानों को गठबंधन करने की अनुमति देता है।

क्या मैं सही हूँ? यदि हां, तो क्या इस सूक्ष्मता को हास्केल में नवागंतुक को व्यक्त करने का कोई तरीका है। मैं अपने प्यारे "monads आकार बदल सकते हैं" वाक्यांश बनाना चाहते हैं, बस एक स्पर्श अधिक ईमानदार; अगर जरूरत हो।

शायद आप यहां जो सूक्ष्मता खोज रहे हैं वह यह है कि आप वास्तव में कुछ भी "बदल नहीं रहे" हैं। Monad में कुछ भी आपको आकार के साथ स्पष्ट रूप से गड़बड़ करने देता है। यह आपको क्या करने देता है प्रत्येक पैरामीट्रिक मान के आधार पर नए आकार बनाते हैं, और उन नए आकारों को एक नए समग्र आकार में पुनः संयोजित किया जाता है।

इस प्रकार, आप हमेशा आकार बनाने के उपलब्ध तरीकों से सीमित रहेंगे। एक पूरी तरह से सामान्य Monad के साथ आपके पास return है, जो परिभाषा के अनुसार जो भी आकार आवश्यक है, (>>= return) पहचान फ़ंक्शन है। Monad की परिभाषा आपको कुछ प्रकार के कार्यों के अनुसार बताती है कि आप क्या कर सकते हैं; यह आपके लिए उन कार्यों को प्रदान नहीं करता है।

+0

लेकिन आप 'अनुक्रम' जैसी चीजें कर सकते हैं, है ना? मैं कहूंगा कि संरचना निश्चित रूप से "बदल रही है"। – Rotsor

+0

@Rotsor: वास्तव में नहीं। 'अनुक्रम' केवल मौजूदा संरचनाओं को समान रूप से जोड़ता है '(>> =)' करता है, लेकिन यह चीजों की पूरी सूची को एक साथ जोड़कर करता है। यह ऐसी कुछ भी नहीं कर सकता जो उस सूची में नहीं है जिसे आप इसे लागू करते हैं। –

+0

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

0

अपनी आवश्यकताओं

h :: (Monad m, Num a) => a -> m a 
h 0 = fail "Failed." 
h a = return a 

सूट करता है? उदाहरण के लिए, वास्तव में h की तरह एक हस्ताक्षर के साथ

> [0,1,2,3] >>= h 
[1,2,3] 
+3

दिलचस्प है, लेकिन मैं 'mzero' के साथ वर्ग' विफल 'होगा: एक मोनड की औपचारिक परिभाषा के बाहर। – user2023370

+7

हां, 'असफल' 'मोनाद 'में नहीं है। – augustss

3

एक समारोह अपने तर्क पर कुछ गणित प्रदर्शन से परे कई दिलचस्प बातें नहीं कर सकते। तो, आपके पास सही अंतर्ज्ञान है।

हालांकि, यह functions with similar signatures के लिए आमतौर पर उपयोग की जाने वाली लाइब्रेरी को देखने में मदद कर सकता है। आप पाएंगे कि सबसे सामान्य, जैसा कि आप उम्मीद करेंगे, जेनेरिक मोनैड ऑपरेशंस जैसे return, liftM, या join करें। साथ ही, जब आप एक मोनैडिक फ़ंक्शन में सामान्य फ़ंक्शन को उठाने के लिए liftM या fmap का उपयोग करते हैं, तो आप आम तौर पर समान सामान्य हस्ताक्षर के साथ हवादार होते हैं, और यह मोनैडिक कोड के साथ शुद्ध कार्यों को एकीकृत करने के लिए काफी सुविधाजनक है।

एक विशेष मोनैड ऑफ़र की संरचना का उपयोग करने के लिए, आपको अनिवार्य रूप से उस मोनैड में नए और रोचक कंप्यूटेशंस बनाने के लिए विशिष्ट मोनैड के बारे में कुछ ज्ञान का उपयोग करने की आवश्यकता है। राज्य मोनड पर विचार करें, (s -> (a, s))। उस प्रकार को जानने के बिना, हम get = \s -> (s, s) नहीं लिख सकते हैं, लेकिन राज्य तक पहुंचने में सक्षम होने के बिना, मोनड में होने का कोई मतलब नहीं है।

4

मोनैड के लिए मुख्य संयोजक (>>=) है। ,

(>>=) :: Monad m => m a -> (a -> m b) -> m b 

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

+0

मुझे एक मुश्किल सवाल दिखाई देता है, क्योंकि हम हर जगह [ए] प्रकार प्राप्त करते हैं, लेकिन * अलग * प्रकार होते हैं, मेरा मतलब है: जी को 'g :: (Num a, Num b) => a -> [b के रूप में व्यक्त किया जा सकता है ] 'और फिर आपके पास '(>> = g) :: (संख्या ए, संख्या बी) => [ए] -> [बी]' – Zhen

7

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

newtype Identity a = Identity a 
instance Monad Identity where 
    return = Identity 
    Identity a >>= f = f a 

वास्तव में, यह मुझे बहुत सारे monads सार्थक "आकार" रों है कि करने के लिए स्पष्ट नहीं है: उदाहरण के लिए, वहाँ केवल एक ही "आकार" उपलब्ध Identity इकाई में है State, Reader, Writer, ST, STM, या IO monads?

+0

सही है, और समझ में आया है, लेकिन मुझे व्यक्तिगत रूप से आकार की यह अवधारणा मिलती है, और " कंटेनर के रूप में monads ", बहुत उपयोगी; और परतों को सूचित करने में भी मदद कर सकते हैं। सामान्य विवरण बाद में संबोधित किया जा सकता है। – user2023370

+4

शब्द "आकार" मूल रूप से "राज्य" या "प्रभाव" के समानार्थी है - 'फंक्टर' के हिस्सों जो न तो पैरामीट्रिक हैं और न ही स्थिर हैं। विचार सार्थक है लेकिन उपयोग की जाने वाली शर्तें आदर्श से कम हैं। –

+0

@ user643722 ऐसा लगता है कि आप [मोनड burrito fallacy] के शिकार हो गए हैं (http://byorgey.wordpress.com/2009/01/12/abstraction-intuition-and-the-monad-tutorial-fallacy/) । यह बहुत अच्छा है कि यह आपको मोनाड्स को समझने में मदद करता है, लेकिन वास्तव में दूसरों को समझने में मुश्किल हो सकता है। –

8

Monad के संचालन हद >>= समारोह "पेड़" नोड के मूल्य से व्युत्पन्न एक नया उपसंरचना के साथ मूल मूल्य है कि में पत्र-गांठ की जगह है कि करने के लिए मूल्यों की "आकार बदल" कर सकते हैं (एक उपयुक्त सामान्य के लिए "पेड़" की धारणा - सूची के मामले में, "पेड़" सहयोगी है)।

आपकी सूची में उदाहरण क्या हो रहा है यह है कि प्रत्येक नंबर (पत्ता) को नई सूची द्वारा प्रतिस्थापित किया जा रहा है जिसके परिणामस्वरूप g उस नंबर पर लागू होता है। मूल सूची की समग्र संरचना अभी भी देखी जा सकती है यदि आप जानते हैं कि आप क्या खोज रहे हैं; g के परिणाम अभी भी क्रम में हैं, वे अभी एक साथ टूट गए हैं ताकि आप यह नहीं बता सकें कि कोई कहां समाप्त होता है और अगला तब तक शुरू होता है जब तक आप पहले से ही नहीं जानते।

के बजाय fmap और join पर विचार करने के लिए एक अधिक प्रबुद्ध बिंदु दृश्य हो सकता है। return के साथ, किसी भी तरह से एक मोनड की समतुल्य परिभाषा देता है। fmap/join देखें, हालांकि, यहां क्या हो रहा है और अधिक स्पष्ट है। अपनी सूची उदाहरण के साथ जारी रखते हुए, [[1],[],[3]] उपरोक्त सूची में gfmap पेड है। फिर वह सूची join एड है, जो सूची के लिए केवल concat है।

+2

यदि आप उत्सुक हैं, समकक्ष द्वारा दिखाया गया है: 'join = (>> = id)', 'fmap f = (>> = वापसी। F)', और 'f >> = x = join (fmap fx) ' – mokus

+1

हां वास्तव में, मैं '(>> =)' के बजाय 'join' का उपयोग करके monads को परिभाषित करने के पक्ष में दृढ़ता से हूं। – user2023370

+0

@ मोकस: महान जवाब! लेकिन मुझे पूरा यकीन है कि आपका मतलब था 'x >> = f = join (fmap f x) '। –

0

यह एक पूर्ण उत्तर नहीं है, लेकिन मेरे पास आपके प्रश्न के बारे में कुछ बातें कहने हैं जो वास्तव में किसी टिप्पणी में फिट नहीं होती हैं।

सबसे पहले, Monad और Functor टाइपक्लास हैं; वे प्रकार वर्गीकृत करते हैं। तो यह कहना अजीब बात है कि "एक मोनड आकार बदल सकता है; एक मजेदार नहीं कर सकता।" मेरा मानना ​​है कि आप किस बारे में बात करने की कोशिश कर रहे हैं वह "मोनाडिक वैल्यू" या शायद "मोनैडिक एक्शन" है: एक मान जिसका प्रकार m aMonad m* -> * और कुछ अन्य प्रकार के * के लिए है। मुझे पूरी तरह से यकीन नहीं है कि Functor f :: f a पर कॉल करना है, मुझे लगता है कि मैं इसे "एक मजेदार में मूल्य" कहूंगा, हालांकि, IO String (IO एक मज़ेदार है) का सबसे अच्छा विवरण नहीं है।

दूसरे, ध्यान दें कि सभी monads जरूरी functors (fmap = liftM) कर रहे हैं, तो मैं कहना चाहता हूँ अंतर आप निरीक्षण, fmap और >>= के बीच, या यहाँ तक f के बीच और g है बल्कि Monad और Functor के बीच से।

+1

मुझे आपके द्वारा उठाए गए अंकों से अवगत है। मैंने अनौपचारिक प्रश्न की भाषा रखने की कोशिश की, हालांकि मैंने निशान को ओवरस्टेप कर दिया होगा। जैसा कि दूसरों ने उल्लेख किया है, न ही कोई चीज आकार बदलती है; आखिरकार हम हास्केल का उपयोग कर रहे हैं :) – user2023370

1

एक समारोह आवश्यकता मैं कल्पना कर सकते हैं को संतुष्ट करने का सरलतम प्रकार है:

enigma :: Monad m => m() -> m() 

निम्न में से एक से एक तरीके से इसे लागू कर सकते हैं:

enigma1 m = m -- not changing the shape 

enigma2 _ = return() -- changing the shape 

यह एक बहुत ही सरल परिवर्तन किया गया - enigma2 बस आकार को त्याग देता है और इसे छोटे से बदल देता है। सामान्य परिवर्तन का एक और प्रकार दो आकृतियों साथ संयोजन है:

foo :: Monad m => m() -> m() -> m() 
foo a b = a >> b 

foo का परिणाम आकार a और b दोनों से अलग हो सकता है।

आकार का एक तिहाई स्पष्ट परिवर्तन, इकाई की पूरी शक्ति की आवश्यकता होती है, एक

join :: Monad m => m (m a) -> m a 
join x = x >>= id 

join x के आकार आमतौर पर x के ही रूप में एक ही नहीं है।

आकार के उन प्राचीन परिवर्तनों को जोड़कर, कोई भी sequence, foldM और समान रूप से गैर-तुच्छ चीज़ों को प्राप्त कर सकता है।

+0

मुझे यह नहीं दिख रहा है। 'शामिल' के साथ, हम monads के monads तक ही सीमित हैं। इसी तरह, आपके 'इनिग्मा' भिन्नताएं यूनिट प्रकार द्वारा पैरामीटर किए गए मोनैड की अपेक्षा करने लगती हैं - और इसका उत्पादन करती हैं। – user2023370

+0

उपयोगकर्ता 643722, क्या आपका मतलब यह है कि फ़ंक्शन सामान्य की तरह सामान्य नहीं हैं? वे 'एम' पर सार तत्व हैं, इसलिए वे किसी भी मोनड के लिए काम करते हैं। क्या वह पर्याप्त नहीं है? – Rotsor

+0

@ रोटर्स: क्या आपका मतलब यह नहीं था कि 'foo :: monad m => m a -> m a -> m a'? –