2014-07-22 5 views
7

मैं सोच रहा हूँ करने के लिए किस हद तक मैं विशेष रूप से डेटा destructuring के संबंध में हास्केल (GHC का उपयोग) में सूक्ष्म अनुकूलन के आम उप भाव के बारे में चिंता करने की ज़रूरत है।आम उप भाव पहचान करने के लिए मैं के रूप में पैटर्न का उपयोग करना चाहिए जब?

उदाहरण के लिए, दो क्रमित सूचियों के विलय के लिए इस कोड पर विचार करें:

merge :: Ord a => [a] -> [a] -> [a] 
merge [] bs = bs 
merge as [] = as 
merge (a:as) (b:bs) = 
    case compare a b of 
    LT -> a : merge as (b:bs) -- (1) 
    EQ -> a : merge as bs 
    GT -> b : merge (a:as) bs -- (2) 

GHC पहचान लेगा कि (2) में (a:as) और (b:bs) पर (1) इनपुट पैरामीटर के रूप में ही कर रहे हैं? या, मैं "के रूप में" पैटर्न, उदा .: इस्तेमाल करना चाहिए

merge a'@(a:as) b'@(b:bs) = 
    ... 
    LT -> a : merge as b' 
    ... 
    GT -> b : merge a' bs 

और सामान्य रूप में जब GHC डेटा निर्माण में में आम उप भाव को पहचान सकते हैं और जब मैं यह करने में मदद करने की जरूरत है?

+8

मैं उन्हें हर समय उपयोग करता हूं। यह स्पष्ट करता है कि आप केवल इनपुट का उपयोग कर रहे हैं। – Dan

उत्तर

7

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

module Test where 


merge1 :: Ord a => [a] -> [a] -> [a] 
merge1 [] bs = bs 
merge1 as [] = as 
merge1 (a:as) (b:bs) = case compare a b of 
    LT -> a : merge1 as (b:bs) 
    EQ -> a : merge1 as bs 
    GT -> b : merge1 (a:as) bs 


merge2 :: Ord a => [a] -> [a] -> [a] 
merge2 [] bs = bs 
merge2 as [] = as 
merge2 [email protected](a:as) [email protected](b:bs) = case compare a b of 
    LT -> a : merge2 as ys 
    EQ -> a : merge2 as bs 
    GT -> b : merge2 xs bs 
-O2 और -ddump-simpl साथ

, और बाद विवेकपूर्ण संपादन का एक बहुत, का नाम बदलने को संकलित करता है, तो चर, मेटाडाटा और एनोटेशन, और विभिन्न अन्य चाल की अलग करना आप

merge2_2 :: Ord a => a -> [a] -> [a] -> [a] 
merge2_2 = \ ordInst x y z -> case z of _ { 
     [] -> (x:y); 
     (w:v) -> case compare ordInst x w of _ { 
      LT -> x : merge2_1 ordInst y w v; 
      EQ -> x : merge2 ordInst y v; 
      GT -> w : merge2_2 ordInst x y v 
     } 
    } 

merge2_1 :: Ord a => [a] -> a -> [a] -> [a] 
merge2_1 = \ ordInst x y z -> case x of _ { 
     [] -> (y:z); 
     (w:v) -> case compare ordInst w y of _ { 
      LT -> w : merge2_1 ordInst v y z; 
      EQ -> w : merge2 ordInst v z; 
      GT -> y : merge2_2 ordInst w v z 
     } 
    } 

merge2 :: Ord a => [a] -> [a] -> [a] 
merge2 = \ ordInst x y -> case x of wild { 
     [] -> y; 
     (w:v) -> case y of _ { 
      [] -> wild; 
      (z:zs) -> case compare ordInst w z of _ { 
       LT -> w : merge2_1 ordInst v z zs; 
       EQ -> w : merge2 ordInst v zs; 
       GT -> z : merge2_2 ordInst w v zs 
      } 
     } 
    } 


merge1_2 :: Ord a => a -> [a] -> [a] -> [a] 
merge1_2 = \ ordInst x y z -> case z of _ { 
     [] -> (x:y); 
     (w:v) -> case compare ordInst x w of _ { 
      LT -> x : merge1_1 ordInst y w v; 
      EQ -> x : merge1 ordInst y v; 
      GT -> w : merge1_2 ordInst x y v 
     } 
    } 

merge1_1 :: Ord a => [a] -> a -> [a] -> [a] 
merge1_1 = \ ordInst x y z -> case x of _ { 
     [] -> (y:z); 
     (w:v) -> case compare ordInst w y of _ { 
      LT -> w : merge1_1 ordInst v y z; 
      EQ -> w : merge1 ordInst v z; 
      GT -> y : merge1_2 ordInst w v z 
     } 
    } 

merge1 :: Ord a => [a] -> [a] -> [a] 
merge1 = \ ordInst x y -> case x of wild { 
     [] -> y; 
     (w:v) -> case y of _ { 
      [] -> wild; 
      (z:zs) -> case compare ordInst w z of _ { 
       LT -> w : merge1_1 ordInst v z zs; 
       EQ -> w : merge1 ordInst v zs; 
       GT -> z : merge1_2 ordInst w v zs 
      } 
     } 
    } 

कौन सा की तरह कुछ पर पहुंच सकते हैं, एक diffing उपकरण के साथ तुलना के बाद, मुझसे कहता है कि इन दोनों परिभाषाओं के बीच अंतर केवल सिरों पर संख्या हैकाफ़ंक्शन नाम। तो हां, ऑप्टिमाइज़ेशन लागू करने के बाद जीएचसी कम से कम सूचियों के मामले में आपके लिए इन पैटर्न को समझ सकता है। हालांकि, मैं अब भी उन्हें प्रयोग क्योंकि वहाँ हमेशा मामलों किनारे कर रहे हैं की सिफारिश करेंगे, और यदि आप उन्हें तब प्रयोग करते हैं आप संकलक कुछ जटिल करने के लिए पर भरोसा करने की जरूरत नहीं है। इसका यह भी अर्थ है कि भले ही ऑप्टिमाइज़ेशन सक्षम नहीं हैं, फिर भी आपके कोड में उस अनुकूलन होगा। यह एक छोटे से परिवर्तन की तरह लग सकता है, लेकिन इस समारोह एक आंतरिक पाश में समाप्त होता है या संरचनाओं आप पर काम कर रहे बहुत बड़े हैं अगर यह एक महत्वपूर्ण प्रदर्शन प्रभाव हो सकता है। साथ ही, मुझे लगता है कि क्षेत्रों की एक बड़ी संख्या के साथ निर्माताओं के लिए यह अक्सर "का निर्माण" फ़ॉर्म का उल्लेख करने का कोई नाम करने के लिए सिर्फ अधिक सुविधाजनक है।

Here's the full core dump if you're interested। असल में, मैंने कम कमरे लेने के लिए लाइनों में शामिल होने से शुरुआत की, फिर टाइप हस्ताक्षरों में अनावश्यक शोर हटा दिया, योग्य मॉड्यूल नाम हटा दिए, [Something] एनोटेशन के सभी नामों का नाम बदलकर merge2_$smerge2 से merge2_2 पर बदल दिया गया, सभी स्थानीय प्रकार के हस्ताक्षर हटा दिए गए, फिर नामकरण शुरू किया सब्लिमे टेक्स्ट के अद्भुत एकाधिक कर्सर सुविधा का उपयोग कर। मैं, प्रकार नाम के साथ शुरू कर दिया उन सब को बस a करने का नाम बदलने, तो x, y, z, w, v को चर नाम रखा, और zs (मैं रचनात्मक हूँ, मैं नहीं कर रहे हैं?), : के सभी आवेदनों को बनाया ऑपरेटर इंफिक्स ने Rec क्षेत्रों को हटा दिया, और स्टाइल के कुछ और बिट्स बाद में मुझे आउटपुट मिला जो आपने ऊपर देखा था।

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