2017-12-31 188 views
7

fmap भी <$> है क्योंकि यह फ़ंक्शन एप्लिकेशन में फ़ंक्शन एप्लिकेशन ($) है।

(+5) $ (*10) $ 10  -- 105 
(+5) <$> (*10) <$> [1,2,3] -- [15,25,35] 

फिर मैंने सोचा, अच्छी तरह से अनुप्रयोगी functor श्रेणी में है कि समारोह आवेदन मामले <*> है में, और इस काम करना चाहिए:

[(+5), (+10)] <*> [(*10), (*100)] <*> [1,2,3] -- ERROR 
-- however: 
[(+5), (+10)] <*> ([(*10), (*100)] <*> [1,2,3]) -- [15,25,35,...] 

तो, <$> केवल बाहर काम करता है क्योंकि कार्यों के लिए fmap होने वाला postcomposition, तो (+5) <$> (*10)(+5) . (*10) बन जाता है जिसे तब [1,2,3] पर लागू किया जाता है।

हालांकि सभी एप्लिकेशन ऑपरेटरों (<<= शामिल) के लिए सहयोगीता छोड़ दी गई है, मुझे एक खराब डिजाइन पसंद की तरह लगता है, खासकर जब वे $ की समानता को पहचानते हैं जो पहले से ही सही-सहयोगी है। क्या इसके लिए कोई और कारण है?

+2

समारोह आवेदन स्वाभाविक बाईं है साहचर्य; एक बेहतर सवाल यह होगा कि '$' सही-सहयोगी क्यों है? – chepner

+1

इसके अलावा, 'fmap' फ़ंक्शन एप्लिकेशन के बजाय फ़ंक्शन * उठाने * के रूप में बेहतर विचार है। एक बार 'fmap' उठाए गए फ़ंक्शन को लौटाता है, इसे किसी अन्य फ़ंक्शन के समान ही लागू किया जाता है; कोई विशेष आवेदन की आवश्यकता नहीं है। – chepner

उत्तर

7

असल में, कारण शायद यह है कि यह एक प्राथमिकता स्तर साझा करने के लिए <$> और <*> की अनुमति देता है। हम निश्चित रूप से <*> बाएं साहचर्य तो

की तरह सामान
Prelude> foldr <$> [(+),(*)] <*> [0,1] <*> [[1,2,3], [4,5,6]] 
[6,15,7,16,0,0,6,120] 

काम करता है होना चाहते हैं, और यह भी <$> सही तरीका भले ही यह उच्च पूर्वता नहीं है व्यवहार करते हैं बनाता है। दरअसल कई <$> ऑपरेटर चेनिंग वास्तव में बाएं-सहयोगीता के साथ बहुत उपयोगी नहीं है।

हालांकि, यह सही-सहयोगी के साथ भी बहुत उपयोगी नहीं होगा। जैसा कि चेपर ने टिप्पणी की, यह वास्तव में थोड़ा मजाकिया है कि $ सही-सहयोगी है। बेशक, इस तरह

Prelude> sum $ map (+3) $ take 19 $ cycle [4..7] 
160 

लेकिन फिर रचनाओं लेखन, इस बस के रूप में अच्छी तरह से यकीनन अधिक सुरुचिपूर्ण रूप में लिखा जा सकता है की अनुमति देता है

Prelude> sum . map (+3) . take 19 . cycle $ [4..7] 
160 

(अधिक सुरुचिपूर्ण मैं कहता हूँ, यहाँ क्योंकि गणना श्रृंखला पार्स किया गया है अनिवार्य शैली “ के बजाय, एक कार्यात्मक पाइपलाइन के रूप में, यह करें, फिर ... ”)। मज़ेदार कानूनों के लिए धन्यवाद, यह <$> और . के साथ $ और . के साथ ही किया जा सकता है।

केवल कारण है कि आप एकाधिक $ शैली पसंद कर सकते हैं यह है कि यह, पाइप लाइन में इन्फ़िक्स भाव की अनुमति देता है शायद सबसे आम उदाहरण है लेंस अद्यतन (जो आमतौर पर फ़्लिप & के साथ लिखा जाता है, लेकिन सिद्धांत एक ही है):

Prelude Control.Lens> [4..7] & ix 1+~9 & ix 2*~8 
[4,14,48,7] 

यह काम करता है क्योंकि $ और & बहुत कम पूर्वता है, काफी किसी भी इन्फ़िक्स ऑपरेटर से कम है।यही कारण है कि ताकि आप

Prelude Control.Lens> ix 1+~9 <$> [[4..8], [5..9]] 

<interactive>:23:1: error: 
    Precedence parsing error 
     cannot mix ‘+~’ [infixr 4] and ‘<$>’ [infixl 4] in the same infix expression 

ऐसा नहीं कर सकते ऐसे मामले में <$> के लिए ऐसा नहीं है, तो आप जरूरत कुछ कोष्ठकों वैसे भी उपयोग करने के लिए, और फिर आप के साथ-साथ यह भी कम पूर्वता रचना ऑपरेटरों के साथ यह कर सकता है Control.Category से:

Prelude Control.Lens Control.Category> (ix 1+~9 >>> ix 2*~8) <$> [[4..8], [5..9]] 
[[4,14,48,7,8],[5,15,56,8,9]] 

या प्रत्येक अपडेटर के आसपास कोष्ठक के साथ:

Prelude Control.Lens> (ix 1+~9) . (ix 2*~8) <$> [[4..8], [5..9]] 
[[4,14,48,7,8],[5,15,56,8,9]] 
संबंधित मुद्दे