2011-11-03 7 views
19

मैं हास्केल में नौसिखिया हूं और आशा करता हूं कि यह सवाल मूर्ख नहीं है।क्या "सूची" विशेष रूप से हास्केल के पैटर्न मिलान में संभाली गई है?

मैं इतना उदाहरण देखा है कि जब मैं एक सूची हो रहा है, मैं व्यक्तिगत चर करने के लिए सूची का बाँध "रचना तत्व" से मेल खाते हैं और करने में सक्षम हूँ:

listSizeDesc :: [a] -> String 
listSizeDesc [] = "Emtpy" 
listSizeDesc (x:xs) = "Something inside" 

हालांकि, मैं कुछ करने की कोशिश जैसे:

foo :: Int -> String 
foo 0 = "Zero" 
foo (n - 1) = "next number is " ++ show n 

यह काम नहीं करता है।

ऐसा लगता है कि दोनों (एन -1) और (x: xs) वर्णन करते हैं कि तर्क "बनाया गया" है और तर्क के लिए "घटक" को बांधता है। जिस तरह से सूची विशेष रूप से रिकर्सन की आसानी के लिए डिज़ाइन की गई है? Coz ऐसा लगता है कि यह मिलान/तर्क-बाध्यकारी तर्क अन्य कार्यों पर लागू नहीं होता है (:)।

+13

निश्चित रूप से एक बेवकूफ सवाल नहीं है। यह एक साथी नौसिखिया के रूप में मेरी समझ है: सूचियां "विशेष" नहीं हैं। पैटर्न मिलान के साथ काम करता है: क्योंकि: सूचियों के लिए एक प्रकार का कन्स्ट्रक्टर है। यह प्रकार के रचनाकारों का काम करता है लेकिन सामान्य कार्यों के लिए नहीं। यह काम कितना अच्छी तरह से समझाया गया है [यहां विकीबुक्स पर] (http://en.wikibooks.org/wiki/Haskell/Pattern_matching) –

+1

जब तक यह अच्छी तरह से पूछा जाता है, तब तक मूर्खतापूर्ण प्रश्न जैसी कोई चीज़ नहीं होती है। – hugomg

+1

संक्षिप्त उत्तर: संख्या –

उत्तर

14

सूची प्रकार एक निर्माता के साथ "योग प्रकार", की तरह कुछ है।

आपका दूसरा उदाहरण पूर्णांक पर एक पैटर्न मिलान है, जो डेटाटाइप परिभाषा नहीं है। पूर्णांक पर, आपके वाक्यविन्यास का उपयोग करके कोई पैटर्न नहीं है।एक तरफ ध्यान दें पर

foo :: Int -> String 
foo 0 = "Zero" 
foo n = "next number is " ++ show (n+1) 

अगर आप की तरह डेटाटाइप्स साथ पूर्णांकों सांकेतिक शब्दों में बदलना:: आप के साथ अपने उदाहरण लिख सकते हैं

data Nat = Zero | Succ Nat deriving (Show) 

तो फिर आप अपने पैटर्न मैच उपयोग कर सकते हैं के रूप में आप शुरू में करना चाहता था।

foo :: Nat -> String 
foo Zero = "Zero" 
foo [email protected](p) = "next number is " ++ show(n) 
यहाँ

पैटर्न Succ(p)n-1 की भूमिका निभाता है।

+0

महान उदाहरण! सबकुछ अब मुझे समझ में आता है: डी धन्यवाद बहुत –

+2

वह अंतिम उदाहरण पीछे की तरफ है। ओपी क्या चाहता है उससे मेल खाने के लिए, पैटर्न सिर्फ 'n' होना चाहिए और फ़ंक्शन को 'Succ n' दिखाना चाहिए। – jwodder

3
moo :: Int -> String 
moo 0 = "Zero" 
moo n = "next number is " ++ show (n + 1) 

n - 1 एक सामान्य कार्य अनुप्रयोग है, पैटर्न नहीं। + के लिए एक अपवाद बनाया गया था और यह वह मॉडल हो सकता है जिसे आप जा रहे हैं। आप

goo :: Int -> String 
goo 0 = "Zero" 
goo (n+1) = "previous number is " ++ show n 

hugs में कुछ लिख सकते हैं; तुम अब भी अगर आप pragma

{-#LANGUAGE NPlusKPatterns#-} 
+5

बीटीडब्लू, उन 'एनप्लसकेपटरर्न' को बहिष्कृत कर दिया गया है, क्योंकि वे कई प्रोग्रामर को भ्रमित करते हैं। देखभाल के साथ प्रयोग करें! इसके अलावा, AFAIK वे केवल सकारात्मक संख्या से मेल खाते हैं। – fuz

+0

हां, यह मेरा मुद्दा था, मुझे लगता है कि स्पष्ट रूप से व्यक्त नहीं किया गया है। – applicative

18

समस्या आपके सामने केवल मिलान कि पैटर्न है डेटा कंस्ट्रक्टर्स साथ काम करता है शामिल हैं ghc के साथ ऐसा कर सकते हैं। एक डेटा कन्स्ट्रक्टर संक्षेप में बहुत सरल है; यह सिर्फ डेटा मूल्यों को लेता है और उन्हें किसी प्रकार की संरचना में एक साथ समूहित करता है। उदाहरण के लिए, data Foo = Bar a b बस डेटा के दो टुकड़े लेता है और उन्हें Foo लेबल के नीचे समूहित करता है। आपके पहले उदाहरण में उपयोग किए जाने वाले (:) फ़ंक्शन केवल एक फ़ंक्शन से अधिक है; यह एक डेटा कन्स्ट्रक्टर है। यह दाएं तर्क को बाएं तर्क जोड़कर एक नई सूची बनाता है।

अब, पैटर्न मिलान केवल इस प्रक्रिया के विपरीत कर रहा है। यह एक डेटाटाइप deconstructs। जब आप अपने पैटर्न में (x:xs) लिखते हैं, तो आप डेटा के दो टुकड़ों को निकाल रहे हैं जो निर्माता मूल रूप से एक साथ सिलाई जाती हैं। इसलिए सभी पैटर्न मिलान उस डेटा को निकालने के लिए करते हैं जो पहले एक कन्स्ट्रक्टर एक साथ सिलाई जाती है।

एक अपवाद है: एन + के पैटर्न। हास्केल 9 8 में, आपको फॉर्म के पैटर्न (एन + के) का उपयोग करने की अनुमति थी। यह एक मनमाना अपवाद था और इसे हाल ही में हटा दिया गया था। यदि आप चाहें, तो आप अभी भी इसका उपयोग कर सकते हैं यदि आप NPlusKPatterns भाषा प्राग्मा शामिल करते हैं। (: के लिए वाक्यात्मक चीनी के साथ)

data List a = 
    cons a (List a) 
    | nil 

आप पहला उदाहरण एक डेटाप्रकार पर एक पैटर्न मैच है:

+0

ग्रेट उत्तर। हालांकि मैंने दिए गए सहज उदाहरण के कारण किसी अन्य उत्तर को "स्वीकार करें" दिया, लेकिन यह उत्तर संदेहजनक है। काश मैं एक ही समय में 2 उत्तरों स्वीकार कर सकता हूं, मुझे लगता है कि दोनों जवाब एक दूसरे के लिए अच्छी प्रशंसा हैं। –

5

पहले से ही कुछ महान उत्तर हैं, इसलिए मैं मुख्य प्रश्न से परेशान नहीं होगा। यह इसका सबसे अच्छा उपयोग नहीं है, लेकिन आप जो करने का प्रयास कर रहे थे वह view patterns के साथ पूरा किया जा सकता है।

{-# LANGUAGE ViewPatterns #-} 

foo :: Int -> String 
foo 0 = "Zero" 
foo (pred -> n) = "Next number is " ++ show n 
4

बस इसे के रूप में बस संभव के रूप में डाल करने के लिए:
एक सूची सचमुच concatenations की एक श्रृंखला है। एक अंक अंकगणितीय ऑपरेशन के परिणाम के बराबर हो सकता है। अंतर यह है कि a : b का परिणाम बस a : b है।


और अधिक विस्तार में:

सूचियों और (:) एक विशेष मामला बिल्कुल नहीं हैं। चलो हमारे अपने:

a = Cat 1 (Cat 2 (Cat 3 End)) 

बस पैटर्न मिलान (x:xs), हम कर सकते हैं पैटर्न मैचों की List2 की तरह:

newTail End = End 
newTail (Cat _ x) = x 

data List2 a = End    -- equivalent of "[]" 
      | Cat a (List2 a) -- non-infix ":" 
    deriving (Show) 

तो [1, 2, 3], जो (1 : (2 : (3 : []))) ==, रूप में लिखा जाएगा

परीक्षण करें:

*Main> tail [1,2,3] 
[2,3] 
*Main> newTail a 
Cat 2 (Cat 3 End)