में स्पष्ट रिकर्सन से बचें निम्नलिखित सरल फ़ंक्शन एक दिए गए मोनैडिक फ़ंक्शन को तब तक लागू करता है जब तक कि यह कुछ भी हिट नहीं करता है, जिस बिंदु पर यह अंतिम गैर-कुछ भी मूल्य नहीं देता है। यह वही करता है जो मुझे चाहिए, और मैं समझता हूं कि यह कैसे काम करता है।हास्केल
lastJustM :: (Monad m) => (a -> m (Maybe a)) -> a -> m a
lastJustM g x = g x >>= maybe (return x) (lastJustM g)
हास्केल में मेरी स्वयं शिक्षा के हिस्से के रूप में मैं स्पष्ट प्रत्यावर्तन से बचने के लिए कोशिश कर रहा हूँ (या कम से कम कैसे समझ में) जब भी मैं कर सकते हैं। ऐसा लगता है कि इस मामले में एक साधारण गैर-स्पष्ट रूप से रिकर्सिव समाधान होना चाहिए, लेकिन मुझे इसे समझने में परेशानी हो रही है।
मुझे a monadic versiontakeWhile
की तरह कुछ नहीं चाहिए, क्योंकि यह सभी पूर्व-कुछ मूल्यों को इकट्ठा करने के लिए महंगा हो सकता है, और मुझे उनकी परवाह नहीं है।
मैंने हस्ताक्षर के लिए होगल की जांच की और कुछ भी दिखाई नहीं देता है। m (Maybe a)
बिट मुझे लगता है कि एक मोनैड ट्रांसफॉर्मर यहां उपयोगी हो सकता है, लेकिन मेरे पास वास्तव में अंतर्ज्ञान नहीं है जो मुझे विवरण (अभी तक) के साथ आने की आवश्यकता होगी।
शायद यह करने के लिए शर्मनाक रूप से आसान है या यह देखने में शर्मनाक रूप से आसान है कि यह क्यों नहीं किया जा सकता है या नहीं किया जाना चाहिए, लेकिन यह पहली बार नहीं होगा जब मैंने शैक्षणिक रणनीति के रूप में आत्म-शर्मिंदगी का उपयोग किया हो।
अद्यतन: मैं निश्चित रूप से बजाय Maybe
उपयोग करने का एक विधेय प्रदान कर सकता है: (a -> Bool) -> (a -> m a) -> a
की तरह कुछ (अंतिम मान जिसके लिए विधेय सच है लौटने) बस के रूप में अच्छी तरह से काम करेगा। मुझे जो दिलचस्पी है वह मानक संयोजकों का उपयोग करके स्पष्ट रिकर्सन के बिना संस्करण लिखने का एक तरीका है।
पृष्ठभूमि: यहाँ संदर्भ के लिए एक सरल काम कर उदाहरण है: मान लीजिए हम इकाई वर्ग में यादृच्छिक क्षेत्रों में रुचि रखते हैं, लेकिन हम केवल बाहर निकलने के बिंदु के बारे में परवाह।
randomStep :: (Floating a, Ord a, Random a) =>
a -> (a, a) -> State StdGen (Maybe (a, a))
randomStep s (x, y) = do
(a, gen') <- randomR (0, 2 * pi) <$> get
put gen'
let (x', y') = (x + s * cos a, y + s * sin a)
if x' < 0 || x' > 1 || y' < 0 || y' > 1
then return Nothing
else return $ Just (x', y')
कुछ evalState (lastJustM (randomStep 0.01) (0.5, 0.5)) <$> newStdGen
की तरह हमें एक नया डेटा बिंदु दे देंगे: हम निम्नलिखित कदम समारोह है।
'lastJustM = फिक्स (।। LiftM2 एपी ((>> =)) (फ्लिप (शायद वापसी))।।)'। (ठीक है मैंने 'पॉइंटफ्री 'के साथ धोखा दिया।) – kennytm
@ केनीटीएम: धन्यवाद! मैंने 'पॉइंटफ्री' को आजमाने की भी कोशिश नहीं की क्योंकि मुझे नहीं पता था कि यह इस तरह की चीज़ को संभालने में सक्षम होगा। अब मुझे यह पता लगाना है कि यह कैसे काम करता है। –
कुछ हद तक संयोजक दिए गए पॉइंटफ्री फॉर्म को * कुछ भी * कम करने के लिए एक एल्गोरिदम है; यह 'पॉइंटफ्री' का उपयोग करता है। बेशक, परिणाम उपयोगी हो सकता है या नहीं भी हो सकता है :) –