2009-11-22 14 views
11

मैं हास्केल में पूरी तरह से नया हूँ और जब छोटे कार्यक्रमों लेखन मैं सामान्य रूप से भी कई के साथ अंत जहां खंड समारोह में कई चीजों की जांच करने के, तो यह लिखने के लिए जहां खंड या अच्छा अभ्यास है क्या इसके लिए कोई और अच्छा विकल्प है?हास्केल भी कई जहां खंड, कोई वैकल्पिक सुझाव

मैं नीचे दिए गए कोड में उदाहरण के लिए

अगर है वहाँ दो आयामी सूची की प्रत्येक पंक्ति में चींटी डुप्लिकेट तत्वों को खोजने के लिए कोशिश की, यह काम करता है और हर चीज एक ही समारोह में सामग्री है, लेकिन मैं कैसे कोड लग रहा है और मैं से संतुष्ट नहीं हूं इस समस्या के करीब आने की अधिक अनिवार्य शैली पाएं, इसलिए मैं वहां अनुभवी लोगों से इस पर कोई सुझाव या विचार ढूंढ रहा हूं।

noDups :: [[a]] -> Bool 
noDups du = and (checkSu du) 
     where 
     checkDup []  = [] 
     checkDup (x:xs) = checkRow x ++ checkDup xs 
      where 
      checkRow []  = [] 
      checkRow (x:xs) = [x /= y | y <- xs] ++ checkRow xs 

एक बार फिर यह कोड केवल एक समस्या को चित्रित करने के लिए है, मैं कार्यात्मक शैली में समस्या बनाने के लिए दृष्टिकोण की तलाश में हूं। आपके सुझाव या लेख, लिंक बहुत उपयोगी होंगे।

धन्यवाद

उत्तर

24

कोशिश सार, पुन: प्रयोज्य कार्यों आप उन्हें रचना करने में सक्षम हो जाएगा लिखने के लिए बहुत आसान

isUnique :: Eq a => [a] -> Bool 
isUnique [] = True 
isUnique (x:xs) = all (/= x) xs && isUnique xs 

noDups :: Eq a => [[a]] -> Bool 
noDups = all isUnique 
+0

+1 सभी जटिलताओं को एक साथ में जोड़ने की कोशिश करने के बजाय छोटे कार्यों में विभाजित करने का सुझाव देने के लिए +1। – Joren

3
noDups :: [[a]] -> Bool 
noDups = and . checkDup 
    where 
    --checkDup 
    checkDup []  = [] 
    checkDup (x:xs) = checkRow x ++ checkDup xs 
    --alternatively 
    checkDup xs = concat $ map checkRow xs 
    --alternatively 
    checkDup = concat . map checkRow 
    --alternatively 
    checkDup = concatMap checkRow 
    --checkRow 
    checkRow []  = [] 
    checkRow (x:xs) = [x /= y | y <- xs] ++ checkRow xs 
2

हालांकि अपवाद हैं, सामान्य रूप में आप को परिभाषित करने के "चाहते हो सकता है सकारात्मक "काम करता है, इस मामले में यानी एक समारोह जो True लौटाता है यदि तर्क कुछ डुप्लिकेट डेटा शामिल करता है परिभाषित करते हैं। आपको लगता है कि इस प्रकार लिख सकते:

has_nested_duplicate :: (Eq a) => [[a]] -> Bool 
has_nested_duplicate = any has_duplicate 
    where 
    has_duplicate []  = False 
    has_duplicate (x:xs) = x `elem` xs || has_duplicate xs 

यह पैटर्न मिलान, any, elem और (||) उपयोग करता है। निषेध पाने के लिए, not का उपयोग करें:

noDups :: (Eq a) => [[a]] -> Bool 
noDups = not . has_nested_duplicate 
6

आप जहां खंड दूसरा जरूरत नहीं है। आप एक ही where खंड के तहत कई फ़ंक्शन डाल सकते हैं। उन कार्यों के निकायों में where खंड में सभी फ़ंक्शन नाम दायरे में हैं। इस बारे में सोचें कि शीर्ष-स्तरीय कार्य कैसे काम करते हैं। तो अगर आप लिख सकते हैं:

noDups :: [[a]] -> Bool 
noDups du = and (checkSu du) 
    where checkDup []  = [] 
     checkDup (x:xs) = checkRow x ++ checkDup xs 

     checkRow []  = [] 
     checkRow (x:xs) = [x /= y | y <- xs] ++ checkRow xs 

वास्तव में यह और अधिक स्पष्ट है, क्योंकि आपके संस्करण में होता है जब आप checkDup में x बाँध, कि xदूसराwhere खंड में दायरे में अब भी है, फिर भी आप बाध्यकारी हैं उसी नाम पर checkRow के तर्क। मुझे लगता है कि यह शायद जीएचसी शिकायत करेगा, और यह निश्चित रूप से भ्रमित है।

4

अपने विशेष उदाहरण के विवरण में से कुछ अलग छोड़कर (नाम expecially अच्छी तरह से चुना नहीं कर रहे हैं), मैं जहां खंड का एक बड़ा प्रशंसक हूँ:

  • एक समारोह एक where खंड में परिभाषित किया जा सकता है एक शीर्ष-स्तरीय फ़ंक्शन से बेहतर है क्योंकि एक पाठक जानता है कि फ़ंक्शन का दायरा सीमित है --- इसका उपयोग केवल कुछ स्थानों पर किया जा सकता है।

  • यह आसान

पढ़ने के लिए अपने विशिष्ट उदाहरण में एक where खंड एक संलग्न समारोह है, जो अक्सर बनाता है के मापदंडों पर कब्जा कर सकते हैं के रूप में परिभाषित एक समारोह, आप घोंसला where clauses- की जरूरत नहीं है - एक एकल where खंड करेगा, क्योंकि उसी where खंड में परिभाषित फ़ंक्शंस एक दूसरे के साथ पारस्परिक रूप से पुनरावर्ती हैं। कोड के बारे में अन्य चीजें हैं जिन्हें बेहतर किया जा सकता है, लेकिन एकल where खंड के साथ मुझे बड़े पैमाने पर संरचना ठीक पसंद है।

एनबी। where क्लॉज को गहराई से इंडेंट करना जरूरी नहीं है जितना आप कर रहे हैं।

1

हास्केल आपको कहां से खंड में परिभाषित चीजों को संदर्भित करने की अनुमति देता है (जहां एक बाध्यकारी के समान चीज है)। वास्तव में जहां एक खंड केवल बाध्यकारी के लिए सिंटेक्टिक चीनी है जो कई चीजों के साथ कई परिभाषाओं और आपसी संदर्भों की अनुमति देता है।

एक उदाहरण क्रम में है।

noDups :: [[a]] -> Bool 
noDups du = and (checkDup du) 
    where 
     checkDup []  = [] 
     checkDup (x:xs) = checkRow x ++ checkDup xs 
      where 
       checkRow []  = [] 
       checkRow (x:xs) = [x /= y | y <- xs] ++ checkRow xs 

noDups :: [[a]] -> Bool 
noDups du = and (checkDup du) 
    where 
     checkDup []  = [] 
     checkDup (x:xs) = checkRow x ++ checkDup xs 
     --checkDup can refer to checkRow 
     checkRow []  = [] 
     checkRow (x:xs) = [x /= y | y <- xs] ++ checkRow xs 

noDups :: [[a]] -> Bool 
noDups du = 
    let checkDup []  = [] 
     checkDup (x:xs) = checkRow x ++ checkDup xs 
     --checkDup can refer to checkRow 
     checkRow []  = [] 
     checkRow (x:xs) = [x /= y | y <- xs] ++ checkRow xs 

    in and (checkDup du) 
1

मैं वैश्विक क्षेत्र स्वच्छ रखने के लिए Norman रूप में एक ही लग रहा है हो जाता है हो जाता है। आपके मॉड्यूल को के भीतर का खुलासा करने वाले अधिक कार्य, नामस्थान बनने के लिए और अधिक बेकार है। दूसरी ओर, आपके मॉड्यूल के वैश्विक दायरे में एक कार्य करने से यह पुन: प्रयोज्य हो जाता है।

मुझे लगता है कि आप एक स्पष्ट भेद कर सकते हैं। कुछ फ़ंक्शन एक मॉड्यूल के लिए प्रिंसिपल होते हैं, वे सीधे एपीआई में योगदान देते हैं। ऐसे फ़ंक्शन भी हैं जो मॉड्यूल प्रलेखन में दिखाई देते हैं, पाठक को यह सोचते हुए छोड़ दिया जाता है कि मॉड्यूल के उद्देश्य से उस विशेष कार्य को क्या करना है। यह स्पष्ट रूप से एक सहायक समारोह है।

मैं कहूंगा कि इस तरह का एक सहायक कार्य कॉलिंग फ़ंक्शन का अधीनस्थ होना चाहिए। यदि इस सहायक फ़ंक्शन को मॉड्यूल के भीतर पुन: उपयोग किया जाना है, तो इस सहायक फ़ंक्शन को कॉलिंग फ़ंक्शन से मॉड्यूल का सीधे पहुंच योग्य फ़ंक्शन बनाकर डिसकूल करें। हालांकि आप मॉड्यूल परिभाषा में इस फ़ंक्शन को निर्यात नहीं करेंगे।
चलो इसे एक एफपी-शैली रिफैक्टरिंग कहते हैं।

यह एक दयालु बात है कि कार्यात्मक प्रोग्रामिंग के लिए "कोड पूर्ण" जैसी पुस्तक मौजूद नहीं है। मुझे लगता है कि कारण बहुत कम उद्योग अभ्यास है। लेकिन हम स्टैक ओवरफ्लो पर ज्ञान एकत्र करते हैं: डी

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