2011-07-08 24 views
6

मैं हास्केल सीख रहा हूं, और मेरे अभ्यास कार्यों में से एक एक साधारण रिकर्सिव permute था। मैं the solution described here अनुकूलित और मूल रूप से यह मिल गया:रिकर्सिव क्रमपरिवर्तन फ़ंक्शन हमेशा खाली सूची

selections [] = [] 
selections (x:xs) = (x, xs) : [ (y, x:ys) | (y,ys) <- selections xs ] 

permute xs = [y:ps | (y,ys) <- selections xs, ps <- permute ys] 

(हाँ, यह कम हो सकता है, लेकिन मैं मुखरता और स्पष्टता के लिए जा रहा था।)

हालांकि, permute के इस संस्करण हमेशा एक खाली सूची नहीं लौटाई गई!

permute [] = [[]] 
permute xs = [y:ps | (y,ys) <- selections xs, ps <- permute ys] 

हालांकि, मैं अब भी क्यों मूल संस्करण हमेशा एक खाली सूची रिटर्न के रूप में हैरान हूँ: थोड़ा घिसटते हुए के बाद, मैं यह करने के लिए permute बदलकर काम करने के लिए मिला है।

+0

कम से कम यह आपके प्रोग्राम से स्पष्ट होना चाहिए कि 'परमिट' का मूल संस्करण किसी तत्व के रूप में '[]' युक्त किसी भी सूची को वापस नहीं कर सकता है, क्योंकि तत्व हमेशा 'y: ps' रूप का होता है। –

उत्तर

12

ठीक है, दोनों स्पष्ट रूप से बहुत समान हैं, तो क्यों न बताएं कि वे कहां असहमत हैं? रिकर्सिव हिस्सा दोनों में बिल्कुल समान है, इसलिए सबसे पहले हम कह सकते हैं कि दोनों संस्करण गैर-खाली सूचियों पर एक ही चीज़ करते हैं। यह गलत लगता है क्योंकि वे अलग-अलग परिणाम देते हैं, लेकिन वास्तव में यह सच है कि वे रिकर्सिव कॉल के परिणामस्वरूप एक ही ऑपरेशन करते हैं।

सही संस्करण से मूल मामला permute [] = [[]] है, जो आत्म-व्याख्यात्मक है। हालांकि, पहले संस्करण से मूल मामला सूची समझ में निहित है। यह देखते हुए परिभाषा:

permute xs = [y:ps | (y,ys) <- selections xs, ps <- permute ys] 

... हम xs के लिए [] में स्थानापन्न देखने के लिए कि क्या होता है सकते हैं:

permute [] = [y:ps | (y,ys) <- [], ps <- permute ys] 

:

permute [] = [y:ps | (y,ys) <- selections [], ps <- permute ys] 

परिभाषा selections [] = [] देखते हुए, हम करने के लिए सरल बना सकते हैं ... जिससे यह स्पष्ट हो जाता है कि कोई परिणाम उत्पन्न नहीं होता है, इसलिए पूरी सूची समझ खाली होती है, बस नीचे सरलीकृत होती है:

permute [] = [] 

अब,, आधार से पहले अंतिम पुनरावर्ती कदम पर विचार तर्क के रूप में [x] प्रतिस्थापन:

permute [x] = [y:ps | (y,ys) <- selections [x], ps <- permute ys] 

selections की परिभाषा, selections (x:xs) = (x, xs) : [ (y, x:ys) | (y,ys) <- selections xs ] है [x] में प्रतिस्थापन selections [x] = (x, []) : [ (y, x:ys) | (y,ys) <- selections [] ] देता है। selections [][] का मूल्यांकन करता है, इसलिए पूरी सूची समझ [] तक कम हो जाती है, selections [x] = (x, []) : [] या केवल selections [x] = [(x, [])] दे रही है।

स्थानापन्न कि जैसा कि ऊपर permute में:

permute [x] = [y:ps | (y,ys) <- [(x, [])], ps <- permute ys] 

सूची में केवल एक तत्व नहीं है, तो हम बंधन और सीधे स्थानापन्न <- समझ अनदेखा कर सकते हैं:

permute [x] = [y:ps | (y,ys) = (x, []), ps <- permute ys] 

permute [x] = [ x:ps | ps <- permute []] 

कि permute [] मूल्यांकन करता है की स्थापना के बाद [] पर, हम इसे भी बदल सकते हैं और पाते हैं कि सूची समझ फिर से []:

तक कम हो जाती है
permute [x] = [] 

... जो किसी भी इनपुट के लिए आसानी से [] लौटने के लिए सामान्यीकृत करता है। संस्करण काम कर रहा है, तथापि, निम्नलिखित परिभाषा का उपयोग करता है:

permute [] = [[]] 

अंतिम पुनरावर्ती कदम के अंतिम कमी में, यह निम्न के प्रतिस्थापन परिवर्तन:

permute [x] = [ x:ps | ps <- permute []] 

permute [x] = [ x:ps | ps <- [[]] ] 

ps के बाद से बाध्य किया जा रहा है एक तत्व के साथ कुछ करने के लिए, हम फिर से सीधे प्रतिस्थापित कर सकते हैं:

permute [x] = (x:[]) 

जो बस है कह रही है कि permute [x] = [x]

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