2011-09-02 4 views
8

यह tryhaskell.org पर एक अनंत लूप में जाता है। मुझे यकीन नहीं है क्यों।जीएचसी कभी-कभी आलसी होने से इंकार क्यों कर रहा है?

last $ filter (<100) $ [2..] >>= (\a -> if 0 == (length $ filter (== 0) $ map (mod a) $ [2..a-1]) then (return a) else []) 
+1

आपको प्रश्न में इसे संपादित करने के बजाय आपको अपना समाधान उत्तर के रूप में पोस्ट करना चाहिए। [यहां देखें] (http://meta.stackexchange.com/questions/41700/should-i-update-my-question-to-include-the-correct-answer)। मैंने आपके संपादन को वापस ले लिया है। – hammar

उत्तर

9

यह आलसी होना करने के लिए मना नहीं कर रहा है, यह सिर्फ वहाँ यह पता चला है कि तुम्हारे जाने के बाद सभी का अभाज्य < 100 मिलता है, वहाँ किसी भी अधिक नहीं हैं के लिए कोई रास्ता नहीं है है।

क्या होगा यदि अनुक्रम

की तरह दिखाई देता

1, 2, ... 99, 100, 101, 102, 5, 103, ...

दूसरे शब्दों में, last अनुमान नहीं लगा सकते भविष्य। ओह कैसे मैं चाहता हूँ।

+0

मुझे यह देखना चाहिए था। धन्यवाद :-) –

+4

@ वैन्सन: आप 'फ़िल्टर' के बजाय' टेकवॉल्ड' का उपयोग कर इसे हल कर सकते हैं। – hammar

9

चलो चीजों को अलग करते हैं, अंदर से काम करते हैं। इससे शुरू:

last $ filter (<100) $ [2..] >>= (\a -> if 0 == (length $ filter (== 0) $ map (mod a) $ [2..a-1]) then (return a) else []) 

पहले map (mod a) [2..a-1] पर विचार करें। यह सिर्फ एक सीमित सूची का एक परिवर्तन है, इसलिए यहां कोई समस्या नहीं है, और हम इसे यहां से [..] डालकर इसे अनदेखा कर देंगे। चूंकि हम केवल समाप्त होने की परवाह करते हैं, किसी भी सीमित सूची को दूसरे के रूप में अच्छा है।

filter (== 0) [...] के लिए ही चला जाता है। यह केवल सूची को छोटा कर सकता है, इसलिए हम इसके बजाय खाली सूची के साथ समाप्त हो सकते हैं, लेकिन निश्चित रूप से सीमित हो सकते हैं। तो इसे भी अनदेखा करें। अब length [..] पर विचार करें - हम जानते हैं कि सूची सीमित है, इसलिए यह 0 या उससे अधिक का कुछ जवाब देकर ठीक ठीक हो जाएगा। हम विशिष्ट उत्तर को अनदेखा करेंगे और ? अपनी जगह पर रखेंगे। अभी तक ठीक है।

लैम्ब्डा \a -> if 0 == ? then return a else [] सूची इकाई में return उपयोग कर रहा है, तो यह या तो [a] या [], जो संयोग से Maybe के बराबर है साथ a बदल देता है, लेकिन है कि एक और बात है। दोबारा, हम जानते हैं कि यह बहुत काम करेगा, इसलिए हम विवरणों को अनदेखा करते हैं और \a -> [a?] का उपयोग करते हैं।

मोनैडिक बाइंड [2..] >>= \a -> [a?] अधिक दिलचस्प है। (>>=) यहां concatMap है, और पहला तर्क एक अनंत सूची है। प्रत्येक तत्व को सिंगलटन सूची में मैप करना और संक्षेप में कुछ भी नहीं बदलता है, जबकि खाली सूची में मैपिंग तत्व को हटा देता है, इसलिए यह अनिवार्य रूप से केवल filter है। हालात नहीं हैं, हालांकि, हम एक अनंत सूची को फ़िल्टर कर रहे हैं, इस बात के बिना कि कोई स्पष्ट आश्वासन नहीं है कि फ़िल्टर को पास करेगा। यदि आप filter (const False) [0..] करते हैं तो "परिणाम" में कोई तत्व नहीं होगा, लेकिन गणना कभी खत्म नहीं होगी; []filter के आउटपुट में इनपुट सूची के अंत को खोजने से आता है, और इसमें कोई नहीं है, और चूंकि इसे पहले तत्व नहीं मिलेगा, परिणाम केवल _|_ है।

तो चीजें पहले ही समस्याग्रस्त हैं। अगला भाग, filter (<100), चीजों को और भी खराब बनाता है - हम सख्ती से बढ़ती सूची से तत्वों को फ़िल्टर कर रहे हैं, फिर इसे कुछ मूल्य के आधार पर फ़िल्टर कर रहे हैं, इसलिए उपर्युक्त तर्क से यदि हम परिणाम 100 पर जाते हैं तो गणना गणना होगी लटका।

और अंतिम अपमान last है - प्रश्न में सूची अभी भी अनंत है, लेकिन अधिक तत्वों के उत्पादन के बजाय किसी बिंदु पर अलग हो जाएगी, इसलिए जब हम अंतिम तत्व मांगते हैं तो हम देख सकते हैं कि यह समाप्त हो जाएगा कई कारण!

तुम यहाँ करना, पहले अपने ज्ञान है कि सूची सख्ती से बढ़ती जा रही है लागू होते हैं, और बजाय छानने सूची, बस इसे का एक उपसर्ग वांछित बिंदु तक का समय लग चाहते हैं क्या - बल्कि जैसे, takeWhile (<100)filter (< 100) से अधिक। ध्यान दें कि परिणाम में 100 से अधिक तत्व नहीं होने पर यह अभी भी अलग हो जाएगा, क्योंकि takeWhile को कब रुकना है, यह नहीं पता होगा।

+0

उत्कृष्ट स्पष्टीकरण! –

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