2010-02-08 19 views
32

हास्केल में पैटर्न मिलान क्या है और यह संरक्षित समीकरणों से कैसे संबंधित है?हास्केल पैटर्न मिलान - यह क्या है?

मैंने एक सरल स्पष्टीकरण की कोशिश की है, लेकिन मुझे एक नहीं मिला है।

संपादित करें: कोई भी होमवर्क के रूप में टैग किया गया है। मैं अब स्कूल नहीं जाता, मैं सिर्फ हास्केल सीख रहा हूं और मैं इस अवधारणा को समझने की कोशिश कर रहा हूं। ब्याज से शुद्ध

+4

शायद एफ # में पैटर्न मिलान अवधारणा को भी शामिल करना चाहिए ... –

+1

टन भाषाओं में पैटर्न मिलान होता है, न केवल हास्केल और एफ #। – Joe

+1

यह शुद्ध-कार्यात्मक और बाधा भाषाओं की एक आम विशेषता है। प्रोलॉग, एरलांग और एसएमएल, उदाहरण के लिए। – outis

उत्तर

52

संक्षेप में, पैटर्न गणित में टुकड़े टुकड़े कार्यों को परिभाषित करने की तरह हैं। आप पैटर्न का उपयोग करके विभिन्न तर्कों के लिए विभिन्न फ़ंक्शन निकायों को निर्दिष्ट कर सकते हैं। जब आप कोई फ़ंक्शन कॉल करते हैं, तो उचित तर्क को विभिन्न तर्क पैटर्न के साथ वास्तविक तर्कों की तुलना करके चुना जाता है। अधिक जानकारी के लिए A Gentle Introduction to Haskell पढ़ें।

की तुलना करें: बराबर हास्केल के साथ

Fibonacci sequence

:

fib 0 = 1 
fib 1 = 1 
fib n | n >= 2 
     = fib (n-1) + fib (n-2) 

नोट "n ≥ 2" piecewise समारोह में हास्केल संस्करण में एक गार्ड हो जाता है, लेकिन अन्य दो स्थितियां बस पैटर्न हैं। पैटर्न ऐसी स्थितियां हैं जो मूल्यों और संरचनाओं का परीक्षण करती हैं, जैसे x:xs, (x, y, z), या Just x। एक टुकड़े की परिभाषा में, = या संबंधों के आधार पर स्थितियां (मूल रूप से, कुछ बातें जो कुछ कहती हैं "कुछ और है" पैटर्न बन जाती हैं। गार्ड अधिक सामान्य स्थितियों के लिए अनुमति देते हैं। हम फिर से लिखने सकता fib गार्ड उपयोग करने के लिए:

fib n | n == 0 = 1 
     | n == 1 = 1 
     | n >= 2 = fib (n-1) + fib (n-2) 
+0

इस के लिए एक बेहतर स्पष्टीकरण कभी नहीं देखा! +1। [यह एफ # डॉक्टर] (http://msdn.microsoft.com/en-us/library/dd547125.aspx) भी ठंडा है। – nawfal

3

एक कार्यात्मक भाषा में, पैटर्न मिलान अलग अलग रूपों के खिलाफ एक तर्क की जाँच शामिल है। एक साधारण उदाहरण में सूचियों पर पुनरावर्ती परिभाषित संचालन शामिल है। मैं पैटर्न मिलान की व्याख्या करने के लिए ओकैमल का उपयोग करूंगा क्योंकि यह मेरी पसंद की कार्यात्मक भाषा है, लेकिन अवधारणाएं एफ # और हास्केल, AFAIK में समान हैं।

सूची lst की सूची की गणना करने के लिए फ़ंक्शन की परिभाषा यहां दी गई है। OCaml, एक `` एक सूची में is defined recursively as the empty list [] , or the structure ज :: टी , whereis an element of type एक ( एक being any type we want, such as an integer or even another list), टी is a list (hence the recursive definition), and :: `विपक्ष ऑपरेटर, जो एक तत्व है और एक सूची से बाहर एक नई सूची बनाता है।

तो समारोह इस प्रकार दिखाई देगा:

let rec len lst = 
    match lst with 
    [] -> 0 
    | h :: t -> 1 + len t 

rec एक आपरिवर्तक कि OCaml बताता है कि एक समारोह में ही रिकर्सिवली फोन होगा। उस हिस्से के बारे में चिंता मत करो। match कथन वह है जिसे हम ध्यान केंद्रित कर रहे हैं। OCaml दो पैटर्न - खाली सूची, या h :: t के विरुद्ध lst की जांच करेगा - और उसके आधार पर एक अलग मूल्य लौटाएगा। चूंकि हम जानते हैं कि प्रत्येक सूची इन पैटर्नों में से एक से मेल खाती है, हम आश्वस्त रह सकते हैं कि हमारा कार्य सुरक्षित रूप से वापस आ जाएगा।

ध्यान दें कि भले ही ये दो पैटर्न सभी सूचियों का ख्याल रखेंगे, आप उनके लिए सीमित नहीं हैं। h1 :: h2 :: t जैसे पैटर्न (लंबाई 2 या अधिक की सभी सूचियों से मेल खाते हुए) भी मान्य हैं।

बेशक, पैटर्न का उपयोग पुनरावर्ती परिभाषित डेटा संरचनाओं, या पुनरावर्ती कार्यों तक ही सीमित नहीं है।यहाँ एक (काल्पनिक) समारोह एक नंबर 1 या 2 है कि क्या आप यह बताने के लिए है:

let is_one_or_two num = 
    match num with 
    1 -> true 
    | 2 -> true 
    | _ -> false 

इस मामले में, हमारे पैटर्न के रूपों संख्या खुद को कर रहे हैं। _ एक विशेष पकड़ है - सभी डिफ़ॉल्ट केस के रूप में उपयोग किए जाते हैं, यदि उपर्युक्त पैटर्न में से कोई भी मिलान नहीं करता है।

12

कम से कम हास्केल में पैटर्न मिलान algebraic data types की अवधारणा से गहराई से जुड़ा हुआ है। आप इस प्रकार का डेटा प्रकार की घोषणा कब:

data SomeData = Foo Int Int 
       | Bar String 
       | Baz 

... यह Foo परिभाषित करता है, Bar, और Bazरूप कंस्ट्रक्टर --not "कंस्ट्रक्टर्स" OOP में साथ भ्रमित होने की - कि एक SomeData मूल्य का निर्माण अन्य मूल्यों से बाहर।

पैटर्न मिलान रिवर्स --a पैटर्न में यह कर "deconstruct" होगा उसके घटक टुकड़ों में एक SomeData मूल्य (वास्तव में, मुझे विश्वास है कि पैटर्न मिलान केवल तरह से मूल्यों को निकालने के लिए है की तुलना में ज्यादा कुछ नहीं है हास्केल)।

जब किसी प्रकार के लिए कई कन्स्ट्रक्टर होते हैं, तो आप प्रत्येक पैटर्न के लिए फ़ंक्शन के कई संस्करण लिखते हैं, जिसमें सही कन्स्ट्रक्टर का उपयोग किया जाता है, इस पर निर्भर करता है कि आप सभी संभव निर्माणों से मेल खाने के लिए पैटर्न लिख चुके हैं-- जो आमतौर पर करने के लिए अच्छा अभ्यास है)।

+1

"फ़ंक्शन का एकाधिक संस्करण" वास्तव में केवल एक केस कथन के लिए वाक्यविन्यास चीनी है: http://learnhaskell.blogspot.com/2007/09/lesson-3-case-3.html –

1

पैटर्न मिलान उन दर्दनाक परिचालनों में से एक है जो प्रक्रियात्मक प्रोग्रामिंग पृष्ठभूमि से आते हैं तो किसी के सिर को पाने में मुश्किल होती है। मुझे इसमें प्रवेश करना मुश्किल लगता है क्योंकि डेटा संरचना बनाने के लिए उपयोग किया जाने वाला एक ही वाक्यविन्यास मिलान के लिए उपयोग किया जा सकता है।

एफ # में आप इतनी तरह एक सूची की शुरुआत करने के लिए एक तत्व जोड़ने के लिए विपक्ष ऑपरेटर :: उपयोग कर सकते हैं:

let a = 1 :: [2;3] 
//val a : int list = [1; 2; 3] 

इसी तरह आप सूची को विभाजित करने के तो जैसे एक ही ऑपरेटर का उपयोग कर सकते हैं:

let a = [1;2;3];; 
match a with 
    | [a;b] -> printfn "List contains 2 elements" //will match a list with 2 elements 
    | a::tail -> printfn "Head is %d" a //will match a list with 2 or more elements 
    | [] -> printfn "List is empty" //will match an empty list 
+1

"... एक ही वाक्यविन्यास एक डेटा संरचना बनाने के लिए इस्तेमाल किया जा सकता है मिलान के लिए इस्तेमाल किया जा सकता है "- यह काफी ज्यादा बिंदु है; आप यह जानने के लिए पैटर्न मिलान का उपयोग करते हैं कि मूल्य बनाने के लिए किस कन्स्ट्रक्टर का उपयोग किया गया था - नॉर्मन रैमसे या कैमकैन के उत्तरों को देखें। यह यह समझने में भी मदद करता है कि विपक्ष केवल एक ऐसा कार्य नहीं है जो सूचियों (जैसे लंबाई या संयोजक) पर कार्य करता है, लेकिन एक सूची निर्माता है। बेशक, जैसा कि फिबोनाकी उदाहरण दिखाते हैं, आप 0 या 1 के साथ-साथ कंस या 'जस्ट' (हास्केल से एक आम) जैसे विशिष्ट मूल्यों पर पैटर्न मिलान कर सकते हैं। – Nefrubyr

23

अन्य अच्छे उत्तर हैं, इसलिए मैं आपको एक बहुत ही तकनीकी उत्तर देने जा रहा हूं।

  • "उन्मूलन का निर्माण" का अर्थ है "कैसे का उपयोग करने या एक मूल्य के उपयोग करने के लिए" के अलावा

  • "बीजीय डेटा प्रकार",: पैटर्न मिलान उन्मूलन बीजीय डेटा प्रकार के लिए निर्माण है प्रथम श्रेणी के काम करता है, स्वच्छ, एफ #, हास्केल, या एमएल

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

data StringSeq = Empty     -- the empty sequence 
       | Cat StringSeq StringSeq -- two sequences in succession 
       | Single String   -- a sequence holding a single element 

अब, बातें इस परिभाषा के साथ गलत के सभी प्रकार देखते हैं, लेकिन एक उदाहरण के रूप में यह दिलचस्प है क्योंकि यह मनमाने ढंग से लंबाई के अनुक्रमों के निरंतर समय समामेलन प्रदान करता है। (इसे हासिल करने के अन्य तरीके हैं।) घोषणा Empty, Cat, और Single प्रस्तुत करती है, जो अनुक्रम बनाने के सभी तरीके हैं। (यही कारण है कि हर एक को एक परिचय — चीजें बनाने के लिए एक तरह से निर्माण बना देता है।)

  • आप किसी भी अन्य मूल्यों के बिना एक खाली अनुक्रम बना सकते हैं।
  • Cat के साथ अनुक्रम बनाने के लिए, आपको दो अन्य अनुक्रमों की आवश्यकता है।
  • Single साथ एक दृश्य बनाने के लिए, आप एक तत्व (एक स्ट्रिंग इस मामले में) की जरूरत है

यहाँ पंच लाइन आता है:, उन्मूलन निर्माण, पैटर्न मिलान आप एक दृश्य की जांच और पूछने के लिए एक रास्ता देती है यह प्रश्न आपने किस कन्स्ट्रक्टर के साथ बनाया था?। क्योंकि आपको किसी भी उत्तर के लिए तैयार रहना है, आप प्रत्येक कन्स्ट्रक्टर के लिए कम से कम एक विकल्प प्रदान करते हैं। यहाँ लंबाई समारोह है:

slen :: StringSeq -> Int 
slen s = case s of Empty -> 0 
        Cat s s' -> slen s + slen s' 
        Single _ -> 1 

भाषा के मूल में, सभी पैटर्न मिलान इस case निर्माण पर बनाया गया है। हालांकि, क्योंकि बीजीय डेटा प्रकार और पैटर्न मिलान भाषा का मुहावरे के लिए इतना महत्वपूर्ण है, वहाँ एक समारोह परिभाषा की घोषणा के रूप में पैटर्न मिलान करने के लिए विशेष "वाक्यात्मक चीनी":

slen Empty = 0 
slen (Cat s s') = slen s + slen s' 
slen (Single _) = 1 
इस वाक्यात्मक चीनी के साथ

, पैटर्न मिलान द्वारा गणना समीकरणों द्वारा परिभाषा की तरह दिखती है। (हास्केल समिति ने इसे उद्देश्य पर किया।) और जैसा कि आप अन्य उत्तरों में देख सकते हैं, उस पर एक गार्ड को मारकर case अभिव्यक्ति में समीकरण या विकल्प को विशेषज्ञता देना संभव है। मैं अनुक्रम उदाहरण के लिए एक व्यावहारिक गार्ड के बारे में नहीं सोच सकता, और अन्य उत्तरों में बहुत से उदाहरण हैं, इसलिए मैं इसे वहां छोड़ दूंगा।

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