2014-09-24 10 views
19

मैं <$> के प्रकार हस्ताक्षर के पीछे तर्क को समझता हूं, क्योंकि यह fmap का सिर्फ एक इंफिक्स संस्करण है, लेकिन इसे >>= के प्रकार हस्ताक्षर से तुलना करने से यह मुझे बहुत कम समझ में आता है।

आइए पहले स्थापित करें कि मेरा क्या मतलब है।

(>>=) :: Monad m => m a -> (a -> m b) -> m b 
(<*>) :: Applicative f => f (a -> b) -> f a -> f b 
(<$>) :: Functor f => (a -> b) -> f a -> f b 

प्रकार हस्ताक्षर को देखते हुए हम देख सकते हैं कि >>= बाईं तरफ एक मूल्य लेता है, और सही है, जो भावना है, तो आप अपने चेनिंग संपत्ति पर विचार का एक बहुत बनाता है पर एक समारोह: foo >>= bar >>= baz

कौन सा मुझे आश्चर्य होता है, <*> और <$> क्यों नहीं करते? आप foo <*> bar <*> baz नहीं लिख सकते हैं क्योंकि इसे एक कार्य होने के लिए foo <*> bar के आउटपुट की आवश्यकता होगी, न कि मूल्य।

मुझे पता है कि <**> और =<< मौजूद है कि दोनों मापदंडों के आदेश फ्लिप, मेरे जैसे कुछ करने के लिए अनुमति देता है:

Just 4 <$$> (+3) <$$> (*2) >>= (\x -> Just (x-3)) 

हैं:

Just 4 <**> pure (+3) <**> pure (*2) >>= (\x -> Just (x-3)) 

कौन सा खूबसूरती से करने के लिए कम किया जा सकता था <$$> अस्तित्व में था, या <$> और <*> के पैरामीटर आदेश को उलट दिया गया था।

एक और चीज जो मुझे आश्चर्य करती है कि अंतर क्यों मौजूद है, यह है कि यह नवागंतुकों के लिए उपयोग करने के लिए कठिन होता है और/या याद करता है कि यह कार्य है, या जो मूल्य पहले आता है, इसे देखने के बिना।

तो इसे क्यों है कि <*> और <$> के मामलों में यह fn op val है, लेकिन >>= साथ यह val op fn है?

+4

लेकिन आप अक्सर 'Applicatives' के साथ इस वास्तव में चाहते हैं : उदाहरण के लिए '(+) <$> बस 5 <*> बस 5 ' <- वह 'बस' सुंदर नहीं है;) – Carsten

+2

'(>> =) 'चेन" अनिवार्य शैली "बनाता है (अन्यथा हम सोचते रहेंगे क्यों यह नहीं है '$' के समान आदेश)। '(<= <) 'चेनिंग -" '(।)' शैली" भी अनुमति देता है। '(<*>) 'बहु-तर्क कार्यों" लागू करने "के लिए उपयोगी है - घोषणा के क्रम में तर्क प्रदान करना। –

+2

असली सवाल यह है कि क्यों '(>> =)' हास्केल में काफी कुछ सबकुछ के विपरीत एक ऑर्डर का उपयोग कर रहा है। '(= <<) का प्रकार :: मोनाड एम => (ए -> एमबी) -> (एम -> एमबी) '' (>> =) = फ्लिप की तुलना में हास्केल में बाकी सब कुछ जैसा दिखता है (= <<) '। –

उत्तर

18

"इस आदेश में पैरामीटर क्यों लेता है" का जवाब मूल रूप से "कारण" है। जो भी इन कार्यों को परिभाषित करता है, वह सोचा कि सबसे अच्छा तरीका था। (और यह शायद प्रत्येक मामले में एक ही व्यक्ति नहीं था।) हालांकि, मैं कुछ उदाहरण प्रदान करता हूं:

मान लीजिए कि हमारे पास किसी प्रकार का पार्सिंग मोनड है।यह भी मान लीजिए कि हम

data Foobar = Foobar X Y Z 

parseFoo :: Parser X 
parseBar :: Parser Y 
parseBaz :: Parser Z 

परिभाषित किया है तो हम

parseFoobar :: Parser Foobar 
parseFoobar = do 
    foo <- parseFoo 
    bar <- parseBar 
    baz <- parseBaz 
    return (Foobar foo bar baz) 

लिख सकते हैं या, स्पष्ट रूप से,

parseFoobar = 
    parseFoo >>= \ foo -> 
    parseBar >>= \ bar -> 
    parseBaz >>= \ baz -> 
    return (Foobar foo bar baz) 

आइए अब कि अनुप्रयोगी शैली लिखें:

parseFoobar = return Foobar <*> parseFoo <*> parseBar <*> parseBaz 

या, वैकल्पिक रूप से,

parseFoobar = Foobar <$> parseFoo <*> parseBar <*> parseBaz 

अगर हम मान लें कि <**> = flip <*> मौजूद है (और सही संबद्धता है), तो हम

parseFoobar = parseBaz <**> parseBar <**> parseFoo <**> return Foobar 

सिर्फ अजीब लग यही कारण है कि है। अंत में समारोह के साथ, और विपरीत क्रम में तर्क? आप इसे इस तरह क्यों लिखना चाहते हैं? (ध्यान दें कि किसी भी प्रभाव भी रिवर्स ऑर्डर में हैं।)

monadic संस्करण में, प्रभाव शीर्ष से नीचे होते हैं। आवेदक संस्करण में, प्रभाव बाएं से दाएं होते हैं। ऐसा लगता है कि "प्राकृतिक"।

+0

क्या आप उदाहरण कार्यों में कुछ उदाहरण प्रकार जोड़ सकते हैं? बस इतना है कि मेरे सिर को लपेटने में आसान समय है –

+0

में थोड़ी सी चीजें संपादित की गईं। – MathematicalOrchid

+0

यह कार्य श्रृंखला के मामले में कैसे काम करता है? आप यहां क्या कर रहे हैं 3 फ़ंक्शन वाले मानों पर एक फ़ंक्शन लागू कर रहा है, लेकिन 'बस 4 >> = foo >> = bar >> = baz',' (+) <$> से काफी अलग तरीके से काम करता है बस 3 <*> बस 4' –

22

मोनाद यहां रास्ते में न आने दें। आवेदन के बारे में सोचें।

की तुलना करें:

(<$>) :: Functor f => (a -> b) -> f a -> f b 

और

($) :: (a -> b) -> a -> b 

आप देख सकते हैं एक functor के तहत नियमित रूप से आवेदन और आवेदन के बीच एक संबंध है।

सामान्य ज्ञान: वहाँ proposals किया गया है ताकि हम लिख सकते हैं खाली स्थान के (आवेदन) ओवरलोड कोष्ठक का उपयोग करें:

(| f a1 .. an |) 
बजाय

pure f <*> a1 <*> .. <*> an 
+4

मैंने इसे कभी नहीं देखा, मैंने केवल '<$>' 'fmap' के संदर्भ में देखा, अब आपने इसे' $ 'के रूप में प्रस्तुत किया है, यह बहुत अधिक समझ में आता है –

+1

मुझे लगता है कि यह स्वीकार किया जाना चाहिए का जवाब! –

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