कुछ स्पष्टीकरण क्रम में हैं!
आईडी फंक्शन किस लिए होता है की भूमिका क्या है? हमें यहां इसकी आवश्यकता क्यों होनी चाहिए?
id
है पहचान समारोह , id x = x
है, और जब साथ कार्यों की एक श्रृंखला का निर्माण शून्य के बराबर के रूप में प्रयोग किया जाता है समारोह रचना , (.)
। आप इसे प्रस्तावना में परिभाषित कर सकते हैं ।
उपरोक्त उदाहरण में, आईडी फ़ंक्शन लंबा फ़ंक्शन में संचायक है?
संचायक एक फ़ंक्शन है जिसे बार-बार फ़ंक्शन एप्लिकेशन के माध्यम से बनाया जा रहा है। कोई स्पष्ट लैम्ब्डा,, नहीं है क्योंकि हम संचायक नाम step
। आप चाहें तो इसे लंबोदर के साथ लिख सकते हैं:
foldl f a bs = foldr (\b g x -> g (f x b)) id bs a
या ग्राहम हटन के रूप में लिखेंगे :
5.1 foldl
ऑपरेटर
अब हम suml
उदाहरण से सामान्यीकरण करते हैं और मानक ऑपरेटर पर विचार करते हैं foldl
जो f
मानों को संयोजित करने के लिए एक फ़ंक्शन का उपयोग करके सूची के तत्वों को बाएं से दाएं क्रम में संसाधित करता है , और v
शुरुआती मूल्य के रूप में एक मूल्य:
foldl :: (β → α → β) → β → ([α] → β)
foldl f v [ ] = v
foldl f v (x : xs) = foldl f (f v x) xs
इस ऑपरेटर का उपयोग करके, suml
बस द्वारा इसे फिर से परिभाषित किया जा सकता है suml = foldl (+) 0
। कई अन्य कार्यों को सरल तरीके से उपयोग करके परिभाषित किया जा सकता है foldl
। उदाहरण के लिए, मानक फ़ंक्शन को निम्नानुसार reverse
उपयोग करके पुनर्परिभाषित किया जा सकता foldl
है:
reverse :: [α] → [α]
reverse = foldl (λxs x → x : xs) [ ]
यह परिभाषा तह का उपयोग करके हमारी मूल परिभाषा से अधिक कुशल है, क्योंकि यह (++)
सूचियों के लिए अक्षम अपेंडेंट ऑपरेटर के उपयोग से बचती है ।
फ़ंक्शन के लिए पिछले अनुभाग में गणना का एक सरल सामान्यीकरण suml
दिखाता है कि फ़ंक्शन को कैसे फिर से परिभाषित करना foldl
है fold
:
foldl f v xs = fold (λx g → (λa → g (f a x))) id xs v
इसके विपरीत, यह फिर से परिभाषित करना संभव नहीं है fold
के मामले में foldl
तथ्य यह है कि के कारण,
foldl
इसकी सूची तर्क की पूंछ में सख्त है, लेकिन fold
नहीं है। उपयोगी 'द्वंद्व प्रमेयों' की एक संख्या के विषय में कर रहे हैं fold
और foldl
, और भी निर्णय लेने से जो ऑपरेटर सबसे अच्छा विशेष अनुप्रयोगों (बर्ड, 1998) के लिए उपयुक्त है के लिए कुछ दिशा निर्देश।
तह का प्रोटोटाइप तह है :: (a -> - b -> b) -> b -> [a] -> b
एक Haskell प्रोग्रामर का कहना है कि प्रकार की foldr
है (a -> b -> b) -> b -> [a] -> b
।
और पहला पैरामीटर एक फ़ंक्शन है जिसमें दो मापदंडों की आवश्यकता होती है, लेकिन myFoldl के कार्यान्वयन में चरण फ़ंक्शन 3 मापदंडों का उपयोग करता है, मैं पूरी तरह से भ्रमित हूं
यह भ्रामक और जादुई है! हम एक चाल खेलते हैं और एक फ़ंक्शन के साथ संचायक को बदलते हैं, जिसके परिणामस्वरूप परिणाम प्राप्त करने के लिए प्रारंभिक मूल्य पर लागू किया जाता है।
ग्राहम हटन चाल चालू करने के लिए बताते हैं foldl
में foldr
उपरोक्त लेख में। हम नीचे एक पुनरावर्ती परिभाषा लिखकर शुरू करते हैं foldl
:
foldl :: (a -> b -> a) -> a -> [b] -> a
foldl f v [] = v
foldl f v (x : xs) = foldl f (f v x) xs
और फिर इस पर स्थैतिक तर्क परिवर्तन के माध्यम से इसे रिफलेक्टर करें f
:
foldl :: (a -> b -> a) -> a -> [b] -> a
foldl f v xs = g xs v
where
g [] v = v
g (x:xs) v = g xs (f v x)
चलिए अब फिर से लिखते हैं g
ताकि v
अंदर की ओर तैरें:
foldl f v xs = g xs v
where
g [] = \v -> v
g (x:xs) = \v -> g xs (f v x)
जो g
एक तर्क के एक समारोह के रूप में सोचने के समान है, जो एक फ़ंक्शन देता है:
foldl f v xs = g xs v
where
g [] = id
g (x:xs) = \v -> g xs (f v x)
अब हमारे पास g
एक फ़ंक्शन है , जो किसी सूची को पुन: बनाता है, कुछ फ़ंक्शन लागू करता है f
। अंतिम मान पहचान फ़ंक्शन है, और प्रत्येक चरण किसी फ़ंक्शन में भी परिणाम करता है।
लेकिन , हमारे पास सूचियों पर पहले से ही एक समान पुनरावर्ती कार्य है foldr
!
2 गुना ऑपरेटर
fold
ऑपरेटर, जबकि का उपयोग करते हैं, प्रत्यावर्तन सिद्धांत (क्लीन, 1952) में अपनी मूल है fold
बैकस एक प्रोग्रामिंग भाषा दिनांकों में एक केंद्रीय अवधारणा के रूप में एपीएल की कमी ऑपरेटर (इवर्सन, 1962) के लिए वापस, और बाद में एफपी की प्रविष्टि ऑपरेटर के लिए ( , 1978)। हास्केल में, fold
सूचियों के ऑपरेटर को निम्नानुसार परिभाषित किया जा सकता है:
fold :: (α → β → β) → β → ([α] → β)
fold f v [ ] = v
fold f v (x : xs) = f x (fold f v xs)
यही कारण है, एक समारोह में दिया जाता है f
प्रकार के α → β → β
और एक मूल्य के v
प्रकार के β
, समारोह
fold f v
प्रकार की एक सूची को संसाधित करता है [α]
प्रकार का एक मूल्य देने के लिए β
नहीं के बराबर निर्माता की जगह []
मूल्य द्वारा सूची के अंत में v
, और प्रत्येक विपक्ष निर्माता (:)
द्वारा सूची के भीतर समारोह f
। इस तरीके से, fold
ऑपरेटर प्रसंस्करण सूचियों के लिए पुनरावृत्ति का एक सरल पैटर्न संलग्न करता है, जिसमें सूचियों के लिए दो निर्माणकर्ता बस अन्य मूल्यों और कार्यों द्वारा प्रतिस्थापित किए जाते हैं। सूचियों पर कई परिचित कार्यों का उपयोग करने की एक सरल परिभाषा है fold
।
यह हमारे g
फ़ंक्शन के लिए एक बहुत ही समान पुनरावर्ती योजना जैसा दिखता है । अब चाल: हाथ में सभी उपलब्ध जादू (उर्फ बर्ड, मेर्टेंस और मैल्कम) का उपयोग करते हुए हम एक विशेष नियम लागू करते हैं, गुना की सार्वभौमिक संपत्ति , जो एक फ़ंक्शन के लिए दो डी for nitions के बीच एक तुल्यता है जो g
प्रक्रियाओं को सूचीबद्ध करता है, जैसा कि कहा गया है।
g [] = v
g (x:xs) = f x (g xs)
यदि और केवल यदि
g = fold f v
इसलिए, सिलवटों की सार्वभौमिक संपत्ति बताती है कि:
g = foldr k v
जहां g
दो समीकरणों के बराबर होना चाहिए कुछ के लिए k
और v
:
g [] = v
g (x:xs) = k x (g xs)
हमारे पहले के डिजाइनों से, हम जानते हैं v == id
। दूसरे समीकरण के लिए हालांकि, हमें इसकी परिभाषा की गणना करने की आवश्यकता है k
:
g (x:xs) = k x (g xs)
<=> g (x:xs) v = k x (g xs) v
<=> g xs (f v x) = k x (g xs) v
<= g' (f v x) = k x g' v
<=> k = \x g' -> (\a -> g' (f v x))
जो, हमारी गणना की गई परिभाषाओं को प्रतिस्थापित करता है k
और v
निम्न की परिभाषा देता है:
foldl :: (a -> b -> a) -> a -> [b] -> a
foldl f v xs =
foldr
(\x g -> (\a -> g (f v x)))
id
xs
v
पुनरावर्ती g
को फोल्डर कॉम्बीनेटर के साथ बदल दिया जाता है, और संचायक f
रिवर्स फ़ंक्शन में सूची के प्रत्येक तत्व पर रचनाओं की एक श्रृंखला के माध्यम से निर्मित एक फ़ंक्शन बन जाता है (इसलिए हम दाएं के बजाय बाएं मुड़ते हैं)।
यह निश्चित रूप से कुछ हद तक उन्नत है, इसलिए इस परिवर्तन को गहराई से समझने के लिए, सिलवटों की सार्वभौमिक संपत्ति , जो परिवर्तन को संभव बनाती है, मैं नीचे से जुड़े हटन के ट्यूटोरियल की सलाह देता हूं।
संदर्भ
step = curry $ uncurry (&) <<< (flip f) *** (.)