28

यह Why am I getting "Non-exhaustive patterns in function..." when I invoke my Haskell substring function?हास्केल में, गैर-संपूर्ण पैटर्न संकलन-समय त्रुटियों क्यों नहीं हैं?

की एक अनुवर्ती मैं समझता हूँ कि -Wall का उपयोग कर, GHC गैर संपूर्ण पैटर्न के खिलाफ चेतावनी दे सकता है। मैं सोच रहा हूँ क्या यह डिफ़ॉल्ट रूप से एक संकलन समय त्रुटि यह देखते हुए कि यह स्पष्ट रूप से एक आंशिक समारोह को परिभाषित करने के हमेशा संभव है नहीं कर पीछे कारण बताया गया है:

f :: [a] -> [b] -> Int 
f [] _ = error "undefined for empty array" 
f _ [] = error "undefined for empty array" 
f (_:xs) (_:ys) = length xs + length ys 

सवाल GHC-विशिष्ट नहीं है।

यह क्योंकि ...

  • कोई भी विश्लेषण इस तरह का प्रदर्शन करने के लिए एक हास्केल संकलक लागू करने के लिए करना चाहता था है?
  • एक गैर-संपूर्ण पैटर्न खोज कुछ ढूंढ सकता है लेकिन सभी मामलों में नहीं?
  • आंशिक रूप से परिभाषित कार्यों को वैध माना जाता है और अक्सर दिखाया गया है कि ऊपर दिखाए गए निर्माण को लागू नहीं किया जाए? यदि यह मामला है, तो क्या आप मुझे समझा सकते हैं कि गैर-संपूर्ण पैटर्न सहायक/वैध क्यों हैं?

उत्तर

33

मामलों में जहां आप कोई आपत्ति नहीं है कि एक पैटर्न मैच समझी जाने वाली है कर रहे हैं। उदाहरण के लिए, जबकि इस इष्टतम कार्यान्वयन नहीं हो सकता है, मुझे नहीं लगता कि अगर यह संकलन नहीं लगा कि यह मदद मिलेगी है:

fac 0 = 1 
fac n | n > 0 = n * fac (n-1) 

इस गैर संपूर्ण है (ऋणात्मक संख्याओं किसी भी मामले से मेल नहीं खाते) वास्तव में फैक्टोरियल फ़ंक्शन के सामान्य उपयोग के लिए कोई फर्क नहीं पड़ता।

यह भी नहीं आम तौर पर संकलक के लिए तय करने के लिए अगर एक पैटर्न मैच संपूर्ण है संभव हो सकता है:

mod2 :: Integer -> Integer 
mod2 n | even n = 0 
mod2 n | odd n = 1 

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

+4

एक और मामला आम मामला एक गार्ड/केस/शाखा के अंदर लैम्ब्डा स्टेटमेंट होगा। आप जानते हैं कि तर्क का एक निश्चित रूप है क्योंकि आप किस शाखा में हैं, इसलिए लैम्बडा में इसे शामिल करना अनावश्यक है। –

+1

मुझे नहीं लगता कि इसे अन्यथा लिखा जाना चाहिए। यह एक महान mod2 परिभाषा है भले ही संकलक सोचता है कि यह गैर-संपूर्ण है। मैं इस सवाल पर पहुंचा क्योंकि मुझे यह त्रुटि एक फाइब फ़ंक्शन लिखने में मिली है जिसे नकारात्मक पूर्णांक के लिए परिभाषित नहीं किया जाना चाहिए। –

+0

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

12

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

अपने प्रश्न के तीसरे भाग के लिए के रूप में:

मैं कभी कभी कार्य करता है जो मिलकर काम करते हैं और गुण जो आप आसानी से हास्केल में व्यक्त नहीं कर सकते हो जाते हैं की एक संख्या लिखें। कम से कम इनमें से कुछ कार्यों में गैर-संपूर्ण पैटर्न होते हैं, आमतौर पर 'उपभोक्ता'। यह आता है, उदाहरण के लिए उन कार्यों में जो एक दूसरे के 'सॉर्ट-ऑफ' उलटा होते हैं।

एक खिलौना उदाहरण:

duplicate :: [a] -> [a] 
duplicate [] = [] 
duplicate (x:xs) = x : x : xs 

removeDuplicates :: Eq a => [a] -> [a] 
removeDuplicates [] = [] 
removeDuplicates (x:y:xs) | x == y = x : removeDuplicates xs 

अब यह देखने के लिए कि removeDuplicates (duplicate as)as के बराबर है (जब भी तत्व प्रकार Eq में है) बहुत आसान है, लेकिन सामान्य रूप में duplicate (removeDuplicates bs), दुर्घटना के कारण उसकी एक विषम संख्या हैं तत्वों या लगातार 2 तत्व भिन्न होते हैं। यदि यह क्रैश नहीं होता है, तो ऐसा इसलिए होता है क्योंकि bs को पहले स्थान पर duplicate द्वारा उत्पादित किया गया था (या द्वारा उत्पादित किया जा सकता था!

तो हम निम्नलिखित कानून (मान्य नहीं हास्केल) है:

removeDuplicates . duplicate == id 
duplicate . removeDuplicates == id (for values in the range of duplicate) 

अब, अगर आप गैर संपूर्ण पैटर्न यहाँ रोकना चाहते हैं, आप removeDuplicates वापसी Maybe [a] कर सकता है, या लापता के लिए त्रुटि संदेश जोड़ने मामलों। तुम भी

newtype DuplicatedList a = DuplicatedList [a] 

duplicate :: [a] -> DuplicatedList a 
removeDuplicates :: Eq a => DuplicatedList a -> [a] 
-- implementations omitted 

की तर्ज पर कुछ कर सकते हैं इस के लिए आवश्यक है, क्योंकि आप आसानी से व्यक्त कर सकते हैं नहीं 'भी लंबाई की एक सूची जा रहा है, तत्व बराबर होने की क्रमागत जोड़ी के साथ' हास्केल प्रकार प्रणाली में (जब तक आप ओलेग न हों :)

लेकिन यदि आप removeDuplicates निर्यात नहीं करते हैं तो मुझे लगता है कि यहां गैर-संपूर्ण पैटर्न का उपयोग करना ठीक है। जैसे ही आप इसे निर्यात करते हैं, आप इनपुट पर नियंत्रण खो देंगे और लापता मामलों से निपटना होगा!

+0

मुझे लगता है कि आप निकालें डुप्लीकेट्स (x: y: xs) | x == y = x: हटाएं xs डुप्लिकेट करता है। – gawi

+0

धन्यवाद, मैंने इसे ठीक किया! – yatima2975

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