2009-11-28 24 views
15

Type classes जेनेरिक और पुन: प्रयोज्य कार्यों को एक बहुत ही संगत, कुशल और एक्स्टेंसिबल तरीके से लिखने की एक बड़ी संभावना प्रतीत होता है। लेकिन अभी भी नहीं "मुख्यधारा-भाषा" उन्हें प्रदान करता है - इसके विपरीत: Concepts, जो काफी समान विचार हैं, को अगले C++ से बाहर रखा गया है!टाइप क्लास के साथ क्या गलत है?

टाइपक्लास के खिलाफ तर्क क्या है? जाहिरा तौर पर कई भाषाओं इसी तरह की समस्याओं से निपटने के लिए एक तरह से तलाश कर रहे हैं: .NET IComparable जो

T Max<T>(T a, T b) where T : IComparable<T> { // } 

जैसे कार्यों के सभी प्रकार है कि इंटरफ़ेस को लागू पर काम करने की अनुमति की तरह सामान्य बाधाओं और इंटरफेस की शुरुआत की।

स्काला बजाय लक्षण के संयोजन का उपयोग करता और इतने implicit parameters/दृश्य सीमा, जो स्वत: सामान्य कार्यों के लिए पारित कर रहे हैं कहा जाता है।

लेकिन यहां दिखाए गए दोनों अवधारणाओं के बहुत नुकसान हैं - इंटरफेस विरासत-आधारित हैं और इस प्रकार संकेत के कारण अपेक्षाकृत धीमी है और इसके अलावा मौजूदा प्रकार को लागू करने की कोई संभावना नहीं है।

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

इसके बजाय लागू पैरामीटर नियमित इंटरफेस/लक्षणों के साथ असंगत हैं।

प्रकार वर्गों के साथ, वहाँ एक समस्या (छद्म कोड)

typeclass Monoid of A where 
    static operator (+) (x : A, y : A) : A 
    static val Zero : A 
end 

instance Int of Monoid where 
    static operator (+) (x : Int, y : Int) : Int = x + y 
    static val Zero : Int = 0 
end 

तो क्यों न हम प्रकार वर्गों का उपयोग नहीं करते नहीं हो सकता है? क्या उनके बाद गंभीर नुकसान हैं?

संपादित करें: कृपया स्ट्रक्चरल टाइपिंग, शुद्ध सी ++ टेम्पलेट्स या बतख टाइपिंग के साथ टाइपक्लास को भ्रमित न करें। एक टाइपक्लास स्पष्ट रूप से तत्काल प्रकारों द्वारा तत्काल तत्काल सम्मेलन द्वारा संतुष्ट नहीं है। इसके अलावा यह उपयोगी कार्यान्वयन ले सकता है और न केवल एक इंटरफ़ेस परिभाषित करता है।

+3

नेट एक प्रकार की कक्षा का समर्थन करता है: नया। मुझे लगता है कि वे लागू नहीं किए गए हैं क्योंकि कार्यान्वयन की लागत की तुलना में नेट क्या है 'अब के लिए पर्याप्त है'। –

+0

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

+0

@ स्टेव जेसॉप: मेरी टिप्पणी विशेष रूप से आपकी पोस्ट पर लागू नहीं होती है (यह वास्तव में एक बहुत ही उपयोगी उत्तर है) - मैं बस संभावना को रोकना चाहता था आम तौर पर सवाल गलतफहमी का। – Dario

उत्तर

9

अवधारणाओं बाहर रखा गया है, क्योंकि समिति नहीं लगता था कि यह उन्हें सही समय में हो सकता है, और क्योंकि वे रिहाई के लिए आवश्यक समझा जाता था। ऐसा नहीं है कि वे नहीं सोचते कि वे एक अच्छा विचार हैं, वे नहीं सोचते कि सी ++ के लिए उनकी अभिव्यक्ति परिपक्व है: http://herbsutter.wordpress.com/2009/07/21/trip-report/

स्टेटिक प्रकार आपको किसी ऑब्जेक्ट को किसी फ़ंक्शन पर सहेजने से रोकने की कोशिश करते हैं, जो नहीं करता समारोह की आवश्यकताओं को पूरा नहीं करते हैं। सी ++ में यह एक बड़ा बड़ा सौदा है, क्योंकि उस समय ऑब्जेक्ट को कोड द्वारा एक्सेस किया जाता है, वहां कोई जांच नहीं है कि यह सही बात है।

अवधारणाओं आप टेम्पलेट पैरामीटर, कि टेम्पलेट की आवश्यकताओं को संतुष्ट नहीं करता गुजर को रोकने के लिए प्रयास करें। लेकिन उस समय टेम्पलेट पैरामीटर को कंपाइलर द्वारा एक्सेस किया गया है, वहां पहले से ही है यह जांच कर रहा है कि यह सही बात है, यहां तक ​​कि अवधारणाओं के बिना भी। यदि आप इसे किसी ऐसे तरीके से उपयोग करने का प्रयास करते हैं जो इसका समर्थन नहीं करता है, तो आपको एक कंपाइलर त्रुटि मिलती है [*]। भारी टेम्पलेट-कोड का उपयोग करने के मामले में आपको कोण ब्रैकेट से भरे तीन स्क्रीन मिल सकती हैं, लेकिन सिद्धांत रूप में यह एक सूचनात्मक संदेश है। एक असफल संकलन से पहले त्रुटियों को पकड़ने की आवश्यकता रनटाइम पर अपरिभाषित व्यवहार से पहले त्रुटियों को पकड़ने की आवश्यकता से कम जरूरी है।

अवधारणाएं टेम्पलेट इंटरफेस निर्दिष्ट करना आसान बनाती हैं जो एकाधिक इंस्टीटेशंस पर काम करेगी। यह महत्वपूर्ण है, लेकिन फ़ंक्शन इंटरफेस निर्दिष्ट करने से बहुत कम दबाने वाली समस्या है जो कई कॉलों पर काम करेगी।

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

[*] आमतौर पर। उदाहरण के लिए कुछ अपवाद हैं, उदाहरण के लिए सी ++ टाइप सिस्टम वर्तमान में इनपुट इटरेटर का उपयोग करने से नहीं रोकता है जैसे कि यह एक आगे इटरेटर था। इसके लिए आपको इटेटरेटर लक्षणों की आवश्यकता है। अकेले बतख टाइपिंग आपको उस वस्तु को पार करने से नहीं रोकती है जो चलती है, तैरती है और quacks, लेकिन करीबी निरीक्षण पर वास्तव में उन चीजों में से कोई भी नहीं करता है जिस तरह एक बतख करता है, और यह जानकर आश्चर्यचकित हो जाता है कि आपने सोचा था ;-)

+0

"आपके प्रश्न के उत्तर में - कोई भी औपचारिक बयान 'मैं इस इंटरफ़ेस को कार्यान्वित करता हूं' का एक बड़ा नुकसान होता है, जिसके लिए कार्यान्वयन से पहले इंटरफ़ेस का आविष्कार किया जाना चाहिए।" मुझे नहीं लगता कि यह टाइपक्लास के बारे में सच है। थर्ड-पार्टी कोड कह सकता है "टाइप ए ए पर टाइपक्लास बी * * पर लागू होता है, यहां बताया गया है ..." –

+0

पर्याप्त मेला। मैंने मुख्य रूप से उत्तर दिया क्योंकि मुझे पता चला कि अवधारणाओं को किसी प्रकार के "प्रकार वर्गों के खिलाफ तर्क" के कारण खींचा नहीं गया था। मैं हास्केल नहीं कर सकता, और मैंने सोचा कि इस प्रकार के वर्गों को प्रकार के साथ घोषित किया जाना था। तो मुझे लगता है कि आपको कोई रुख नहीं चुनना है - आप इसे उस व्यक्ति को छोड़ दें जो दूसरे के साथ एक का उपयोग करना चाहता है, और मुझे लगता है कि आवश्यक व्यवहार को लागू करने के लिए कुछ संदर्भों में यह प्रकार ज्ञात हो सकता है, लेकिन यह नहीं होना चाहिए दूसरों में जाना जाता है। इस मामले में मुझे कोई अनुमान नहीं है, कोई महत्वपूर्ण नुकसान नहीं है। –

4

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

मुझे लगता है कि टाइपक्लास अधिक शक्तिशाली हैं, क्योंकि abstract base classes की तरह, वे आपको अतिरिक्त रूप से उपयोगी कोड निर्दिष्ट करते हैं (अन्य प्रकार के लिए दूसरों के संदर्भ में एक अतिरिक्त विधि एक्स को परिभाषित करते हैं जो अन्यथा बेसक्लास से मेल खाते हैं लेकिन एक्स को परिभाषित नहीं करते हैं खुद) - विरासत सामान के बिना कि एबीसी (इंटरफेस से अलग) लगभग अनिवार्य रूप से ले जाते हैं। लगभग अनिवार्य रूप से, उदाहरण के लिए, पाइथन के एबीसी "विश्वास करते हैं" कि वे अवधारणा के संदर्भ में विरासत को शामिल करते हैं ... लेकिन, वास्तव में, उन्हें विरासत-आधारित नहीं होना चाहिए (कई लोग केवल उपस्थिति की जांच कर रहे हैं और गो के इंटरफेस की तरह कुछ तरीकों का हस्ताक्षर)।

क्यों एक भाषा डिजाइनर (जैसे कि पाइथन के मामले में गिडो) भेड़िये के एबीसी के रूप में "भेड़ के कपड़ों में भेड़िये" चुनने के लिए, अधिक सरल हास्केल जैसी टाइपक्लास पर 2002 के बाद से प्रस्तावित किया गया था , जवाब देने के लिए यह एक कठिन सवाल है। आखिरकार, ऐसा नहीं है कि पाइथन के पास हास्केल से उधार लेने की अवधारणाओं के खिलाफ कोई अनुपालन है (उदाहरण के लिए, सूची समझ/जनरेटर अभिव्यक्तियों - पायथन को यहां एक द्वंद्व की आवश्यकता है, जबकि हास्केल नहीं करता है, क्योंकि हास्केल "आलसी" है)। सबसे अच्छी परिकल्पना जो मैं पेशकश कर सकता हूं वह यह है कि, अब तक, अधिकांश प्रोग्रामर के लिए विरासत इतनी परिचित है कि अधिकांश भाषा डिजाइनरों को लगता है कि वे चीजों को कास्टिंग करके आसानी से स्वीकृति प्राप्त कर सकते हैं (हालांकि गो के डिजाइनरों को ऐसा करने के लिए सराहना की जानी चाहिए)।

+4

के नीचे मेरा लंबा उत्तर देखें, पाइथन को कम से कम आंशिक रूप से एबीसी मिला क्योंकि हास्केल ने गिडो के दिमाग को दर्द दिया। कम से कम, मुझे यह याद है। –

-3

एक Matroid, जो है हम क्या कर (logcally और नहीं मौखिक रूप से एक Matroid कह) को परिभाषित प्रयास करें, और यह अभी भी एक सी struct की तरह होने की संभावना कुछ है। Liskov principle (नवीनतम ट्यूरिंग पदक विजेता) भी सार भी स्पष्ट है, भी सैद्धांतिक, कम वास्तविक डेटा और अधिक शुद्ध सैद्धांतिक वर्ग प्रणाली का इलाज हो जाता है, Handson व्यावहारिक problemsolving के लिए, संक्षेप में यह नजर जो PROLOG, कोड के बारे में कोड के बारे में कोड के बारे में कोड की तरह लग रही थी। ..एक बार एक एल्गोरिदम अनुक्रम और यात्रा का वर्णन करता है जिसे हम पेपर या ब्लैकबोर्ड पर समझते हैं। निर्भर करता है कि आपके पास कौन सा लक्ष्य है, न्यूनतम कोड या सबसे सार के साथ समस्या को हल करना।

+0

क्षमा करें - आप क्या कहने की कोशिश कर रहे हैं? हास्केल को देखो - न्यूनतम कोड ** के साथ हल की गई समस्या ** आमतौर पर सबसे सार है। – Dario

+0

Wahuh ??????????????????? –

+0

अमूर्त बकवास उद्धृत करते हुए: "चलो क्यू (एक्स) टाइप टी के ऑब्जेक्ट्स एक्स के बारे में साबित संपत्ति होने दें। फिर क्यू (वाई) ऑब्जेक्ट्स वाई के प्रकार के लिए सत्य होना चाहिए जहां एस टी का एक उप प्रकार है।" आरोपी होने के सवाल से संबंधित यह मेरी बात है –

0

टाइपक्लास के खिलाफ तर्क क्या है?

नई भाषा सुविधाओं पर विचार करते समय संकलक लेखकों के लिए कार्यान्वयन जटिलता हमेशा चिंता का विषय है। सी ++ ने पहले से ही उस गलती की है और परिणामस्वरूप हमें पहले से ही बगड़ी सी ++ कंपाइलर्स का सामना करना पड़ा है।

इंटरफेस विरासत आधारित है और इस तरह अपेक्षाकृत अविवेक के कारण धीमी गति से कर रहे हैं और इसके अलावा वहाँ दे एक मौजूदा प्रकार उन्हें

सही नहीं लागू की कोई संभावना नहीं है। OCaml के संरचनात्मक रूप से टाइप वस्तु प्रणाली को देखो, उदाहरण के लिए: foo समारोह किसी भी प्रकार कि आवश्यक bar तरीका प्रदान करता है की किसी भी वस्तु को स्वीकार करता है

# let foo obj = obj#bar;; 
val foo : < bar : 'a; .. > -> 'a = <fun> 

है।

एमएल के उच्च-आदेश मॉड्यूल सिस्टम के लिए ही। दरअसल, उस वर्ग और प्रकार के वर्गों के बीच औपचारिक समानता भी होती है। अभ्यास में, वर्गों को छोटे पैमाने पर अबास्ट्रक्शंस जैसे ऑपरेटर ओवरलोडिंग के लिए बेहतर होता है जबकि उच्च-ऑर्डर मॉड्यूल बड़े पैमाने पर अबास्ट्रक्शंस के लिए बेहतर होते हैं जैसे ओकासाकी के कतारों पर कटे जाने योग्य सूचियों के पैरामीटरकरण।

क्या उनके बाद गंभीर नुकसान हैं?

अपना खुद का उदाहरण, सामान्य अंकगणित देखें। एफ # वास्तव में INumeric इंटरफेस के लिए विशेष रूप से उस विशेष मामले को संभाल सकता है। एफ # Matrix प्रकार भी उस दृष्टिकोण का उपयोग करता है।

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

प्रश्न निश्चित रूप से होना चाहिए: क्या कोई भी के लिए प्रकार कक्षाओं को अपनाने के लिए एक आकर्षक केस बना सकता है?

0

लेकिन फिर भी कोई "मुख्यधारा-भाषा" प्रदान करता है [प्रकार कक्षाएं।]

जब यह प्रश्न पूछा गया था, यह सच हो सकता है। आज, हास्केल और क्लोजर जैसी भाषाओं में बहुत अधिक रुचि है। हास्केल में टाइप क्लास (class/instance) हैं, क्लोजर 1.2+ में protocols (defprotocol/extend) है।

[प्रकार कक्षाओं] के खिलाफ तर्क क्या है?

मुझे नहीं लगता कि प्रकार के वर्ग अन्य polymorphism तंत्र की तुलना में निष्पक्ष "बदतर" हैं; वे सिर्फ एक अलग दृष्टिकोण का पालन करें।तो असली सवाल यह है कि, क्या वे एक विशेष प्रोग्रामिंग भाषा में अच्छी तरह फिट बैठते हैं?

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


आइए अब कुछ मुख्यधारा प्रोग्रामिंग भाषाओं के लिए टाइप क्लास पर विचार करें।

हास्केल: यह कहने की कोई आवश्यकता नहीं है कि इस भाषा में प्रकार वर्ग है।

Clojure: जैसा कि ऊपर कहा, Clojure प्रोटोकॉल के रूप में प्रकार वर्गों की तरह कुछ है।

सी ++: जैसा कि आप अपने आप को कहा है, अवधारणाओं सी ++ 11 विनिर्देश से हटा दिया गया।

इसके विपरीत: अवधारणाएं, जो काफी समान विचार हैं, को अगले सी ++ से बाहर रखा गया है!

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

सी #: भाषा संस्करण 3 के साथ, सी # अनिवार्य रूप से ऑब्जेक्ट उन्मुख और कार्यात्मक प्रोग्रामिंग प्रतिमानों का एक संकर बन गया है। भाषा में एक जोड़ा गया जो संकल्पनात्मक रूप से टाइप वर्गों के समान ही है: विस्तार विधियां। मुख्य अंतर यह है कि आप (प्रतीत होता है) मौजूदा तरीकों से नए तरीकों को जोड़ रहे हैं, इंटरफेस नहीं।

(माना जाता है कि एक्सटेंशन विधि तंत्र लगभग हास्केल के instance … where वाक्यविन्यास के रूप में सुरुचिपूर्ण नहीं है। एक्सटेंशन विधियां एक प्रकार से "वास्तव में" संलग्न नहीं होती हैं, उन्हें एक वाक्य रचनात्मक परिवर्तन के रूप में लागू किया जाता है। अंत में, यह नहीं करता है एक बहुत बड़ी व्यावहारिक फर्क।)

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

(VB.NET:। माइक्रोसॉफ्ट कर दिया गया है "सह-विकसित" C# और VB.NET भाषाओं कुछ समय के लिए है, तो के बारे में सी # मेरी बयान VB.NET के लिए मान्य होने के लिए, भी हो)

जावा: मुझे जावा बहुत अच्छी तरह से नहीं पता है, लेकिन सी ++, सी # और जावा भाषाओं में, यह शायद "शुद्ध" ओओ भाषा है। मैं नहीं देखता कि कक्षाएं इस भाषा में स्वाभाविक रूप से कैसे फिट होंगी।

एफ #: मुझे why type classes might never get introduced into F# समझाते हुए एक फोरम पोस्ट मिला है। यह स्पष्टीकरण इस तथ्य के आसपास केंद्रित है कि एफ # नाममात्र है, न कि एक संरचनात्मक प्रकार प्रणाली। (हालांकि मुझे यकीन नहीं है कि यह एफ # के प्रकार के वर्गों के लिए पर्याप्त कारण नहीं है।)

1

मुझे बोल्ड शुरू करने दें: मैं इसे रखने की प्रेरणा पूरी तरह समझता हूं और कुछ लोगों की प्रेरणा को समझ नहीं सकता इसके खिलाफ बहस करने के लिए ...

आप क्या चाहते हैं nonvirtual ad hoc polymorphism।

  • तदर्थ: कार्यान्वयन भिन्न हो सकते हैं
  • nonvirtual: प्रदर्शन के कारणों के लिए; संकलन प्रेषण

शेष मेरी राय में चीनी है।

सी ++ में टेम्पलेट्स के माध्यम से पहले से ही पॉलीमोर्फिज्म है। हालांकि "अवधारणाएं" स्पष्ट करती हैं कि उपयोगकर्ता द्वारा परिभाषित इकाई किस प्रकार की विज्ञापन पॉलिमॉर्फिक कार्यक्षमता का उपयोग किया जाता है।

सी # बस इसे करने का कोई तरीका नहीं है। एक दृष्टिकोण जो गैर-वर्चुअल नहीं होगा: यदि फ्लोट जैसे प्रकार केवल "अनौपचारिक" या "IAddable" (...) जैसे कुछ लागू करेंगे, तो हम कम से कम एक सामान्य न्यूनतम, अधिकतम, lerp लिखने में सक्षम होंगे और उस क्लैंप, मैपेंज, बेजियर (...) के आधार पर। हालांकि यह तेज़ नहीं होगा। आप उसे नहीं चाहते हैं। यह शायद नहीं है कि ज्यादा एक ओवरहेड की बढ़ेगी बाद से नेट वैसे भी JIT संकलन करता भी List<MyClass> (मूल्य और संदर्भ प्रकार के मतभेद के कारण) के लिए की तुलना में List<int> के लिए अलग कोड उत्पन्न करता है: इस फिक्सिंग की

तरीके विज्ञापन पॉलीमोर्फिक भागों के लिए भी अलग कोड उत्पन्न करते हैं। सी # भाषा को इसे व्यक्त करने के लिए बस एक तरीका चाहिए। एक तरीका वह है जो आपने स्केच किया है।

एक और तरीका समारोह एक तदर्थ बहुरूपी फ़ंक्शन का उपयोग करने के लिए प्रकार की कमी को जोड़ने के लिए होगा:

U SuperSquare<T, U>(T a) applying{ 
     nonvirtual operator (*) T (T, T) 
     nonvirtual Foo U (T) 
    } 
    { 
     return Foo(a * a); 
    } 
बेशक आप अधिक से अधिक की कमी लग सकती है जब बार फू का उपयोग करता है को लागू करने की

। तो आप एक तंत्र को कई बाधाओं का नाम दे सकते हैं जो आप नियमित रूप से उपयोग करते हैं ... हालांकि यह फिर से चीनी है और इसे देखने का एक तरीका सिर्फ टाइपक्लास अवधारणा का उपयोग करना होगा ...

नाम देना कई बाधाओं एक प्रकार वर्ग को परिभाषित करने की तरह है, लेकिन मैं सिर्फ संक्षिप्त नाम तंत्र के कुछ प्रकार के रूप में यह को देखने के लिए चाहते हैं - समारोह प्रकार की कमी की एक मनमाना वसूली के लिए चीनी:

// adhoc is like an interface: it is about collecting signatures 
    // but it is not a type: it dissolves during compilation 
    adhoc AMyNeeds<T, U> 
    { 
     nonvirtual operator (*) T (T, T) 
     nonvirtual Foo U (T) 
    } 

    U SuperSquare<T, U>(T a) applying AMyNeeds<T, U>   
    { 
     return Foo(a * a); 
    } 

कुछ जगह पर "मुख्य" सभी प्रकार के तर्क ज्ञात हैं और सबकुछ ठोस हो जाता है और इसे एक साथ संकलित किया जा सकता है।

क्या अभी भी गुम है क्या विभिन्न कार्यान्वयन बनाने की कमी है। ऊपरी उदाहरण में हम केवल पॉलिमॉर्फिक फ़ंक्शंस का उपयोग करते हैं और सभी को पता है ...

कार्यान्वयन उसके बाद फिर से विस्तार के तरीकों के रास्ते का अनुसरण कर सकते हैं - किसी भी बिंदु पर किसी भी वर्ग में कार्यक्षमता जोड़ने के करने की क्षमता में:

public static class SomeAdhocImplementations 
{ 
    public nonvirtual int Foo(float x) 
    { 
     return round(x); 
    } 
} 

मुख्य में आप अब लिख सकते हैं:

int a = SuperSquare(3.0f); // 3.0 * 3.0 = 9.0 rounded should return 9 

कंपाइलर सभी "nonvirtual" विज्ञापन कार्यों की जांच करता है, एक अंतर्निहित फ्लोट (*) ऑपरेटर और int Foo (float) दोनों पाता है और इसलिए उस रेखा को संकलित करने में सक्षम है।

विज्ञापन का पॉलीमोर्फिज्म निश्चित रूप से नीचे आता है कि आपको प्रत्येक संकलन समय प्रकार के लिए पुन: संकलित करना होगा ताकि सही कार्यान्वयन सम्मिलित हो जाएं। और शायद आईएल समर्थन नहीं करता है कि एक डीएल में डाल दिया जा रहा है। लेकिन हो सकता है कि वे वैसे भी इस पर काम करें ...

मुझे एक प्रकार के वर्ग के निर्माण की अनावश्यकता की कोई वास्तविक आवश्यकता नहीं है। यदि संकलन पर कुछ भी असफल हो जाता है तो हमें बाधाओं की त्रुटियां मिलती हैं या यदि उन्हें "adhoc" कोडक्लॉक के साथ एक साथ जोड़ दिया गया है तो त्रुटि संदेश और भी पठनीय हो सकता है।

MyColor a = SuperSquare(3.0f); 
    // error: There are no ad hoc implementations of AMyNeeds<float, MyColor> 
    // in particular there is no implementation for MyColor Foo(float) 

लेकिन निश्चित रूप से एक प्रकार के वर्ग/"एडोक पॉलीमोर्फिज्म इंटरफ़ेस" का अस्थिरता भी सोचने योग्य है। त्रुटि संदेश तब बताएगा: "The AMyNeeds constraint of SuperSquare has not been matched. AMyNeeds is available as StandardNeeds : AMyNeeds<float, int> as defined in MyStandardLib"। अन्य तरीकों के साथ एक वर्ग में कार्यान्वयन करना भी संभव होगा और समर्थित इंटरफेस की सूची में "adhoc इंटरफ़ेस" जोड़ें।

लेकिन विशेष भाषा डिज़ाइन से स्वतंत्र: मुझे उन्हें एक तरफ या दूसरे जोड़ने का नकारात्मक हिस्सा नहीं दिख रहा है। स्थाई रूप से टाइप की गई भाषाओं को हमेशा अभिव्यक्तिशील शक्ति की सीमा को धक्का देना होगा, क्योंकि वे बहुत कम अनुमति देकर शुरू होते हैं, जो अभिव्यक्तिशील शक्ति का एक छोटा सेट होता है, एक सामान्य प्रोग्रामर संभव होने की उम्मीद करता ...

tldr : मैं तुम्हारे पक्ष में हूं। इस तरह की सामग्री मुख्यधारा में स्थाई रूप से टाइप की गई भाषाओं में बेकार है। हास्केल ने रास्ता दिखाया।

+0

कोई भी विभिन्न संदर्भों में int Foo (float x) को अलग-अलग करना चाहता है। सुपरस्कायर को तब पता होना चाहिए कि कौन सी लेता है। इस अतिरिक्त फीचर की आवश्यकता क्यों होगी और क्यों हैस्केल में टाइपक्लास क्यों दिखते हैं, इस बारे में उचित चर्चा करना अच्छा होगा। –

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