दिलचस्प पोस्ट
PostgreSQL क्लाइंट लायब्रेरी (लिब्पीक) नहीं मिल सकता पायथन में अनुक्रम से आइटम निकालने का शानदार तरीका? OSX पर स्विंग: कमांड-क्यू ट्रैप कैसे करें? सहायता लाइब्रेरी का उपयोग करके तरंग एनीमेशन कैसे प्राप्त करें? क्या यह निर्धारित करने का एक तरीका है कि WPF बाइंडिंग कहां / घोषित किया गया है? पायसीन 3 प्रिंट () फ़ारसी / अरबी वर्णों के साथ फ़ंक्शन ड्राय-एचडीपीआई, ड्रॉएबल-एमडीपीआई, ड्रॉएबल-एलडीपीआई एंड्रॉइड पदावनत: फ़ंक्शन विभाजन () को बहिष्कृत किया गया है कैसे इस कथन को फिर से लिखना है? भारतीय नंबरिंग प्रारूप में मुद्रा प्रदर्शित htmlagilitypack – स्क्रिप्ट और शैली निकालें? Android sqlite कैसे एक रिकॉर्ड मौजूद है कि कैसे जांच करने के लिए अगर चेकबॉक्स चेक किया जाता है तो jQuery फायरबसे प्रदर्शन: कितने बच्चे प्रति नोड हैं? .NET मेमोरी प्रोफाइलिंग उपकरण पोस्टग्रेज़ में मौजूदा कॉलम में 'सीरियल' जोड़ना

फ़ंक्शन संयोजन रचना: कैसे करता है (।)। (।) काम करते हो?

(.) दो कार्य करता है जो एक मान लेता है और एक मान वापस करता है:

 (.) :: (b -> c) -> (a -> b) -> a -> c 

चूंकि (.) दो तर्क लेता है, मुझे लगता है (.).(.) अमान्य होना चाहिए, लेकिन यह बिल्कुल ठीक है:

 (.).(.) :: (b -> c) -> (a -> a1 -> b) -> a -> a1 -> c 

यहाँ क्या हो रहा है? मुझे यह एहसास है कि इस सवाल का बुरी तरह से इस्तेमाल किया गया है … सभी फ़ंक्शन वास्तव में सिर्फ एक तर्क लेते हैं, ताकि कतरने के लिए धन्यवाद। शायद यह कहने का एक बेहतर तरीका है कि प्रकार मेल नहीं खाते।

Solutions Collecting From Web of "फ़ंक्शन संयोजन रचना: कैसे करता है (।)। (।) काम करते हो?"

मैकेनिकल सबूत के लिए सबसे पहले टाइप -केक्कर खेलते हैं। इसके बाद मैं उसके बारे में सोचने का एक सहज ज्ञान युक्त तरीका बताता हूं।

मैं (.) से (.) को लागू करना चाहता हूं और फिर मैं परिणाम पर (.) आवेदन करूँगा पहला अनुप्रयोग हमें चर के कुछ समीकरणों को परिभाषित करने में मदद करता है।

 ((.) :: (b -> c) -> (a -> b) -> a -> c) ((.) :: (b' -> c') -> (a' -> b') -> a' -> c') ((.) :: (b'' -> c'') -> (a'' -> b'') -> a'' -> c'') let b = (b' -> c') c = (a' -> b') -> a' -> c' ((.) (.) :: (a -> b) -> a -> c) ((.) :: (b'' -> c'') -> (a'' -> b'') -> a'' -> c'') 

तो हम दूसरी शुरुआत करते हैं, लेकिन जल्दी से अटक जाते हैं …

 let a = (b'' -> c'') 

यह महत्वपूर्ण है: हम let b = (a'' -> b'') -> a'' -> c'' , लेकिन हमने पहले से ही परिभाषित किया है, इसलिए हमें एकजुट करने की कोशिश करनी चाहिए- मिलान करने के लिए हमारी सबसे अच्छी परिभाषाएं हम कर सकते हैं सौभाग्य से, वे मैच करते हैं

 UNIFY b = (b' -> c') =:= (a'' -> b'') -> a'' -> c'' which implies b' = a'' -> b'' c' = a'' -> c'' 

और उन परिभाषाओं / अधिसूचनाओं के साथ हम आवेदन को जारी रख सकते हैं

 ((.) (.) (.) :: (b'' -> c'') -> (a' -> b') -> (a' -> c')) 

फिर विस्तार करें

 ((.) (.) (.) :: (b'' -> c'') -> (a' -> a'' -> b'') -> (a' -> a'' -> c'')) 

और इसे साफ करो

 substitute b'' -> b c'' -> c a' -> a a'' -> a1 (.).(.) :: (b -> c) -> (a -> a1 -> b) -> (a -> a1 -> c) 

जो, ईमानदार होना, एक प्रतिरोधक परिणाम का एक सा है।


यहाँ अंतर्ज्ञान है सबसे पहले fmap पर एक नज़र fmap

 fmap :: (a -> b) -> (fa -> fb) 

यह एक फ़ंक्शन को एक Functor में "लिफ्टों" देता है हम बार-बार इसे लागू कर सकते हैं

 fmap.fmap.fmap :: (Functor f, Functor g, Functor h) => (a -> b) -> (f (g (ha)) -> f (g (hb))) 

हमें Functors गहरे और गहरे परतों में Functors को Functors की Functors

यह पता चला है कि डेटा प्रकार (r ->) एक Functor

 instance Functor ((->) r) where fmap = (.) 

जो बहुत परिचित दिखना चाहिए इसका अर्थ है कि fmap.fmap अनुवाद (.).(.) । इस प्रकार, (.).(.) सिर्फ हमें (r ->) Functor के गहरे और गहरे परतों के पैरामीट्रिक प्रकार को परिवर्तित करने दे रहा है। (r ->) Functor वास्तव में Reader Monad , इसलिए स्तरित Reader एस कई स्वतंत्र प्रकार के वैश्विक, अपरिवर्तनीय राज्य होने की तरह है।

या कई इनपुट आर्गुमेंट्स होने की तरह जो fmap आईएनजी से प्रभावित नहीं हैं। एक (1) arity फ़ंक्शन के "सिर्फ परिणाम" पर एक नया निरंतरता फ़ंक्शन बनाने की तरह तरह।


यह अंततः ध्यान देने योग्य है कि यदि आपको लगता है कि यह सामान दिलचस्प है, तो यह नियंत्रण में लेंस लाने के पीछे मुख्य अंतर्ज्ञान है। लेन्स

चलो एक पल के लिए प्रकारों की उपेक्षा करते हैं और सिर्फ लैम्ब्डा कैलकुस का उपयोग करते हैं।

  • देउगेर इन्फिक्स नोटेशन:
    (.) (.) (.)

  • एटा-विस्तार:
    (\ ab -> (.) ab) (\ cd -> (.) cd) (\ ef -> (.) ef)

  • (.) की परिभाषा को इनलाइन करें:
    (\ abx -> a (bx)) (\ cdy -> c (dy)) (\ efz -> e (fz))

  • विकल्प:
    (\ bx -> (\ cdy -> c (dy)) (bx)) (\ efz -> e (fz))

  • विकल्प b :
    (\ x -> (\ cdy -> c (dy)) ((\ efz -> e (fz)) x))

  • विकल्प e :
    (\ x -> (\ cdy -> c (dy)) (\ fz -> x (fz)))

  • विकल्प c :
    (\ x -> (\ dy -> (\ fz -> x (fz)) (dy)))

  • विकल्प f :
    (\ x -> (\ dy -> (\ z -> x (dyz))))

  • रेसर लैम्बडा नोटेशन:
    \ xdyz -> x (dyz)

और अगर आप जीएचसीआई से पूछते हैं, तो आपको पता चल जाएगा कि इसमें अपेक्षित प्रकार है। क्यूं कर? क्योंकि फ़ंक्शन एरो करीइंग का समर्थन करने के लिए सही-एसोसिएटिक है: प्रकार (b -> c) -> (a -> b) -> a -> c वास्तव में इसका अर्थ है (b -> c) -> ((a -> b) -> (a -> c)) । उसी समय, टाइप वेरिएबल b फ़ंक्शन प्रकार सहित किसी भी प्रकार के लिए खड़े हो सकता है। कनेक्शन देखें?

यहां एक ही घटना का एक सरल उदाहरण है:

 id :: a -> a id x = x 

आईडी का प्रकार कहता है कि आईडी को एक तर्क देना चाहिए। और वास्तव में, हम इसे एक तर्क के साथ कह सकते हैं:

 > id "hello" "hello" 

लेकिन यह पता चला है कि हम इसे दो तर्कों के साथ भी कह सकते हैं:

 > id not True False 

या और भी:

 > id id "hello" "hello" 

क्या हो रहा है? id not True को समझने की चाबी id not True है, पहले id not देखने के लिए। स्पष्ट रूप से, यह अनुमति दी गई है, क्योंकि यह आईडी को एक तर्क के लिए लागू करता है Bool -> Bool का प्रकार not है, इसलिए हम जानते हैं कि आईडी के प्रकार से a होना चाहिए Bool -> Bool , इसलिए हमें पता है कि आईडी की यह घटना प्रकार है:

 id :: (Bool -> Bool) -> (Bool -> Bool) 

या, कम कोष्ठकों के साथ:

 id :: (Bool -> Bool) -> Bool -> Bool 

इसलिए आईडी की यह घटना वास्तव में दो तर्कों को लेती है

वही तर्क id id "hello" और (.) . (.) लिए काम करता है (.) . (.) (.) . (.)

यह उन साफ ​​मामलों में से एक है, जहां मुझे लगता है कि पहले सामान्य मामले को समझना आसान है और फिर विशिष्ट मामले के बारे में सोचें। तो हम फ़ैंटर्स के बारे में सोचें हम जानते हैं कि फ़ैक्टर्स एक ढांचे पर कार्य करने का एक तरीका प्रदान करते हैं –

 class Functor f where fmap :: (a -> b) -> fa -> fb 

लेकिन क्या होगा अगर हमारे पास फैक्टर के दो परत हैं? उदाहरण के लिए, सूची की सूची? उस स्थिति में हम fmap की दो परतों का उपयोग कर सकते हैं

 >>> let xs = [[1,2,3], [4,5,6]] >>> fmap (fmap (+10)) xs [[11,12,13],[14,15,16]] 

लेकिन पैटर्न f (gx) बिल्कुल वैसा ही है (f . g) x ताकि हम लिख सकें

 >>> (fmap . fmap) (+10) xs [[11,12,13],[14,15,16]] 

fmap . fmap का प्रकार क्या है fmap . fmap ?

 >>> :t fmap.fmap :: (Functor g, Functor f) => (a -> b) -> f (ga) -> f (gb) 

हम देखते हैं कि यह मस्तिष्क की दो परतों पर नक्शे है, जैसा कि हम चाहते थे लेकिन अब याद रखें कि (->) r एक मज़ेदार है ( r से कार्य का प्रकार, जिसे आप (r ->) रूप में पढ़ना पसंद कर सकते हैं) और उसका मज़ेदार उदाहरण है

 instance Functor ((->) r) where fmap fg = f . g 

फ़ंक्शन के लिए, fmap फ़ंक्शन संयोजन ही है! जब हम दो fmap लिखते हैं, तो हम फ़ंक्शन फ़ैक्टर के दो स्तरों को मैप करते हैं। हम शुरू में कुछ प्रकार (->) s ((->) ra) , जो s -> r -> a समतुल्य s -> r -> a , और हम कुछ प्रकार s -> r -> b साथ समाप्त होते हैं, तो प्रकार (.).(.) होना चाहिए

 (.).(.) :: (a -> b) -> (s -> r -> a) -> (s -> r -> b) 

जो अपना पहला कार्य लेता है, और दूसरे (दो तर्क) फ़ंक्शन के आउटपुट को बदलने के लिए इसका इस्तेमाल करता है। उदाहरण के लिए, फ़ंक्शन ((.).(.)) show (+) दो तर्कों का एक फ़ंक्शन है, जो पहले अपनी आर्गुमेंट को जोड़ता है और फिर परिणाम को String को show बदलता है:

 >>> ((.).(.)) show (+) 11 22 "33" 

फिर fmap की लंबी श्रृंखलाओं के बारे में सोचने के लिए एक प्राकृतिक सामान्यीकरण है, उदाहरण के लिए

 fmap.fmap.fmap :: (Functor f, Functor g, Functor h) => (a -> b) -> f (g (ha)) -> f (g (hb)) 

जो मस्तिष्क के तीन परतों पर मैप करता है, जो तीन तर्कों के एक समारोह के साथ रचना के बराबर है:

 (.).(.).(.) :: (a -> b) -> (r -> s -> t -> a) -> (r -> s -> t -> b) 

उदाहरण के लिए

 >>> import Data.Map >>> ((.).(.).(.)) show insert 1 True empty "fromList [(1,True)]" 

जो कुंजी 1 साथ खाली नक्शे में मूल्य को सम्मिलित करता है, और फिर आउटपुट को show साथ एक स्ट्रिंग में कनवर्ट करता है।


ये कार्य आम तौर पर उपयोगी हो सकते हैं, इसलिए आप कभी-कभी उन्हें परिभाषित करते हैं

 (.:) :: (a -> b) -> (r -> s -> a) -> (r -> s -> b) (.:) = (.).(.) 

ताकि आप लिख सकें

 >>> let f = show .: (+) >>> f 10 20 "30" 

बेशक, (.:) की एक सरल, पॉजिटिव परिभाषा दी जा सकती है

 (.:) :: (a -> b) -> (r -> s -> a) -> (r -> s -> b) (f .: g) xy = f (gxy) 

जो विघटित करने में मदद कर सकता है (.).(.) कुछ हद तक

आप सही हैं, (.) केवल दो तर्क लेते हैं आप केवल हैस्केल की सिंटैक्स से उलझन में हैं अभिव्यक्ति (.).(.) , यह वास्तव में मध्य में बिंदी है जो अन्य दो बिंदुओं को तर्क के रूप में लेता है, बस 100 + 200 की अभिव्यक्ति की तरह, जिसे (+) 100 200 रूप में लिखा जा सकता है।

 (.).(.) === (number the dots) (1.)2.(3.) === (rewrite using just syntax rules) (2.)(1.)(3.) === (unnumber and put spaces) (.) (.) (.) === 

और यह (.) (.) (.) से अधिक स्पष्ट होना चाहिए कि पहले (.) दूसरे (.) और तीसरे (.) क्योंकि यह तर्क है।

हाँ, यह करी की वजह से है। (.) रूप में Haskell में सभी फ़ंक्शन केवल एक तर्क लेता है। आप जो रचना कर रहे हैं वह प्रत्येक संबंधित रचना (.) लिए पहला आंशिक कॉल है, जो अपना पहला तर्क (संरचना का पहला कार्य (.) लेता है।

(फ़ंक्शन संरचना, $ ऑपरेटर और बिंदु-मुक्त शैली पर पहले मेरे उत्तर पढ़ें।)

कल्पना कीजिए कि आपके पास एक साधारण कार्य है: यह 2 नंबर जोड़ता है और फिर परिणाम नकारता है। हम इसे foo कहते हैं:

 foo ab = negate (a + b) 

अब हम कदम-दर-चरण से इसे बनाते हैं और देखते हैं कि हम किसके साथ समाप्त होते हैं:

 foo ab = negate $ a + b foo ab = negate $ (+) ab foo ab = negate $ (+) a $ b foo ab = negate . (+) a $ b foo a = negate . (+) a -- fx = gx is equivalent to f = g foo a = (.) negate ((+) a) -- any infix operator is just a function foo a = (negate.) ((+) a) -- (2+) is the same as ((+) 2) foo a = (negate.) $ (+) a foo a = (negate.) . (+) $ a foo = (negate.) . (+) foo = ((.) negate) . (+) foo = (.) ((.) negate) (+) -- move dot in the middle in prefix position foo = ((.) ((.) negate)) (+) -- add extra parentheses 

अब हम अभिव्यक्ति का विश्लेषण करते हैं (.) ((.) negate) अधिक बारीकी से यह (.) फ़ंक्शन का आंशिक अनुप्रयोग है, जिसका पहला तर्क है ((.) negate) । क्या हम इसे आगे भी बदल सकते हैं? हाँ हम कर सकते हैं:

 (.) ((.) negate) (.) . (.) $ negate -- because f (fx) is the same as (f . f) x (.)(.)(.) $ negate ((.)(.)(.)) negate 

(.).(.) के बराबर है (.)(.)(.) , क्योंकि पहली अभिव्यक्ति में, मध्य में डॉट उपसर्ग स्थिति में स्थानांतरित किया जा सकता है और कोष्ठकों से घिरा हुआ है, जो कि 2 अभिव्यक्ति को जन्म देता है।

अब हम अपने foo फ़ंक्शन को फिर से लिख सकते हैं:

 foo = ((.).(.)) negate (+) foo = ((.)(.)(.)) negate (+) -- same as previous one foo = negate .: (+) where (.:) = (.).(.) 

अब आप जानते हैं कि (.).(.) के बराबर है (\fgxy -> f (gxy)) :

 (\fgxy -> f (gxy)) negate (+) 2 3 -- returns -5 ((.).(.)) negate (+) 2 3 -- returns -5