2012-12-30 19 views
19

के अंदर क्लॉज सिंटैक्स है, मैं mapM_ फ़ंक्शन कॉल को do ब्लॉक में हास्केल में रीफैक्टर करने का प्रयास कर रहा हूं। कोड को और अधिक पठनीय बनाने के लिए मैं लैम्ब्डा को एक (स्थानीय रूप से) नामित फ़ंक्शन में निकालना चाहता हूं।हास्केल जहां एक ब्लॉक ब्लॉक

मेरे कोड मूल रूप से इस तरह दिखता है:

do 
    -- ... 
    mapM_ (\x -> x + 1) aList 

    return aValue 

मैं

do 
    -- ... 
    mapM_ func aList 
    where func x = x + 1 

    return aValue 

करने के लिए इसे बदलना चाहते हैं, लेकिन मैं return aValue लाइन पर एक सिंटैक्स त्रुटि हो रही है। मेरा वास्तविक लैम्ब्डा अधिक जटिल है :-), लेकिन मैंने यह लैम्बडा कोड के साथ यह सुनिश्चित करने के लिए कोशिश की कि यह लैम्ब्डा कोड में कोई मुद्दा नहीं है।

मैं इस कोड को कैसे लिख सकता हूं? क्या मुझे let ... in का उपयोग करना चाहिए?

उत्तर

27

यहां सामान को परिभाषित करने के तीन समान (लेकिन अलग) तरीके हैं:

  • आप कुछ परिभाषाओं के बाद where खंड संलग्न कर सकते हैं - ज्यादातर समीकरण शैली बाइंडिंग । तो आप अपने फ़ंक्शन के अंत में, या let या आसपास के where खंड के साथ परिभाषित कुछ के बाद डाल सकते हैं।

  • दूसरी ओर, let x = ... in ... एक अभिव्यक्ति कि in के बाद वाले हिस्से का मूल्यांकन है, जो केवल जगह let के बाद सामान दिख रहा है है।

  • एक do ब्लॉक के अंदर, पहले से ही है क्योंकि इस बात की गुंजाइश एक अंतर्निहित घोंसले (चीजें दिखाई के बाद वे पहली बार परिभाषित कर रहे हैं), तो आप सिर्फ let x = ... अकेले उपयोग कर सकते हैं। यह वास्तव में पिछले रूप जैसा ही है - शेष dolet के बाद ब्लॉक प्रभावी ढंग से in ... भाग है।

आप एक स्थानीय परिभाषा कुछ do ब्लॉक के भीतर परिभाषित का उपयोग करता है चाहते हैं, अपने एकमात्र विकल्प तिहाई (या तर्क (रों) के रूप में अन्य मूल्य (रों) गुजर रहा है)। आपके उदाहरण की तरह एक स्वतंत्र सहायक कार्यों के लिए, हालांकि, कोई भी शैली काम करती है।यहाँ अपने उदाहरण है, प्रत्येक प्रदर्शित करने के लिए:

पहली शैली है, जहां funcfoo में कहीं भी दिखाई दे रहा है, कुछ और where खंड में परिभाषित किया जिनमें शामिल हैं:

foo = do ... 
     mapM_ func aList 
     ... 
     return aValue 
    where func x = x + 1 

दूसरी शैली है, जहां func अंदर ही दिखाई दे रहा है let अभिव्यक्ति, जो इस मामले में पूरे do ब्लॉक है:

foo = let func x = x + 1 
     in do 
     ... 
     mapM_ func aList 
     ... 
     return aValue 

और तीसरा शैली को परिभाषित यह do ब्लॉक के अंदर है। इस मामले में, func केवल let के बाद दिखाई देता है; पहले ... में इसे अभी तक परिभाषित नहीं किया गया है।

foo = do ... 
     let func x = x + 1 
     mapM_ func aList 
     ... 
     return aValue 

ओह, और अच्छा उपाय: चूंकि let ... in ... एक अभिव्यक्ति है, आप भी उपयोग कर सकते हैं कहीं भी आप एक अभिव्यक्ति है, कुछ स्थानीय परिभाषाओं नाम है। तो यहाँ एक और उदाहरण है:

foo = do ... 
     let func x = x + 1 in mapM_ func aList 
     ... 
     return aValue 

पहले की तरह, funclet अभिव्यक्ति है, जो इस मामले में यह एक के बाद अभिव्यक्ति, और कहीं नहीं है के अंदर ही दिख रहा है।

+0

धन्यवाद। तीसरा रूप ऐसा लगता है कि यह मुझे उपयोगी होने के लिए 'mapM_' के लिए पर्याप्त लैम्ब्डा फ़ंक्शन को परिभाषित करने की अनुमति देगा। मुझे केवल चिंता है कि यह 'लेट' (मामूली समस्या) में परिभाषित 'func' नाम के साथ शीर्ष-स्तरीय फ़ंक्शन नेमस्पेस को प्रदूषित करता है। – Ralph

+0

@ राल्फ: ठीक है, यह सिर्फ एक बात है कि आप किस क्षेत्र में दिखाना चाहते हैं। यदि आपका 'ऐसा' ब्लॉक इतना बड़ा है कि आपको इसके अंदर नामस्थान को प्रदूषित करने की चिंता करने की ज़रूरत है, तो आपको शायद इसे छोटे टुकड़ों में तोड़ने पर विचार करना चाहिए । :] –

+0

हाँ, यह भी मेरे साथ हुआ था। मैं कुछ कार्यात्मक स्कैला कोड का अनुवाद कर रहा हूं कि कुछ बेवकूफों ने (:-)) उन कार्यों के साथ लिखा जो उनके होने से अधिक लंबे समय तक हैं। – Ralph

3

क्या आपके where फ़ंक्शन के अंत में नहीं होना चाहिए?

इस तरह

:

function aList aValue = do 
    mapM_ func aList 
    return aValue 
    where func x = x + 1 
+0

मुझे यकीन नहीं है। मैं बेहतर पठनीयता के लिए लैम्बडा को एक बहुत ही स्थानीय समारोह में निकालने का कोई तरीका ढूंढना चाहता हूं। अगर मुझे इसे शीर्ष-स्तरीय फ़ंक्शन के अंत में रखना है, जो इसे बहुत कम उपयोग करने योग्य बनाता है। मैं एक हास्केल नोब हूँ। – Ralph

10

एक और विकल्प mapM_ के बजाय forM_ का उपयोग करना है, जो तर्कों के क्रम को फ़्लिप करता है। इसके बाद आप $ ऑपरेटर का उपयोग इस तरह की पिछली लैम्ब्डा अभिव्यक्ति के साथ कर सकते हैं:

do 
    forM_ aList $ \x -> do 
    ... 

    return aValue 
+0

मैंने उस विकल्प को नहीं माना था। मैं यह देखने के लिए फिर से अपना कोड देखूंगा कि वह अधिक पठनीय है या नहीं। अन्य मामलों में जहां मुझे एक मोनैडिक सूची ट्रैवर्सल की आवश्यकता है, लेकिन 'forM_' जैसे कोई सुविधाजनक फ़्लिप संस्करण नहीं है, मैं केवल एक नया फ़ंक्शन बनाने के लिए' फ्लिप 'का उपयोग कर सकता हूं। – Ralph

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