2011-09-22 14 views
13

मैंने हाल ही में निम्नलिखित पैटर्न के साथ कोड लिखा है, और यह सोच रहा था कि इसे लिखने का एक छोटा रास्ता था या नहीं।क्या इस तरह का कोई कार्य पहले से मौजूद है? (या, इस फ़ंक्शन के लिए बेहतर नाम क्या है?)

foo :: IO String 
foo = do 
    x <- getLine 
    putStrLn x >> return x 

बातें एक छोटे से क्लीनर बनाने के लिए, मैं इस समारोह में लिखा था (हालांकि मुझे यकीन है कि नहीं कर रहा हूँ यह एक उपयुक्त नाम है):

constM :: (Monad m) => (a -> m b) -> a -> m a 
constM f a = f a >> return a 

मैं तो कर सकते हैं इस तरह foo:

foo = getLine >>= constM putStrLn 

क्या इस तरह का कोई फ़ंक्शन/मुहावरे पहले से मौजूद है? और यदि नहीं, तो मेरे कॉन्सएम के लिए बेहतर नाम क्या है?

+4

ऐसा लगता है कि आप सादे फ़ैक्टर का उपयोग करके इस फ़ंक्शन को परिभाषित कर सकते हैं: 'constF :: Functor f => (a -> f b) -> a -> f a; constF f a = a <$ f a' – fuz

+0

@FUZxxl, यह भी काम करता है, धन्यवाद ... क्या यह कॉन्स्ट नाम का सही उपयोग है? –

+0

आपका क्या मतलब है? – fuz

उत्तर

18

ठीक है, चलो इस तरह के विचारों को मानें कि को कुछ सरल बनाया जा सकता है। एक गैर-मोनैडिक संस्करण मुझे लगता है कि 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 (>>) 
बेशक

, liftA2liftM2 के बराबर है तो आप आश्चर्य हो सकता है अगर एक और इकाई में 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 होने के बाद, मैं वास्तव में संबंधित अवधारणाओं के बारे में ऊपर चर्चा से क्या ले सकते हैं से परे नामकरण पर अधिक मार्गदर्शन प्रदान नहीं कर सकता।

अंतिम तरफ के रूप में, ध्यान दें कि अभिव्यक्ति निष्पादित करने के बाद आपके कार्य का कोई नियंत्रण प्रवाह विकल्प नहीं है, चाहे मुख्य लक्ष्य क्या हो। पैरामीट्रिक सामग्री से स्वतंत्र एक कम्प्यूटेशनल संरचना (यानी, aMonad m => m a में सामग्री की सामग्री) आमतौर पर एक संकेत है कि आपको वास्तव में पूर्ण Monad की आवश्यकता नहीं है, और Applicative की अधिक सामान्य धारणा के साथ मिल सकती है।

+0

अपने प्रश्न का उत्तर नहीं। महान विश्लेषण के लिए वैसे भी +1। :-) – luqui

+0

@luqui: ठीक है, इसका उद्देश्य किसी चीज के सामान्यीकरण को खोजने के लिए अंतर्निहित संरचना की तलाश करने के बारे में एक तरह का स्पष्टीकरण होना था, यह देखते हुए कि * सटीक * फ़ंक्शन वर्णित नहीं है ... लेकिन हाँ, उस तरह से कहीं भी खो गया है। शायद इसे स्पष्ट करने के लिए किसी बिंदु पर इसे थोड़ा सा संशोधित करना चाहिए। –

0

वहाँ interact है:

http://hackage.haskell.org/packages/archive/haskell98/latest/doc/html/Prelude.html#v:interact

यह काफी आप जो चाह रहे हैं नहीं है, लेकिन यह समान है।

+2

वह भी परिणाम वापस करना चाहता है;' इंटरैक्ट 'कर सकते हैं' ऐसा मत करो। मुझे लगता है, वह सिर्फ एक साधारण उदाहरण से इच्छित कार्यक्षमता को समझा देना चाहता था।आपका जवाब बहुत उपयोगी नहीं है। – fuz

1

मैं वास्तव में एक सुराग यह वास्तव में allready मौजूद नहीं है, लेकिन आप केवल अलग-अलग नामों के साथ पार्सर जनरेटर में इस एक बहुत देखते हैं (उदाहरण के बात अंदर कोष्ठक पाने के लिए) - वहाँ यह normaly किसी तरह का है उदाहरण के लिए ऑपरेटर (>>. और .>> fparsec में) इसके लिए। वास्तव में एक नाम देने के लिए मैं इसे पर कॉल कर सकता हूं अनदेखा?

+1

मैंने लोगों को 'अनदेखा' नाम के लिए 'अनदेखा' नाम का उपयोग किया है :: मोनाड एम => एम ए -> एम() ', 'अनदेखा एम = एम >> वापसी()'। –

+0

@ जुडाह डू-स्टेटमेंट के परिणाम को हटाने के बारे में चेतावनी को कम करने के लिए? – fuz

+0

मुझे यकीन नहीं है कि अनदेखा सही है क्योंकि मुझे दिए गए मान को वापस करने की आवश्यकता है। –

3

हम्म, मुझे नहीं लगता कि constM यहां उचित है।

map :: (a -> b) -> [a] -> [b] 
mapM :: (Monad m) => (a -> m b) -> [a] -> m b 

const :: b -> a -> b 

तो शायद:

constM :: (Monad m) => b -> m a -> m b 
constM b m = m >> return b 

समारोह आप M -ing हो रहा है कर रहे हैं:

f :: (a -> b) -> a -> a 

कौन सा कोई विकल्प नहीं है, लेकिन इसके पहले तर्क को नजरअंदाज किया है। तो इस समारोह में पूरी तरह से कहने के लिए बहुत कुछ नहीं है।

मैं एक तरह से करने के लिए, हम्म, एक पक्ष प्रभाव साथ एक मूल्य के निरीक्षण के रूप में देखते। observe, effect, sideEffect सभ्य नाम हो सकते हैं। observe मेरा पसंदीदा है, लेकिन शायद इसलिए कि यह आकर्षक है, क्योंकि यह स्पष्ट नहीं है।

+0

मुझे लगता है कि मेरे नाम से स्पष्ट है, और मुझे लगता है कि इसके लिए शुद्ध 'एम' की आवश्यकता नहीं है क्योंकि इससे कोई शुद्ध अर्थ नहीं होगा। –

+0

मैं 'निरीक्षण' के बारे में संदिग्ध हूं। हम निश्चित रूप से फ़ंक्शन द्वारा उत्पादित मूल्य का पालन नहीं करते हैं, और चूंकि फ़ंक्शन को केवल 'आवेदक' की आवश्यकता होती है, इसलिए हम किसी भी दुष्प्रभाव को जरूरी नहीं देख पाएंगे। –

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