2015-10-20 8 views
10

"डुप्लिकेट"

किसी के बारे में बताएं Is this a case for foldM? को संभावित डुप्लिकेट के रूप में इंगित करें। अब, मेरी एक मजबूत राय है कि, दो प्रश्नों का उत्तर समान उत्तरों के साथ दिया जा सकता है, जो आवश्यक रूप से डुप्लीकेट नहीं हैं! "1 - 2 क्या है" और "i^2 क्या है" दोनों उपज "-1" उत्पन्न करते हैं, लेकिन नहीं, वे डुप्लिकेट प्रश्न नहीं हैं। मेरा प्रश्न (जो पहले से ही उत्तर दिया गया है) इस बारे में था "क्या कार्य iterateM हास्केल मानक पुस्तकालय में मौजूद है", "एक जंजीर मोनैड कार्रवाई को कैसे कार्यान्वित करें" नहीं।क्या हास्केल में "चेन" मोनैड फ़ंक्शन है?

सवाल

जब मैं कुछ परियोजनाओं लिखते हैं, मुझे लगने इस Combinator लेखन:

repeatM :: Monad m => Int -> (a -> m a) -> a -> m a 
repeatM 0 _ a = return a 
repeatM n f a = (repeatM (n-1) f) =<< f a 

यह सिर्फ एक monadic कार्रवाई n बार करता है, अगली कार्रवाई में पिछले परिणाम खिला। मैंने कुछ hoogle खोज और कुछ Google खोज की कोशिश की, और "मानक" हास्केल के साथ आने वाली कुछ भी नहीं मिली। क्या ऐसा औपचारिक कार्य है जिसे पूर्वनिर्धारित किया गया है?

+3

मुझे इसे किसी भी * सामान्य * पैकेज में भी नहीं मिला - लेकिन [Hayoo] (http://hayoo.fh-wedel.de/?query=Monad+m+%3D%3E+Int+-%3E+ % 28 ए + -% 3 ई + एम + एक% 2 9 + -% 3 ई + ए + -% 3 ई + एम + ए) कम से कम 2 स्थानों को जानता है - इस मामले में मैं * प्रतिलिपि * * अनुमान लगा सकता हूं (शायद 'चेनएम' बेहतर है हालांकि नाम - 'प्रतिकृति' * दिया गया है *) – Carsten

+2

क्या पिछले परिणाम में' प्रतिकृति एम' फ़ीड 'है? –

+0

नहीं, लेकिन अगर मैं दोहराना या दोहराना पढ़ता हूं तो मैं अलग-अलग चीजों पर विचार करता हूं (केवल इस कारण से) - यह वास्तव में नामकरण पर केवल एक टिप्पणी है - माफ करना अगर यह गलतफहमी – Carsten

उत्तर

10

आप foldM, उदा .:

import Control.Monad 

f a = do print a; return (a+2) 

repeatM n f a0 = foldM (\a _ -> f a) a0 [1..n] 

test = repeatM 5 f 3 
    -- output: 3 5 7 9 11 
+0

यह पर्याप्त है! तीन लाइनों –

9

कार्स्टन mentionedreplicate उपयोग कर सकते हैं, और कहा कि एक बुरा विचार नहीं है।

import Control.Monad 
repeatM n f = foldr (>=>) pure (replicate n f) 

इसके पीछे विचार यह है कि किसी भी इकाई m के लिए, प्रकार a -> m b के कार्यों m की Kleisli श्रेणी, पहचान तीर

pure :: a -> m a 

(भी return कहा जाता है)

और साथ फार्म है रचना ऑपरेटर

(<=<) :: (b -> m c) -> (a -> m b) -> a -> m c 
f <=< g = \a -> f =<< g a 

चूंकि वास्तव में a -> m a प्रकार के फ़ंक्शन से निपट रहे थे, हम वास्तव में क्लेस्ली श्रेणी के एक मोनोइड को देख रहे हैं, इसलिए हम इन तीरों के सूचियों को सूचीबद्ध करने के बारे में सोच सकते हैं।

ऊपर दिए गए कोड को की n की प्रतियों में, सामान्य रूप से पहचान के साथ समाप्त करने के लिए संरचना ऑपरेटर को फोल्ड किया गया है। रचना ऑपरेटर को फ़्लिप करना वास्तव में हमें दोहरी श्रेणी में डाल देता है; कई आम मोनैड के लिए, x >=> y >=> z >=> ww <=< z <=< y <=< x से अधिक कुशल है; चूंकि इस मामले में सभी तीर समान हैं, ऐसा लगता है कि हम भी हो सकते हैं। ध्यान दें कि आलसी राज्य मोनड और संभवतः पाठक मोनड के लिए, अप्रत्याशित <=< ऑपरेटर का उपयोग करना बेहतर हो सकता है; >=> आमतौर पर IO, ST s, और सामान्य सख्त स्थिति के लिए बेहतर होगा।

नोटिस: मैं कोई श्रेणी सिद्धांतवादी नहीं हूं, इसलिए ऊपर स्पष्टीकरण में त्रुटियां हो सकती हैं।

2

मुझे लगता है कि मैं अक्सर इस समारोह को चाहता हूं, मेरी इच्छा है कि इसका मानक नाम हो। हालांकि यह नाम repeatM नहीं होगा - यह एक अनंत दोहराव के लिए होगा, जैसे forever यदि यह अस्तित्व में था, तो अन्य पुस्तकालयों के साथ स्थिरता के लिए (और repeatM इस तरह के कुछ पुस्तकालयों में परिभाषित किया गया है)।

जैसा कि पहले से दिए गए उत्तरों से एक और परिप्रेक्ष्य है, मैं इंगित करता हूं कि (s -> m s) राज्य के प्रकार s के साथ एक राज्य मोनैड में एक क्रिया की तरह दिखता है।

वास्तव में, यह StateT s m() पर आइसोमोर्फिक है - एक ऐसी क्रिया जो कोई मूल्य नहीं देती है, क्योंकि यह जो काम करता है वह राज्य को बदलने के तरीके में encapsulated है। इस monad में, आप वास्तव में चाहता था कि समारोह replicateM है। आप इसे इस तरह से हैकेल में लिख सकते हैं, हालांकि यह शायद इसे सीधे लिखने से अधिक दिखता है।

पहले बराबर रूप है जो StateT उपयोगों के s -> m s कनवर्ट करते हैं, जोड़ने जानकारी से मुक्त (), liftM का उपयोग कर वापसी प्रकार पर एक समारोह मैप करने के लिए।

> :t \f -> liftM (\x -> ((),x)) . f 
\f -> liftM (\x -> ((),x)) . f :: Monad m => (a -> m t) -> a -> m ((), t) 

(fmap इस्तेमाल किया जा सकता था है, लेकिन इकाई बाधा यहाँ स्पष्ट लगता है, TupleSections इस्तेमाल किया जा सकता था अगर आप की तरह, यदि आप यह बस \f s -> do x <- f s; return ((),s) है पढ़ने के लिए अंकन आसान कर पाते हैं)।

अब इस सही प्रकार StateT साथ लपेट के लिए है:

> :t StateT . \f -> liftM (\x -> ((),x)) . f 
StateT . \f -> liftM (\x -> ((),x)) . f :: Monad m => (s -> m s) -> StateT s m() 

और फिर आप इसे दोहराने कर सकते हैं n बार, replicateM_ संस्करण का उपयोग कर, क्योंकि replicateM से लौटे सूची [()] दिलचस्प नहीं होगा:

:
> :t \n -> replicateM_ n . StateT . \f -> liftM (\x -> ((),x)) . f 
\n -> replicateM_ n . StateT . \f -> liftM (\x -> ((),x)) . f :: Monad m => Int -> (s -> m s) -> StateT s m() 

और अंत में आप execStateT का उपयोग वापस इकाई आप पर जाने के लिए कर सकते हैं मूल रूप से कार्य कर रहे थे

runNTimes :: Monad m => Int -> (s -> m s) -> s -> m s 
runNTimes n act = 
    execStateT . replicateM_ n . StateT . (\f -> liftM (\x -> ((),x)) . f) $ act 
+0

लिखने से बेहतर यह मेरे उत्तर के समान है। 'स्टेटटी' का monadic इंटरफ़ेस अधिक है, क्योंकि आप परिणामों को कभी नहीं देखते हैं। मान लें कि आप 'newtype StateM s m = stateM {runStateM :: s -> m s}' लेते हैं। फिर 'उदाहरण मोनाड एम => मोनॉयड (राज्य एम) जहां {mempty = शुद्ध; मैपेंड (स्टेटएम एफ) (स्टेटएम जी) = स्टेटएम (एफ> => जी)} '। अब आप 's -> m s' कार्यों का एक समूह स्ट्रिंग करने के लिए 'FoldMap StateM' कर सकते हैं! – dfeuer

+2

बिल्कुल। हर जगह मोनोइड्स हैं। 'एफ()' '>>' के तहत एक मोनोइड है,> एस एस> '> =>' के तहत एक मोनोइड है, और इसी तरह। मेरे उत्तर का बिंदु बस मानक लाइब्रेरी फ़ंक्शन 'प्रतिकृति एम' को प्रश्न से संबंधित था क्योंकि पहली नज़र में यह लागू प्रतीत होता है, और फिर यह नहीं है। अवलोकन "ठीक है, यह' replicateM' है - बस थोड़ा अलग मोनाड के लिए "। – drquicksilver

+0

हां, यह समझ में आता है। – dfeuer

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