क्या मठ वंशानुगत पदानुक्रमों के लिए एक व्यवहार्य (शायद बेहतर) विकल्प हैं?


20

मैं इस तरह से भिक्षुओं के एक भाषा-अज्ञेय वर्णन का उपयोग करने जा रहा हूं , पहले monoids का वर्णन करता हूं:

एक मोनॉइड (लगभग) फ़ंक्शंस का एक सेट है जो किसी प्रकार को एक पैरामीटर के रूप में लेता है और उसी प्रकार को वापस करता है।

एक मोनाड (लगभग) एक फ़ंक्शन का एक सेट है जो एक आवरण प्रकार को एक पैरामीटर के रूप में लेता है और एक ही आवरण प्रकार को वापस करता है।

ध्यान दें कि वे विवरण हैं, न कि परिभाषाएँ। उस विवरण पर हमला करने के लिए स्वतंत्र महसूस करें!

तो एक OO भाषा में, एक संन्यासी ऑपरेशन रचनाओं की अनुमति देता है जैसे:

Flier<Duck> m = new Flier<Duck>(duck).takeOff().flyAround().land()

ध्यान दें कि मोनड निहित वर्गों के बजाय उन कार्यों के शब्दार्थों को परिभाषित और नियंत्रित करता है।

परंपरागत रूप से, एक OO भाषा में हम उन शब्दार्थों को प्रदान करने के लिए एक वर्ग पदानुक्रम और विरासत का उपयोग करेंगे। तो हम एक होगा Birdतरीकों के साथ वर्ग takeOff(), flyAround()और land(), और बतख उन वारिस होगा।

लेकिन फिर हम उड़ान रहित पक्षियों के साथ परेशानी में पड़ जाते हैं, क्योंकि वह penguin.takeOff()असफल हो जाता है। हमें एक्सेप्शन थ्रोइंग और हैंडलिंग का सहारा लेना होगा।

इसके अलावा, एक बार जब हम कहते हैं कि पेंगुइन एक है Bird, तो हम कई उत्तराधिकारियों के साथ समस्याओं में भाग लेते हैं, उदाहरण के लिए यदि हमारे पास एक पदानुक्रम है Swimmer

अनिवार्य रूप से हम वर्गों को श्रेणियों में डालने की कोशिश कर रहे हैं (श्रेणी सिद्धांत लोगों से माफी के साथ), और व्यक्तिगत कक्षाओं के बजाय श्रेणी द्वारा शब्दार्थ को परिभाषित करें। लेकिन भिक्षुओं को पदानुक्रम की तुलना में ऐसा करने के लिए बहुत स्पष्ट तंत्र की तरह लगता है।

तो इस मामले में, हमारे पास Flier<T>ऊपर के उदाहरण जैसा एक सनक होगा:

Flier<Duck> m = new Flier<Duck>(duck).takeOff().flyAround().land()

... और हम कभी भी तुरंत नहीं करेंगे Flier<Penguin>। हम इसे रोकने के लिए स्थैतिक टाइपिंग का भी उपयोग कर सकते हैं, शायद एक मार्कर इंटरफ़ेस के साथ। या जमानत के लिए रनटाइम क्षमता-जाँच। लेकिन वास्तव में, एक प्रोग्रामर को कभी भी पेंगुइन को फ्लियर में नहीं डालना चाहिए, उसी अर्थ में उन्हें कभी भी शून्य से विभाजित नहीं करना चाहिए।

इसके अलावा, यह आम तौर पर लागू होता है। एक उड़ाका पक्षी होना जरूरी नहीं है। उदाहरण के लिए Flier<Pterodactyl>, या Flier<Squirrel>, उन व्यक्तिगत प्रकारों के शब्दार्थ को बदले बिना।

एक बार जब हम एक कंटेनर पर संयोजकीय कार्यों द्वारा शब्दार्थों को वर्गीकृत करते हैं - बजाय टाइप पदानुक्रम के साथ - यह कक्षाओं के साथ पुरानी समस्याओं को हल करता है जो एक विशेष पदानुक्रम में "किस तरह का, तरह का नहीं" फिट होते हैं। यह आसानी से और स्पष्ट रूप से एक वर्ग के लिए कई शब्दार्थों की अनुमति देता है, Flier<Duck>साथ ही साथ Swimmer<Duck>। ऐसा लगता है कि हम वर्ग पदानुक्रम के साथ व्यवहार को वर्गीकृत करके एक प्रतिबाधा बेमेल के साथ संघर्ष कर रहे हैं। मोनाड्स इसे सुरुचिपूर्ण ढंग से संभालते हैं।

तो मेरा सवाल यह है कि जिस तरह से हम विरासत के ऊपर रचना के पक्ष में आए हैं, क्या यह विरासत से अधिक मठों का पक्ष लेने के लिए भी है?

(BTW मुझे यकीन नहीं था कि यह यहाँ या COMP विज्ञान में होना चाहिए, लेकिन यह एक व्यावहारिक मॉडलिंग समस्या की तरह लगता है। लेकिन शायद वहाँ से बेहतर हो।)


1
मुझे यकीन नहीं है कि मैं समझता हूं कि यह कैसे काम करता है: एक गिलहरी और बतख एक ही तरह से नहीं उड़ते हैं - इसलिए उन कक्षाओं में "फ्लाई एक्शन" को लागू करने की आवश्यकता है ... और उड़ाका को गिलहरी और बतख बनाने के लिए एक विधि की आवश्यकता होती है उड़ना ... शायद एक सामान्य फ़्लियर इंटरफ़ेस में ... उफ़ एक मिनट रुकें ... क्या मुझे कुछ याद आया?
assylias

इंटरफेस क्लास इनहेरिटेंस की तुलना में अलग हैं, क्योंकि इंटरफेस क्षमताओं को परिभाषित करते हैं जबकि कार्यात्मक विरासत वास्तविक व्यवहार को परिभाषित करता है। "इनहेरिटेंस से अधिक रचना" में भी, इंटरफेस को परिभाषित करना अभी भी एक महत्वपूर्ण तंत्र है (जैसे बहुरूपता)। इंटरफेस एक ही बहु विरासत की समस्याओं में नहीं चलते हैं। साथ ही, प्रत्येक फ़्लायर कंटेनर के उपयोग के लिए "getFlightSpeed ​​()" या "getManuverability ()" जैसी क्षमता गुण (एक इंटरफ़ेस और बहुरूपता के माध्यम से) प्रदान कर सकता है।
रोब

3
क्या आप यह पूछने की कोशिश कर रहे हैं कि क्या पैरामीट्रिक बहुरूपता का उपयोग करना हमेशा बहुरूपता का पर्यायवाची विकल्प है?
कैओसपांडियन

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

6
मैं आपके monoids और monads के विवरण को नहीं समझता। मोनोइड्स की प्रमुख संपत्ति यह है कि इसमें एक साहचर्य बाइनरी ऑपरेशन शामिल है (फ्लोटिंग-पॉइंट जोड़, पूर्णांक गुणन, या स्ट्रिंग संयोजन)। एक इकाई है कि समर्थन करता है एक अमूर्त है उन्हें क्रमबद्ध किसी क्रम में विभिन्न (संभवतः निर्भर) संगणना।
रफालविंड

जवाबों:


15

संक्षिप्त उत्तर नहीं है , मठ विरासत वंशानुगत (इसे उपप्रकार बहुरूपता के रूप में भी जाना जाता है) का विकल्प नहीं हैं। आप पैरामीट्रिक बहुरूपता का वर्णन करते प्रतीत होते हैं , जो कि भिक्षुओं का उपयोग करते हैं, लेकिन ऐसा करने के लिए केवल एक चीज नहीं है।

जहां तक ​​मैं उन्हें समझता हूं, मठों के पास विरासत से कोई लेना-देना नहीं है। मैं कहूंगा कि दो चीजें अधिक-या-कम ऑर्थोगोनल हैं: वे अलग-अलग समस्याओं का समाधान करने का इरादा रखते हैं, और इसी तरह:

  1. उनका उपयोग सहक्रियात्मक रूप से कम से कम दो इंद्रियों में किया जा सकता है:
    • टाइपेकेलोपेडिया की जांच करें , जो हास्केल के कई प्रकारों को शामिल करता है। आप देखेंगे कि उनके बीच विरासत जैसे रिश्ते हैं। उदाहरण के लिए, मोनाड को एपेक्टिव से उतारा जाता है जो खुद फन्नेकार से उतारा जाता है।
    • मोनाड्स के उदाहरण हैं डेटा प्रकार वर्ग पदानुक्रम में भाग ले सकते हैं। याद रखें, मोनाड एक इंटरफ़ेस की तरह अधिक है - किसी दिए गए प्रकार के लिए इसे लागू करना आपको डेटा प्रकार के बारे में कुछ चीजें बताता है, लेकिन सब कुछ नहीं।
  2. एक का उपयोग करने की कोशिश दूसरे को करना मुश्किल और बदसूरत होगा।

अंत में, हालांकि यह आपके प्रश्न के लिए महत्वपूर्ण है, आपको यह जानने में दिलचस्पी हो सकती है कि भिक्षुओं के पास रचना करने के कुछ अविश्वसनीय शक्तिशाली तरीके हैं; अधिक जानने के लिए मोनाड ट्रांसफार्मर पर पढ़ें। हालाँकि, यह अभी भी अनुसंधान का एक सक्रिय क्षेत्र है क्योंकि हम (और हमारे द्वारा, मेरा मतलब है कि लोग मुझसे बेहतर 100000x हैं) ने भिक्षुओं की रचना करने के लिए शानदार तरीके नहीं निकाले हैं, और ऐसा लगता है कि कुछ सन्यासी मनमाने ढंग से रचना नहीं करते हैं।


अब अपने प्रश्न को निथारने के लिए (क्षमा करें, मैं इसके लिए मददगार होने का इरादा रखता हूं, न कि आपको बुरा महसूस कराने के लिए): मुझे लगता है कि कई संदिग्ध परिसर हैं जिन पर मैं कुछ प्रकाश डालने का प्रयास करूंगा।

  1. एक मोनड फ़ंक्शंस का एक सेट है जो एक कंटेनर प्रकार को एक पैरामीटर के रूप में लेता है और उसी कंटेनर प्रकार को वापस करता है।

    जी नहीं, यह है Monadहास्केल में: एक पैरामिट्रीकृत प्रकार m aके एक कार्यान्वयन के साथ return :: a -> m aऔर (>>=) :: m a -> (a -> m b) -> m b, निम्नलिखित कानूनों को संतोषजनक:

    return a >>= k  ==  k a
    m >>= return  ==  m
    m >>= (\x -> k x >>= h)  ==  (m >>= k) >>= h
    

    मोनाड के कुछ उदाहरण हैं जो कंटेनर नहीं हैं ( (->) b), और कुछ कंटेनर हैं जो (और नहीं बनाया जा सकता है) मोनाड के उदाहरण हैं ( Setक्योंकि, प्रकार वर्ग की कमी के कारण)। तो "कंटेनर" अंतर्ज्ञान एक गरीब है। अधिक उदाहरणों के लिए इसे देखें ।

  2. तो एक OO भाषा में, एक संन्यासी ऑपरेशन रचनाओं की अनुमति देता है जैसे:

      Flier<Duck> m = new Flier<Duck>(duck).takeOff().flyAround().land()
    

    नहीं, बिलकुल नहीं। उस उदाहरण के लिए मोनाड की आवश्यकता नहीं है। इसके लिए आवश्यक सभी प्रकार के मिलान इनपुट और आउटपुट प्रकार हैं। यहाँ इसे लिखने का एक और तरीका है जो इस बात पर जोर देता है कि यह सिर्फ फ़ंक्शन अनुप्रयोग है:

    Flier<Duck> m = land(flyAround(takeOff(new Flier<Duck>(duck))));
    

    मेरा मानना ​​है कि यह एक पैटर्न है जिसे "धाराप्रवाह इंटरफ़ेस" या "विधि श्रृंखलन" के रूप में जाना जाता है (लेकिन मुझे यकीन नहीं है)।

  3. ध्यान दें कि मोनड निहित वर्गों के बजाय उन कार्यों के शब्दार्थों को परिभाषित और नियंत्रित करता है।

    डेटा प्रकार जो कि मोनैड्स भी हैं (और लगभग हमेशा करते हैं!) में ऐसे ऑपरेशन होते हैं जो मोनडर्स से असंबंधित होते हैं। यहाँ तीन कार्यों से बना एक हास्केल उदाहरण है, []जिस पर कुछ भी नहीं है, जिसमें भिक्षुओं का कोई लेना-देना नहीं है: []"ऑपरेशन के शब्दार्थों को परिभाषित और नियंत्रित करता है" और "निहित वर्ग" नहीं करता है, लेकिन यह एक सनक बनाने के लिए पर्याप्त नहीं है:

    \predicate -> length . filter predicate . reverse
    
  4. आपने सही ढंग से नोट किया है कि क्लास पदानुक्रम का उपयोग करने से लेकर चीजों को मॉडल करने तक की समस्याएं हैं। हालाँकि, आपके उदाहरण कोई भी प्रमाण प्रस्तुत नहीं करते हैं जो कि भिक्षु कर सकते हैं:

    • उस सामान पर एक अच्छा काम करें जो विरासत में अच्छा है
    • उस सामान पर एक अच्छा काम करें जो विरासत में खराब है

3
धन्यवाद! मेरे लिए बहुत प्रक्रिया है। मुझे बुरा नहीं लगता - मैं अंतर्दृष्टि की बहुत सराहना करता हूं। मुझे बुरे विचारों को ले जाने में बुरा लगेगा। :) (स्टैकएक्सचेंज के पूरे बिंदु पर जाता है!)
रोब

1
@RobY आपका स्वागत है! वैसे, अगर आपने इसके बारे में पहले नहीं सुना है, तो मैं LYAH की सिफारिश करता हूं क्योंकि यह सीखने के लिए एक बहुत अच्छा स्रोत है (और हास्केल!) क्योंकि इसमें बहुत सारे उदाहरण हैं (और मुझे लगता है कि उदाहरण के टन करना सबसे अच्छा तरीका है। टैकल मोनाड्स)।

यहाँ `बहुत है; मैं टिप्पणियों पर ज़ोर नहीं देना चाहता, लेकिन कुछ टिप्पणियां: # 2 land(flyAround(takeOff(new Flier<Duck>(duck))))काम नहीं करती (कम से कम OO में) क्योंकि उस निर्माण को फ़्लियर के विवरण में प्राप्त करने के लिए ब्रेकिंग इनकैप्सुलेशन की आवश्यकता होती है। कक्षा में opertions का पीछा करते हुए, फ्लेयर का विवरण छिपा रहता है, और यह इसके शब्दार्थ को संरक्षित कर सकता है। यही कारण है कि हास्केल में एक मोनाड बांधता है (a, M b)और (M a, M b)ऐसा नहीं है कि मोनाड को "कार्रवाई" फ़ंक्शन के लिए अपने राज्य को उजागर नहीं करना पड़ता है।
रॉब

# 1, दुर्भाग्यवश मैं हास्केल में मोनाड के सख्त बचाव को धुंधला करने की कोशिश कर रहा हूं , क्योंकि हास्केल को कुछ भी मैप करने से बड़ी समस्या होती है: कंस्ट्रक्टर्स पर रचना सहित फ़ंक्शन रचना , जिसे आप जावा के साथ एक पैदल यात्री भाषा में आसानी से नहीं कर सकते। तो unitनिहित प्रकार पर (ज्यादातर) कंस्ट्रक्टर bindबन जाता है , और (ज्यादातर) एक संकलित संकलन समय ऑपरेशन (यानी शुरुआती बाध्यकारी) बन जाता है जो "कार्रवाई" कार्यों को कक्षा में रखता है। यदि आपके पास प्रथम श्रेणी के कार्य हैं, या एक फ़ंक्शन <ए, मोनाद <बी >> वर्ग है, तो एक bindविधि देर से बाध्यकारी कर सकती है, लेकिन मैं उस दुरुपयोग को आगे ले जाऊंगा। ;)
रोब

# 3 सहमत हैं, और यही इसकी सुंदरता है। यदि Flier<Thing>उड़ान के शब्दार्थ को नियंत्रित करता है, तो यह बहुत सारे डेटा और संचालन को उजागर कर सकता है जो उड़ान के शब्दार्थ को बनाए रखते हैं, जबकि "मोनाड" -सम्पीडेंट शब्दार्थ वास्तव में इसे श्रृंखलाबद्ध और संक्षिप्त बनाने के बारे में हैं। उन चिंताओं के साथ (और मैं जिन लोगों का उपयोग कर रहा हूं, वे नहीं कर सकते हैं), वर्ग के अंदर की चिंताएं हैं: उदाहरण Resource<String>के लिए एक httpStatus संपत्ति है, लेकिन स्ट्रिंग नहीं है।
रोब

1

तो मेरा सवाल यह है कि जिस तरह से हम विरासत के ऊपर रचना के पक्ष में आए हैं, क्या यह विरासत से अधिक मठों का पक्ष लेने के लिए भी है?

गैर-ओओ भाषाओं में, हाँ। अधिक परंपरागत OO भाषाओं में, मैं नहीं कहूंगा।

मुद्दा यह है कि अधिकांश भाषाओं में टाइप विशेषज्ञता नहीं है, जिसका अर्थ है कि आप बना नहीं सकते हैं Flier<Squirrel>औरFlier<Bird> विभिन्न कार्यान्वयन है। आपको कुछ करना होगा static Flier Flier::Create(Squirrel)(और फिर प्रत्येक प्रकार के लिए अधिभार)। बदले में, जब भी आप एक नया जानवर जोड़ते हैं, तो आपको इस प्रकार को संशोधित करना होगा, और काम करने के लिए कोड की थोड़ी बहुत नकल करने की संभावना है।

ओह, और कुछ भाषाओं में नहीं (उदाहरण के लिए C #) public class Flier<T> : T {}अवैध है। इसका निर्माण भी नहीं होगा। अधिकांश, यदि सभी ओओ प्रोग्रामर Flier<Bird>अभी भी उम्मीद नहीं करेंगे Bird


टिप्पणी के लिए धन्यवाद। मेरे पास कुछ और विचार हैं, लेकिन सिर्फ तुच्छ रूप से, भले ही Flier<Bird>एक मानकीकृत कंटेनर है, कोई भी इसे एक Bird(!) List<String>नहीं माना जाएगा एक सूची नहीं एक स्ट्रिंग है।
रोब

@RobY - Flierनहीं है सिर्फ एक कंटेनर। यदि आप इसे सिर्फ एक कंटेनर मानते हैं, तो आप कभी क्यों सोचेंगे कि यह वंशानुक्रम के उपयोग की जगह ले सकता है?
तेलस्तीन

मैं तुम्हें वहाँ खो दिया ... मेरी बात यह है कि मोनाद एक बढ़ाया कंटेनर है। Animal / Bird / Penguinआमतौर पर एक बुरा उदाहरण है, क्योंकि यह सभी प्रकार के शब्दार्थों में लाता है। एक व्यावहारिक उदाहरण एक REST-ish monad है जिसका हम उपयोग कर रहे हैं: (या कुछ अन्य प्रकार) के Resource<String>.from(uri).get() Resourceशीर्ष पर शब्दार्थ जोड़ता है String, इसलिए यह स्पष्ट रूप से नहीं है String
रोब

@ रॉबी - लेकिन फिर यह किसी भी तरह से विरासत से संबंधित नहीं है।
तेलस्टिन

सिवाय इसके कि यह एक अलग तरह का कंटेंट है। मैं स्ट्रिंग को संसाधन में रख सकता हूं, या मैं एक संसाधनस्ट्रिंग वर्ग को सार कर सकता हूं और विरासत का उपयोग कर सकता हूं। मेरा विचार यह है कि एक चेयरिंग कंटेनर में क्लास लगाना अमूर्त व्यवहार का एक बेहतर तरीका है, इसे विरासत के साथ क्लास पदानुक्रम में रखना। तो "कोई तरीका नहीं संबंधित" के अर्थ में "बदलने / न मानने" - हाँ।
रोब
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.