2013-05-09 9 views
21

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

  • कुछ विशेष ट्रांसफार्मर के शीर्ष पर होना चाहिए ढेर (उदाहरण के लिए रीडर टी? लेखक?)
  • डिजाइन को ड्राइव करने के लिए क्या करना चाहिए? सहज बोध? प्रकार? (उदाहरण के लिए अपनी एपीआई की जरूरतों के हिसाब से ढेर को आकार दें)
  • क्या प्रत्येक स्टैक एक दूसरे के लिए आइसोमोर्फिक है (कुछ हद तक) या यह संभावना है कि, यदि मैं अपना स्टैक गलत तरीके से बनाता हूं तो मैं निश्चित रूप से कुछ का उपयोग करने में सक्षम नहीं हो सकता अंतर्निहित monads या lift . lift . liftIO [...] का एक बड़ा bloated गड़बड़ है? मेरी आंत महसूस करने का सुझाव होगा कि, अगर ट्रांसफार्मर कुछ उदाहरण प्राप्त करते हैं (उदाहरण के लिए मोनैड रीडर, मोनाडियो, आदि, mtl में अधिकांश ट्रांसफार्मर की तरह), इससे कोई फर्क नहीं पड़ता कि मैंने ट्रांसफॉर्मर को किस क्रम में रखा है।

मुझे अनुभवी हास्केलर्स से सर्वोत्तम प्रथाओं या अंगूठे के नियमों के बारे में सुनने में रूचि है।

forever $ print "Thanks!"

उत्तर

21

यह अनुभव लेता है। याद रखने की एक बात यह है कि मोनैड ट्रांसफॉर्मर को मोनाद के बारे में कुछ भी नहीं पता है, इसलिए बाहरी व्यक्ति आंतरिक व्यवहार के द्वारा "बाध्य" होता है। तो

StateT s (ListT m) a 

, सबसे पहले और सबसे महत्वपूर्ण, आंतरिक मोनड की वजह से एक नोडेटर्मिनिस्टिक गणना है। फिर, सामान्य रूप से नोडेटर्मिनिज्म लेना, आप राज्य जोड़ते हैं - यानी नोडेटर्मिनिज्म की प्रत्येक "शाखा" का अपना राज्य होगा।ListT (StateT s m) a साथ

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

यहाँ दान Piponi द्वारा एक diagram जो कुछ उपयोगी अंतर्ज्ञान देता है:

monad doodles

मैं भी यह कार्यान्वयन प्रकार का विस्तार करने के लिए मददगार है, मुझे गणना किस तरह यह है के लिए एक महसूस देने के लिए । ListT विस्तार करना मुश्किल है, लेकिन आप इसे "nondeterminsm" के रूप में देख सकते हैं, और StateT विस्तार करना आसान है। तो उपरोक्त उदाहरण के लिए, मैं

StateT s (ListT m) a =~ s -> ListT m (a,s) 

आईई देखें। यह एक आने वाली स्थिति लेता है, और कई आउटगोइंग राज्य लौटाता है। यह आपको एक विचार देता है कि यह कैसे काम करेगा। एक समान दृष्टिकोण run फ़ंक्शन के प्रकार को देखने के लिए है जिसे आपको अपने ढेर के लिए जरूरी है - क्या यह आपके पास मौजूद जानकारी और आपके द्वारा की जाने वाली जानकारी से मेल खाता है?

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

ReaderT, WriterT, और StateT सबसे आम ट्रांसफॉर्मर हैं। सबसे पहले, वे सभी एक-दूसरे के साथ यात्रा करते हैं, इसलिए यह अप्रासंगिक है कि आप उन्हें किस क्रम में डालते हैं (यदि आप तीनों का उपयोग कर रहे हैं तो RWS का उपयोग करने पर विचार करें)। साथ ही, व्यावहारिक रूप से, मैं आमतौर पर इन्हें बाहरी पर चाहता हूं, "अमीर" ट्रांसफार्मर जैसे ListT, LogicT, और ContT अंदर।

ErrorT और MaybeT आमतौर पर उपरोक्त तीन के बाहर जाते हैं; कैसे MaybeTStateT साथ सूचना का आदान को देखो:

MaybeT (StateT s m) a =~ StateT s m (Maybe a) =~ s -> m (Maybe a, s) 
StateT s (MaybeT m) a =~ s -> MaybeT m (a,s) =~ s -> m (Maybe (a,s)) 

जब MaybeT बाहर की दुनिया में, एक राज्य परिवर्तन भले ही गणना में विफल रहता है मानने योग्य है। जब MaybeT अंदर है, यदि गणना विफल हो जाती है, तो आपको कोई राज्य नहीं मिलता है, इसलिए आपको असफल गणना में होने वाले किसी भी राज्य परिवर्तन को रोकना होगा। इनमें से कौन सा आप चाहते हैं उस पर निर्भर करता है कि आप क्या करने की कोशिश कर रहे हैं - पूर्व, हालांकि, अनिवार्य प्रोग्रामर के अंतर्ज्ञान से मेल खाता है। (ऐसा नहीं है कि इसके लिए कुछ आवश्यक है)

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

12

यह काफी एक व्यापक सवाल है। मैं आपको काम करने के लिए कुछ बुनियादी विचार देने जा रहा हूं।

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

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

यदि आप उपयोग कर रहे मोनैड ट्रांसफार्मर आदेश पर निर्भर नहीं हैं - उदा। ReaderT और WriterT के संयोजन के लिए इससे कोई फर्क नहीं पड़ता, मुझे विश्वास है - फिर इसे कान से चलाएं और अपने आवेदन के लिए जो भी अच्छा लगता है उसके साथ जाएं। यह पसंद की तरह है जो अनुभव के साथ आसान हो जाएगा।

¹: ListTControl.Monad.Trans से कुछ समस्याएं हैं, इसलिए मान लें कि यह ListT done right है।

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