2010-11-30 10 views
7

मान लें कि हम Maybe मोनैड पर उपयोग करना चाहते हैं, और फिर हम सूची में एक लुकअप करना चाहते हैं।क्या एक मोनाड ट्रांसफॉर्मर में फ़ंक्शन लपेटना चाहिए/क्या खराब अभ्यास माना जाना चाहिए?

अब इस के लिए एक आसान, और भी असामान्य नहीं तरीका है:

पहली संभावना

find a = ReaderT (lookup a) 

हालांकि यह इस तरह प्रतीत होता है कि कैसे ReaderT ट्रांसफार्मर काम करता है के बारे में कुछ गैर तुच्छ बात का दावा । Control.Monad.Reader के लिए स्रोत कोड को देखते हुए यह स्पष्ट है कि यह ठीक काम करता है। लेकिन मैंने इसका समर्थन करने वाले किसी दस्तावेज़ को नहीं पढ़ा है। हालांकि हम भी इस तरह लगता है लिख सकते हैं:

दूसरी संभावना

find a = do y <- ask 
      lift (lookup a y) 

इसी प्रकार के विचारों MaybeT, StateT, State और Reader लपेटकर के लिए पकड़। आम तौर पर मैं पहले उदाहरण की तरह कुछ लिखता हूं, लेकिन अधिकांश समय यह वास्तव में स्पष्ट है कि इसे दूसरे उदाहरण की तरह कैसे लिखना है, और आप यह भी कह सकते हैं कि यह अधिक पठनीय है। तो मेरा सवाल है: क्या पहले उदाहरण की तरह कोड को बुरा माना जाना चाहिए?

+2

आप 'ए = लिफ्ट' भी लिख सकते हैं। लुकअप ए = << पूछें ', जो कि दूसरे विकल्प के रूप में स्पष्ट (IMHO) है, लेकिन छोटा है। –

+0

या fmap का उपयोग करें: एक = fmap (लुकअप ए) पूछें = लुकअप <$> – urso

+0

पूछें कि यह निर्माता है कि उन्होंने कन्स्ट्रक्टर – fuz

उत्तर

3

MTL पुस्तकालय के वर्तमान संस्करण - जो ट्रांसफार्मर पुस्तकालय पर आधारित है - जब सरल Reader इकाई का उपयोग कर वास्तव में इस उद्देश्य के लिए समारोह reader :: (r -> a) -> Reader r a निर्यात करता है। इसलिए हम देखते हैं कि लाइब्रेरी का डिज़ाइन इस उपयोग को ध्यान में रखता है। चूंकि ReaderT के लिए ऐसा कोई फ़ंक्शन प्रदान नहीं किया गया है, इसलिए हम कुछ विश्वास के साथ कह सकते हैं कि ReaderT के साथ ऐसा करने का आधिकारिक रूप से समर्थित तरीका सीधे निर्माता का उपयोग करना है।

यदि आप कहते हैं कि एक समान readerT :: Monad m => (r -> a) -> ReaderT r m a लाइब्रेरी में जोड़ा जाना चाहिए तो मैं आपसे सहमत हूं।यह स्थिरता के लिए दोनों अच्छा होगा, और किसी के कोड को तोड़ने के बिना किसी दिन आंतरिक प्रतिनिधित्व को बदलने की संभावना को अनुमति देने के लिए।

लेकिन अभी के लिए, आपकी "पहली संभावना" जाने का रास्ता है।

9

मुझे लगता है कि पहला रास्ता साथ सबसे बड़ी समस्या यह है: MTL लेखकों (या जो भी ट्रांसफार्मर पुस्तकालय आप का उपयोग करें), ReaderT के लिए डेटा निर्माता निर्यात बंद करने का फैसला

तो यह काम करना बंद कर देगा। यह एमटीएल 1 से एमटीएल 2 के संस्करण बंप में राज्य मोनड के साथ हुआ और यह काफी परेशान है। जबकि, ask रीडर के आधिकारिक एपीआई का हिस्सा है और आपको इसके आसपास चिपकने की योजना बनाना चाहिए।

दूसरी तरफ, मैं पहली बार गलत नहीं मानूंगा।

+0

राज्य मोनैड अभी भी निर्माता के साथ उपलब्ध है। मुझे लगता है कि आपका मतलब 'एसटी'-मोनड है। – fuz

+2

यदि आप यहां देखें: http://hackage.haskell.org/packages/archive/mtl/2.0.1.0/doc/html/src/Control-Monad-State-Lazy.html आप देखेंगे कि राज्य के लिए डेटा कन्स्ट्रक्टर अब निर्यात नहीं किया गया है। यह सच है कि आप इस के आसपास काम करने के लिए बहुत सी चीजें कर सकते हैं। –

3

कम से कम एक गति अंतर है।

मैंने program लिखा, जो एक राज्य के रूप में एक यादृच्छिक जीन का उपयोग करता है और चलते समय लगभग 5000000 यादृच्छिक मूल्य उत्पन्न करना चाहिए। अब इन दो काम करता है, जो एक पासा रोल पर विचार करें:

random16 = State $ randomR (1,6) -- Using the internal representation 
random16' = do 
      s <- get 
      (r,s') <- randomR (1,6) s 
      put s' 
      return r 

पहले एक Whith, कार्यक्रम, के बारे में 6 सेकंड में चलाता है, जबकि दूसरा एक बहुत धीमी है, के बारे में 8 सेकंड ले रही है। मैं छवि कर सकता हूं, यह पाठक के लिए समान है, इसलिए रनटाइम महत्वपूर्ण होने पर शायद अधिक स्पष्ट होने के बजाय इसका उपयोग करें। मैंने इसके लिए सख्त संस्करण का इस्तेमाल किया।