2012-03-14 20 views
7

मैं एक गणना के लिए एक इकाई है कि असफल और कुछ प्रवेश करता है हो सकता है:केवल इकाई ट्रांसफार्मर में बाहरी इकाई अपडेट कर रहा है

f1 :: WriterT [String] (Either String) a 

मैं एक समारोह है कि असफल नहीं हो लेकिन कुछ प्रवेश करता है:

f2 :: Writer [String] b 

f2 से लॉग का उपयोग करके f1 में लेखक मोनैड को अपडेट करने का सबसे अच्छा तरीका क्या है, और f2 गणना के आउटपुट को कैप्चर करें? फिलहाल मैं यह कर रहा हूँ:

f2result <- (\(r,l) -> do {tell l; return r}) (runWriter f2) 

मैं लिफ्ट का उपयोग कर रहा एक अलग गणना के साथ आंतरिक इकाई अद्यतन करने के लिए है, तो लेखक के आसपास स्विचन और या तो monads समस्या का समाधान नहीं होगा।

+0

धन्यवाद danr और rampion:

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

उत्तर

4

आप f2, सबसे आसान संभव दृष्टिकोण f2 refactor करने के लिए हो सकता है परिभाषित यदि ऐसा है तो यह thusly परिभाषित किया है:

f2 :: Monad m => WriterT [String] m b 

कौन सा बहुत कठिन नहीं होना चाहिए, के बाद से Writer w bWriterT w Identity b के रूप में परिभाषित किया गया है, और Identity इकाई नहीं करता है आपको कुछ नहीं देना

फिर आप f1 >> f2 करके उन्हें चेन करने में सक्षम होंगे।

आप f2 को फिर से परिभाषित नहीं कर सकते, तो आप हमेशा अपनी खुद की उचित हस्ताक्षर के साथ निर्धारित कर सकते हैं:

f2' :: Monad m => WriterT [String] m b 
f2' = WriterT . return $ runWriter f2 

और अगर आप f2 का एक समूह है रैप करने के लिए, आप हमेशा रैप करने के लिए एक समारोह निर्धारित कर सकते हैं उन्हें आप

wrap :: Monad m => Writer w b -> WriterT w m b 
wrap = WriterT . return . runWriter 

तो तुम f1 >> wrap f2a >> wrap f2b >> wrap f2c ...

4

कर सकते हैं के लिए एक rampion के जवाब पर नजर रखने, आप के बजाय रेफरी के रूप में कर सकते हैं किसी भी MonadWriter पर अभिनेता f2 :

f2 :: MonadWriter [String] m => m a 

चाहिए नहीं में अपनी परिभाषा को बदलने के लिए संभव हो सकता है आप लपेट कर सकते हैं rampion करता है इसी तरह के रूप में:

f2' :: MonadWriter [String] m => m a 
f2' = do let (a,w) = runWriter f2 
     tell w 
     return a 

MonadWriter को [String] तर्क यह GHC pragma की आवश्यकता है:

{-# LANGUAGE FlexibleContexts #-} 

हमेशा के रूप में, pragmas ar ई मॉड्यूल के शीर्ष पर डाल दिया। आपकी प्रतिक्रियाओं के लिए

wrap :: MonadWriter w m => Writer w b -> m b 
wrap = uncurry (<<) . (return *** tell) . runWriter 
    where (<<) = flip (>>) 
+1

और रैपर 'रैप बन जाता है :: MonadWriter w m => लेखक w बी -> एम बी; लपेटें = uncurry (<<)। (वापसी *** बताओ)। runWriter जहां (<<) = flip (>>) ' – rampion

+0

@ रैंपियन: अच्छा!मैं पॉइंट फ्री शैली की सराहना कर सकता हूं;) – danr

+0

ठीक है, मुझे पारस्परिक प्रशंसा समाज में शामिल होने दें, और कहें कि मैं मोनाडवाइटर टाइपक्लास के सामान्यीकरण की सराहना कर सकता हूं :) – rampion