इसको देखने के कई अच्छे तरीके हैं। मेरे लिए सबसे आसान काम "इंडक्टिव" और "कोइंडिक्टिव परिभाषाओं" के बीच के संबंध के बारे में सोचना है।
एक सेट की एक आगमनात्मक परिभाषा इस तरह से होती है।
सेट "नेट" को सबसे छोटे सेट के रूप में परिभाषित किया गया है जैसे कि "शून्य" नेट में है, और यदि नेट में है "एनसीसी" सूट एन "।
जो निम्नलिखित Ocaml से मेल खाती है
type nat = Zero | Succ of nat
इस परिभाषा के बारे में एक बात ध्यान देने वाली है कि एक संख्या
omega = Succ(omega)
इस सेट का सदस्य नहीं है। क्यों? मान लें कि यह था, अब सेट एन पर विचार करें जिसमें सभी समान तत्व हैं जैसे कि नेट में ओमेगा नहीं है। स्पष्ट रूप से शून्य N में है, और यदि y N में है, तो Succ (y) N में है, लेकिन N Nat से छोटा है जो एक विरोधाभास है। तो, ओमेगा नेट में नहीं है।
या, शायद एक कंप्यूटर वैज्ञानिक के लिए अधिक उपयोगी:
कुछ सेट "ए" को देखते हुए, सेट "लिस्ट ऑफ़" को सबसे छोटे सेट के रूप में परिभाषित किया गया है जैसे कि "निल" ए की सूची में है, और यदि एक्स ए की सूची में है और एक्स "कॉन्स एक्स एक्स" में है की सूची में है।
जो कुछ इस तरह से मेल खाता है
type 'a list = Nil | Cons of 'a * 'a list
यहां ऑपरेटिव शब्द "सबसे छोटा" है। अगर हमने "सबसे छोटा" नहीं कहा, तो हमारे पास यह बताने का कोई तरीका नहीं होगा कि क्या सेट नट में केला है!
फिर,
zeros = Cons(Zero,zeros)
nats की सूची के लिए एक वैध परिभाषा नहीं है, जैसे ओमेगा एक वैध नेट नहीं था।
इस तरह से डेटा को परिभाषित करना हमें उन कार्यों को परिभाषित करने की अनुमति देता है जो पुनरावृत्ति का उपयोग करके उस पर काम करते हैं
let rec plus a b = match a with
| Zero -> b
| Succ(c) -> let r = plus c b in Succ(r)
फिर हम इसके बारे में तथ्यों को साबित कर सकते हैं, जैसे "प्लस एक शून्य =" एक प्रेरण का उपयोग (विशेष रूप से, संरचनात्मक प्रेरण)
हमारा प्रमाण संरचनात्मक प्रेरण द्वारा a पर बढ़ता है।
आधार मामले के लिए शून्य होना चाहिए। plus Zero Zero = match Zero with |Zero -> Zero | Succ(c) -> let r = plus c b in Succ(r)
तो हम जानते हैं plus Zero Zero = Zero
। आज्ञा देना a
। आगमनात्मक परिकल्पना मान लें कि plus a Zero = a
। अब हम दिखाते हैं कि plus (Succ(a)) Zero = Succ(a)
यह स्पष्ट है कि इस plus (Succ(a)) Zero = match a with |Zero -> Zero | Succ(a) -> let r = plus a Zero in Succ(r) = let r = a in Succ(r) = Succ(a)
प्रकार, नेट में plus a Zero = a
सभी के लिए प्रेरण द्वाराa
हम बेशक अधिक दिलचस्प बातें साबित कर सकते हैं, लेकिन यह सामान्य विचार है।
अब तक हमने इंडक्टिवली डिफाइन किए गए डेटा को निपटाया है, जो हमें "सबसे छोटा" सेट देने से मिला। इसलिए अब हम सहिष्णुता से परिभाषित कोडता के साथ काम करना चाहते हैं जो हमें सबसे बड़ा सेट होने की अनुमति देता है।
इसलिए
एक सेट होने दो। सेट "स्ट्रीम ऑफ़" को सबसे बड़े सेट के रूप में परिभाषित किया गया है, जैसे कि x की धारा में प्रत्येक x के लिए x में आदेशित जोड़ी (सिर, पूंछ) होती है जैसे कि सिर एक में है और पूंछ स्ट्रीम में है
हास्केल में हम इसे व्यक्त करेंगे
data Stream a = Stream a (Stream a) --"data" not "newtype"
दरअसल, हास्केल में हम निर्मित सूचियों का सामान्य रूप से उपयोग करते हैं, जो एक ऑर्डर की गई जोड़ी या एक खाली सूची हो सकती है।
data [a] = [] | a:[a]
केला इस प्रकार का सदस्य नहीं है, क्योंकि यह एक आदेशित जोड़ी या खाली सूची नहीं है। लेकिन, अब हम कह सकते हैं
ones = 1:ones
और यह पूरी तरह से मान्य परिभाषा है। Whats अधिक, हम इस सह-डेटा पर सह-पुनरावृत्ति कर सकते हैं। वास्तव में, एक फ़ंक्शन के लिए सह-पुनरावर्ती और पुनरावर्ती होना संभव है। जबकि रिकर्सन को फ़ंक्शन द्वारा डेटा से युक्त डोमेन द्वारा परिभाषित किया गया था , सह-पुनर्संयोजन का अर्थ है कि इसका सह-डोमेन है (सीमा भी कहा जाता है) जो सह-डेटा है। आदिम पुनरावृत्ति का अर्थ हमेशा छोटे डेटा पर "स्वयं को कॉल करना" होता है जब तक कि कुछ सबसे छोटे डेटा तक नहीं पहुंच जाते। आदिम सह-पुनरावृत्ति हमेशा "स्वयं को कॉल करता है" जो आपके पास पहले था उससे अधिक या उसके बराबर डेटा पर।
ones = 1:ones
मुख्य रूप से सह-पुनरावर्ती है। जबकि फ़ंक्शन map
(अनिवार्य भाषाओं में "फॉरच" की तरह) आदिम रूप से पुनरावर्ती (प्रकार) और आदिम रूप से सह-पुनरावर्ती है।
map :: (a -> b) -> [a] -> [b]
map f [] = []
map f (x:xs) = (f x):map f xs
वही फ़ंक्शन के लिए जाता है zipWith
जो एक फ़ंक्शन और सूचियों की एक जोड़ी लेता है और उस फ़ंक्शन का उपयोग करके उन्हें एक साथ जोड़ता है।
zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
zipWith f (a:as) (b:bs) = (f a b):zipWith f as bs
zipWith _ _ _ = [] --base case
कार्यात्मक भाषाओं का क्लासिक उदाहरण फाइबोनैचि अनुक्रम है
fib 0 = 0
fib 1 = 1
fib n = (fib (n-1)) + (fib (n-2))
जो प्राथमिक रूप से पुनरावर्ती है, लेकिन अनंत सूची के रूप में अधिक सुरुचिपूर्ण ढंग से व्यक्त किया जा सकता है
fibs = 0:1:zipWith (+) fibs (tail fibs)
fib' n = fibs !! n --the !! is haskell syntax for index at
इंडक्शन / कोइंडक्शन का एक दिलचस्प उदाहरण यह साबित कर रहा है कि ये दोनों परिभाषाएँ एक ही चीज़ की गणना करती हैं। इसे पाठक के लिए एक अभ्यास के रूप में छोड़ दिया जाता है।