ठीक है, चलो इस तरह के विचारों को मानें कि को कुछ सरल बनाया जा सकता है। एक गैर-मोनैडिक संस्करण मुझे लगता है कि const' f a = const a (f a)
जैसा कुछ दिखता है, जो कि अधिक विशिष्ट प्रकार के साथ flip const
के बराबर है। मोनैडिक संस्करण के साथ, हालांकि, f a
का नतीजा मस्तिष्क की गैर-पैरामीट्रिक संरचना (यानी, जिसे अक्सर "साइड इफेक्ट्स" कहा जाता है) के मनमाना चीजें कर सकते हैं, जिसमें a
के मूल्य पर निर्भर चीजें शामिल हैं। यह हमें क्या बताता है कि, का नाटक करने के बावजूद हम f a
के परिणाम को छोड़ रहे हैं, हम वास्तव में इस तरह के कुछ भी नहीं कर रहे हैं। a
फ़ंक्शन के पैरामीट्रिक भाग के रूप में अपरिवर्तित बहुत कम आवश्यक है, और हम return
को किसी और चीज़ के साथ प्रतिस्थापित कर सकते हैं और अभी भी एक अवधारणात्मक समान कार्य है।
doBoth :: (Monad m) => (a -> m b) -> (a -> m c) -> a -> m c
doBoth f g a = f a >> g a
यहाँ से, दो अलग अलग तरीकों का एक अंतर्निहित संरचना देखने के लिए देखते हैं:
तो पहली बात हम निष्कर्ष निकाल सकते हैं कि यह की तरह निम्नलिखित एक समारोह का एक विशेष मामले के रूप में देखा जा सकता है किसी प्रकार।
एक परिप्रेक्ष्य बंटवारे कई कार्यों में एक भी तर्क के पैटर्न पहचान करने के लिए, तो परिणाम पुनर्संयोजन है। इस अवधारणा को कार्यों के लिए Applicative
/Monad
उदाहरणों द्वारा सन्निहित है, इसलिए की तरह है:
doBoth :: (Monad m) => (a -> m b) -> (a -> m c) -> a -> m c
doBoth f g = (>>) <$> f <*> g
...या, यदि आप पसंद:
doBoth :: (Monad m) => (a -> m b) -> (a -> m c) -> a -> m c
doBoth = liftA2 (>>)
बेशक
, liftA2
liftM2
के बराबर है तो आप आश्चर्य हो सकता है अगर एक और इकाई में monads पर एक आपरेशन उठाने इकाई ट्रांसफार्मर के साथ कुछ है; सामान्य रिश्ते में वहाँ अजीब है, लेकिन इस मामले में यह आसानी से काम करता है, कुछ इस तरह दे रही है:
doBoth :: (Monad m) => ReaderT a m b -> ReaderT a m c -> ReaderT a m c
doBoth = (>>)
... सापेक्ष उचित रैपिंग और इस तरह, बिल्कुल। अपने मूल संस्करण पर वापस जाने के लिए, return
का मूल उपयोग अब ReaderT a m a
के साथ कुछ होना चाहिए, जो पाठक monads के लिए ask
फ़ंक्शन के रूप में पहचानना बहुत कठिन नहीं होना चाहिए।
अन्य परिप्रेक्ष्य पहचान करने के लिए कि (Monad m) => a -> m b
तरह प्रकार के साथ काम करता है सीधे बना जा सकता है, बहुत शुद्ध कार्यों की तरह है। फ़ंक्शन (<=<) :: Monad m => (b -> m c) -> (a -> m b) -> (a -> m c)
फ़ंक्शन संरचना (.) :: (b -> c) -> (a -> b) -> (a -> c)
के लिए सीधे समतुल्य प्रदान करता है, या इसके बजाय आप सामान्य रूप से एक ही चीज़ के साथ काम करने के लिए Control.Category
और newtype
wrapper Kleisli
का उपयोग कर सकते हैं।
हमें अभी भी तर्क को विभाजित करने की आवश्यकता है, इसलिए, हमें वास्तव में यहां "शाखाकरण" संरचना की आवश्यकता है, जो Category
अकेले नहीं है; साथ ही हम (&&&)
मिल Control.Arrow
उपयोग करते हुए, हमें बताने समारोह इस प्रकार पुनर्लेखन द्वारा:
doBoth :: (Monad m) => Kleisli m a b -> Kleisli m a c -> Kleisli m a (b, c)
doBoth f g = f &&& g
जब से हम पहले Kleisli तीर का परिणाम के बारे में परवाह नहीं है, केवल अपने साइड इफेक्ट है, हम में से आधे त्यागने कर सकते हैं स्पष्ट तरीके से tuple:
doBoth :: (Monad m) => Kleisli m a b -> Kleisli m a c -> Kleisli m a c
doBoth f g = f &&& g >>> arr snd
जो हमें सामान्य रूप में वापस ले जाता है। अपने मूल करने के लिए विशेषज्ञता, return
अब बस id
हो जाता है:
constKleisli :: (Monad m) => Kleisli m a b -> Kleisli m a a
constKleisli f = f &&& id >>> arr snd
के बाद से नियमित रूप से कार्य भी कर रहे हैं Arrow
रों, परिभाषा से ऊपर के साथ-साथ वहाँ काम करता है अगर तुम प्रकार हस्ताक्षर सामान्यीकरण। हालांकि, यह परिभाषा है कि शुद्ध कार्यों के लिए परिणाम का विस्तार और सरल करने के लिए इस प्रकार शिक्षाप्रद हो सकता है:
\f x -> (f &&& id >>> arr snd) x
\f x -> (snd . (\y -> (f y, id y))) x
\f x -> (\y -> snd (f y, y)) x
\f x -> (\y -> y) x
\f x -> x
।
तो हम उम्मीद कर रहे हैं flip const
पर वापस आ गए हैं!
संक्षेप में, अपने कार्य या तो (>>)
या flip const
पर कुछ बदलाव है, लेकिन एक तरीका है कि मतभेद पर निर्भर करता है में - पूर्व दोनों एक ReaderT
पर्यावरण और अंतर्निहित इकाई की (>>)
का उपयोग कर, बाद का उपयोग कर विशिष्ट Arrow
के अंतर्निहित दुष्प्रभाव और Arrow
साइड इफेक्ट्स एक विशेष क्रम में होने वाली अपेक्षाओं की अपेक्षा करते हैं। इन विवरणों के कारण, कोई सामान्यीकरण या सरलीकरण उपलब्ध होने की संभावना नहीं है। कुछ अर्थों में, आप जिस परिभाषा का उपयोग कर रहे हैं वह बिल्कुल उतना आसान है जितना इसे होना चाहिए, यही कारण है कि मैंने दी गई वैकल्पिक परिभाषाएं लंबी हैं और/या रैपिंग और अनैपिंग की कुछ मात्रा शामिल हैं।
इस तरह का एक कार्य किसी प्रकार की "मोनड यूटिलिटी लाइब्रेरी" का प्राकृतिक जोड़ होगा। जबकि Control.Monad
उन लाइनों के साथ कुछ संयोजक प्रदान करता है, यह पूर्ण से बहुत दूर है, और मैं मानक पुस्तकालयों में इस फ़ंक्शन पर न तो कोई भी बदलाव ढूंढ सकता हूं और न ही याद कर सकता हूं। हालांकि, हैक पर एक या अधिक उपयोगिता पुस्तकालयों में इसे खोजने के लिए मुझे आश्चर्य नहीं होगा।
अधिकांशतः अस्तित्व के प्रश्न के साथ dispensed होने के बाद, मैं वास्तव में संबंधित अवधारणाओं के बारे में ऊपर चर्चा से क्या ले सकते हैं से परे नामकरण पर अधिक मार्गदर्शन प्रदान नहीं कर सकता।
अंतिम तरफ के रूप में, ध्यान दें कि अभिव्यक्ति निष्पादित करने के बाद आपके कार्य का कोई नियंत्रण प्रवाह विकल्प नहीं है, चाहे मुख्य लक्ष्य क्या हो। पैरामीट्रिक सामग्री से स्वतंत्र एक कम्प्यूटेशनल संरचना (यानी, a
Monad m => m a
में सामग्री की सामग्री) आमतौर पर एक संकेत है कि आपको वास्तव में पूर्ण Monad
की आवश्यकता नहीं है, और Applicative
की अधिक सामान्य धारणा के साथ मिल सकती है।
ऐसा लगता है कि आप सादे फ़ैक्टर का उपयोग करके इस फ़ंक्शन को परिभाषित कर सकते हैं: 'constF :: Functor f => (a -> f b) -> a -> f a; constF f a = a <$ f a' – fuz
@FUZxxl, यह भी काम करता है, धन्यवाद ... क्या यह कॉन्स्ट नाम का सही उपयोग है? –
आपका क्या मतलब है? – fuz