2012-09-05 36 views
11

मुझे आश्चर्य है कि गुना बाएं द्वारा अपेक्षित फ़ंक्शन को b -> a -> a के बजाय 0 हस्ताक्षर a -> b -> a टाइप करें। क्या इसके पीछे कोई डिज़ाइन निर्णय है?गुना क्यों छोड़ दिया जाता है (ए -> बी -> ए) (बी -> ए -> ए) के बजाय?

हास्केल में, उदाहरण के लिए, मुझे को foldl (:) [] xs (जो b -> a -> a के साथ संभव होगा) की बजाय सूची को रिवर्स करने के लिए foldl (\xs x -> x:xs) [] xs लिखना होगा। दूसरी ओर, ऐसे उपयोग मामले हैं जिनके लिए मानक a -> b -> a की आवश्यकता होती है। स्कैला में, यह संलग्न हो सकता है: xs.foldLeft(List.empty[Int]) ((xs, x) => xs:+x) जिसे xs.foldLeft(List.empty[Int]) (_:+_) के रूप में लिखा जा सकता है।

आनुपातिक रूप से अधिक उपयोग मामलों को वैकल्पिक विकल्प के बजाय दिए गए प्रकार के हस्ताक्षर की आवश्यकता होती है, या क्या ऐसे अन्य निर्णय हैं जो बास्क के डिजाइन को हास्केल और स्कैला (और शायद अन्य कई भाषाओं) में ले जाते हैं?

+4

दूसरे शब्दों में, आपको सूची को वापस करने के लिए '(:)' के तर्क आदेश को उलटना होगा। मेरी समझ मे आ रहा है। –

+1

ध्यान दें कि 'mapAccumL' और' mapAccumR' ('Data.List' /' Data.Traversable' से) के समान हस्ताक्षर हैं, हालांकि वे विपरीत दिशाओं में भी काम करते हैं। – leftaroundabout

उत्तर

28

वैचारिक तौर पर सही गुना, का कहना है कि foldr f z [1..4] निम्नलिखित रूप

f 
/\ 
1 f 
/\ 
    2 f 
    /\ 
    3 f 
    /\ 
     4 z 

की अभिव्यक्ति के मूल्य के साथ निम्नलिखित रूप

: 
/\ 
1 : 
/\ 
    2 : 
    /\ 
    3 : 
    /\ 
     4 [] 

की एक सूची की जगह हम इस का प्रतिनिधित्व करना हो तो एक पंक्ति पर अभिव्यक्ति, सभी कोष्ठक सही से जुड़े होंगे, इसलिए नाम सही गुना होगा: (1 `f` (2 `f` (3 `f` (4 `f` z))))। एक बाएं गुना कुछ हद तक एक दाहिने गुना करने के लिए दोहरी है। विशेष रूप से, हम इसी चित्र के आकार के लिए चाहते हैं एक छोड़ दिया गुना एक छोड़ दिया गुना के लिए कि का एक आईना छवि होने के लिए, के रूप में निम्नलिखित:

 f 
    /\ 
     f 4 
    /\ 
    f 3 
/\ 
    f 2 
/\ 
z 1 

हम पर इस चित्र को लिखने के लिए थे, तो एक पंक्ति है, हम एक अभिव्यक्ति मिलेगा जहां बाईं ओर सभी कोष्ठकों सहयोगी है, जो एक बाईं गुना के नाम के साथ अच्छी तरह से jibes:

((((z `f` 1) `f` 2) `f` 3) `f` 4) 

लेकिन लगता है कि इस दर्पण चित्र में, गुना की पुनरावर्ती परिणाम है पहली तर्क के रूप में f को खिलाया गया, जबकि सूची के प्रत्येक तत्व को दूसरे तर्क के रूप में खिलाया जाता है, यानी तर्क f को खिलाया जाता है सही गुना की तुलना में विपरीत क्रम में।

4

क्योंकि आप foldLeft के लिए संक्षिप्त रूप में लिखते हैं; यह एक ऑपरेटर है जो सभी bs के माध्यम से a को धक्का देता है, इसलिए फ़ंक्शन को उसी तरह लिखना स्वाभाविक है (यानी (A,B) => A)। ध्यान दें कि foldRight इसे दूसरे क्रम में करता है।

+0

अच्छा, लेकिन यह केवल स्काला के लिए हास्केल में नहीं समझाएगा जिसमें '/:' नहीं है। – sschaef

7

प्रकार हस्ताक्षर foldl :: (a -> b -> a) -> a -> [b] -> a है; संयोजन समारोह के लिए बाईं ओर प्रारंभिक मान होना स्वाभाविक है, क्योंकि यह सूची के तत्वों के साथ मिलकर बनता है। इसी प्रकार, आपको foldr पर ध्यान दिया जाएगा, यह एक और तरीका है। रिवर्स की आपकी परिभाषा में जटिलता यह है कि आप लैम्ब्डा अभिव्यक्ति का उपयोग कर रहे हैं जहां flip अच्छा होगा: foldl (flip (:)) [] xs, जिसमें फ्लिप और रिवर्स की अवधारणाओं के बीच सुखद समानता भी है।

2

आप इस राशि कहते हैं:

List(4, 2, 1).foldLeft(8)(_/_) 

वह उसी के रूप में:

((8/4)/2)/1 

देखें कि पहले पैरामीटर हमेशा ते संचायक है?इस क्रम में पैरामीटर रखने से प्लेसहोल्डर सिंटैक्स (अंडरस्कोर) विस्तारित अभिव्यक्ति के लिए एक प्रत्यक्ष अनुवाद बनाता है।

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