2013-07-15 11 views
10

http://lisperati.com/haskell/ht4.html पर लेखक ऐसे कार्यों को दिखाता है जो एक साधारण एसवीजी फ़ाइल से बहुभुज पढ़ते हैं। मैं अधिकांश कोड को समझता हूं, हालांकि मुझे आश्चर्य हुआ कि फ़ंक्शनहास्केल फ़ंक्शन गार्ड फ़ंक्शन पैरामीटर की तुलना में अन्य मानों पर कैसे काम कर सकते हैं?

let readPoint :: String -> Point 
     readPoint s | Just [x,y] <- matchRegex (mkRegex "([0-9.]+),([0-9.]+)") s = (read x,read y) 

अधिक समझने योग्य रूप में फिर से लिखना संभव है। मैंने पाया कि लाइन थोड़ा सा परेशान है क्योंकि गार्ड को फ़ंक्शन के पैरामीटर (इस मामले में "रीडपॉइंट") पर काम करना चाहिए, लेकिन यहां गार्ड स्पष्ट रूप से MatchRegex के परिणाम पर काम करता है।

तो क्या कोई इस के पीछे जादू को समझा सकता है?

और क्या इसे एक और समझने योग्य रूप में फिर से लिखा जा सकता है?

उत्तर

9

आप गार्ड के बारे में सोच सकते हैं बदलने के लिए। गार्ड में अभिव्यक्ति वैध बूलियन अभिव्यक्ति हो सकती है, जैसे कि कथन में। इसका मतलब है कि आप किसी भी मूल्य और कार्यों का दायरा उपयोग कर सकते हैं।

उदाहरण के लिए, आप निम्नलिखित पुनर्लेखन कर सकते हैं:

foo x | abc = ... 
     | def = ... 
     | otherwise = ... 

रूप

foo x = if abc then ... else if def then ... else ... 

हम भी साथ verbosely इस में थोड़ा और अधिक लिख सकते हैं case बल्कि if से:

foo x = case abc of 
    True -> ... 
    False -> case def of 
    True -> ... 
    False -> ... 

आखिरकार, if स्वयं सिंटैक्स sug है एक मामले के लिए ar! case के संदर्भ में सबकुछ लिखना यह देखना आसान बनाता है कि एक ही चीज़ के लिए अलग-अलग विशेषताएं सिंटैक्स चीनी कैसे होती हैं।

दूसरी अभिव्यक्ति स्पष्ट रूप से समझ में आती है भले ही परिस्थितियों को मौजूदा चर (abc और def) संदर्भ पैरामीटर x के बजाय संदर्भित करता है; गार्ड सिर्फ उसी तरह काम करते हैं।

आप उदाहरण थोड़ा और जटिल हैं क्योंकि यह "pattern guards" नामक एक्सटेंशन का उपयोग करता है। इसका मतलब है कि गार्ड सिर्फ एक बूलियन से अधिक हो सकता है - यह एक पैटर्न से मेल खाने का भी प्रयास कर सकता है। यदि पैटर्न मेल खाता है, तो गार्ड सफल होता है (उदा। वह True के साथ गार्ड के समान है); अन्यथा, गार्ड मिलान करने में विफल रहता है (बस False प्राप्त करने की तरह)।

हम निम्नलिखित के रूप में यह फिर से लिखने की कल्पना कर सकते:

readPoint s | Just [x, y] <- matchRegex (mkRegex "...") s = ... 
      | otherwise = ... 

रूप

readPoint s = case matchRegex (mkRegex "...") s of 
       Just [x, y] -> ... 
       _ -> ... 

आप इस और सामान्य गार्ड की case संस्करण के बीच समानांतर देख सकते हैं। पैटर्न गार्ड सिर्फ उबलते पैटर्न के बजाय मनमानी पैटर्न में विलुप्त होने का विस्तार करते हैं। वहाँ समारोह के तर्कों का उपयोग करने के लिए सीमित करने के लिए कोई कारण नहीं है -

फिर, मुझे यकीन है कि आप इस बात से सहमत हूँ कि यह समझ में आता है अनुमति देने के लिए case बयान में किसी भी अभिव्यक्ति कर रहा हूँ। गार्ड के लिए भी यही सच है क्योंकि वे वास्तव में सिंटैक्स चीनी हैं।

+3

उत्कृष्ट! यह याद रखना हमेशा अच्छा होता है कि हास्केल में काफी कुछ सब कुछ मामला और लैम्ब्डा अभिव्यक्तियों के लिए सिंटैक्टिक चीनी है। – leftaroundabout

5

इसे पैटर्न गार्ड कहा जाता है - इसके बारे में here पढ़ें।

यह बराबर है

को
readPoint :: String -> Point 
readPoint s = case matchRegex (mkRegex "([0-9.]+),([0-9.]+)") s of 
        Just [x,y] -> (read x,read y) 

विचार है कि आप कष्टप्रद नेस्टेड मामले बयान से छुटकारा पा सकते है। पैटर्न का उपयोग करते हुए रक्षा करता है आप की तरह

readPoint :: String -> Point 
readPoint s | Just [x,y] <- matchRegex (mkRegex "([0-9.]+),([0-9.]+)") s = (read x,read y) 
      | Just [x] <- matchRegex (mkRegex "([0-9.]+)") s = (read x,0) 
      | otherwise = (0,0) 

कुछ कर सकते हैं एक अगर बयान के लिए सिर्फ वाक्य रचना चीनी के रूप में अधिक वर्बोज़

readPoint :: String -> Point 
readPoint s = case matchRegex (mkRegex "([0-9.]+),([0-9.]+)") s of 
        Just [x,y] -> (read x,read y) 
        Nothing -> case matchRegex (mkRegex "([0-9.]+)") s of 
            Just [x] -> (read x,0) 
             Nothing -> (0,0) 
संबंधित मुद्दे

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