2011-02-27 11 views
11

में ओपन और बंद यूनियन प्रकार मैं पहली बार ओकैम में देख रहा हूं, जिसमें एफ # और हास्केल के साथ थोड़ी सी पृष्ठभूमि है। इस प्रकार, बहुत परिचित दिखने वाला है, लेकिन एक चीज जो "खुली" और "बंद" यूनियनों की अवधारणा नहीं है (बैकटिक और [< सिंटैक्स के साथ)।ओकैम

इनके लिए क्या उपयोगी हैं और कितनी बार उपयोग किया जाता है?

+1

आप पॉलिमॉर्फिक वेरिएंट का उपयोग क्यों करेंगे, इसके लिए यहां भी जवाब देखें: http://stackoverflow.com/questions/1746743/extending-an-existing-type-in-ocaml – aneccodeal

उत्तर

17

gasche's answer has good advice। मैं खुले और बंद यूनियनों को थोड़ा और समझाऊंगा।

सबसे पहले, आपको दो प्रकार के यूनियनों को अलग करने की आवश्यकता है: मूल रूप (मूल बैकटिक) और पॉलीमोर्फिक वेरिएंट (बैकटिक के साथ)।

  • बेसिक वेरिएंट उत्पादक हैं: यदि आप अलग अलग मॉड्यूल M1 और M2 में एक ही निर्माता नामों के साथ दो प्रकार परिभाषित करते हैं, आप विभिन्न प्रकार की है। M1.Foo और M2.Foo विभिन्न रचनाकार हैं। `Foo हमेशा एक ही निर्माता होता है चाहे आप इसका उपयोग न करें।
  • इसके अलावा, पॉलिमॉर्फिक वेरिएंट सब कुछ मूल रूप से कर सकते हैं और अधिक कर सकते हैं। लेकिन महान शक्ति के साथ बड़ी जटिलता आती है, इसलिए आपको केवल तभी उपयोग करना चाहिए जब आवश्यक और ध्यान से।

एक पॉलिमॉर्फिक प्रकार का वर्णन बताता है कि किस प्रकार के रचनाकारों के पास हो सकता है। लेकिन कई बहुरूप प्रकार भिन्न रूप से ज्ञात नहीं हैं - उनमें (पंक्ति) प्रकार चर शामिल हैं। खाली सूची [] पर विचार करें: इसका प्रकार 'a list है, और इसका उपयोग कई संदर्भों में किया जा सकता है जो 'a पर अधिक विशिष्ट प्रकार निर्दिष्ट करते हैं। उदाहरण के लिए:

# let empty_list = [];; 
val empty_list : 'a list = [] 
# let list_of_lists = [] :: empty_list;; 
val list_of_lists : 'a list list = [[]] 
# let list_of_integers = 3 :: empty_list;; 
val list_of_integers : int list = [3] 

पंक्ति प्रकार चर के लिए समान है। एक खुला प्रकार, [> … ] लिखा गया है, इसमें एक पंक्ति चर है जिसे प्रत्येक बार मान का उपयोग करने के लिए अधिक रचनाकारों को कवर करने के लिए तत्काल किया जा सकता है।

# let foo = `Foo;; 
val foo : [> `Foo ] = `Foo 
# let bar = `Bar;; 
val bar : [> `Bar ] = `Bar 
# let foobar = [foo; bar];; 
val foobar : [> `Bar | `Foo ] list = [`Foo; `Bar] 

सिर्फ इसलिए कि किसी प्रकार में एक निर्माता दिखाई देता है इसका मतलब यह नहीं है कि उस प्रकार के प्रत्येक उपयोग को सभी रचनाकारों को अनुमति देना है। [> …] कहता है कि एक प्रकार में कम से कम इन रचनाकारों के पास होना चाहिए, और दोहरी [< …] कहता है कि इन प्रकार के अधिकांश रचनाकारों में एक प्रकार होना चाहिए।इस समारोह पर विचार करें:

# let h = function `Foo -> `Bar | `Bar -> `Foo;; 
val h : [< `Bar | `Foo ] -> [> `Bar | `Foo ] = <fun> 

hFoo और Bar से निपटने के ही लायक है, इसलिए इनपुट प्रकार अन्य निर्माताओं की अनुमति नहीं कर सकते हैं; लेकिन h को उस प्रकार पर कॉल करना ठीक है जो केवल Foo की अनुमति देता है। इसके विपरीत, hFoo या Bar लौटा सकता है, और किसी भी संदर्भ में h का उपयोग किया जाता है Foo और Bar (और दूसरों को अनुमति दे सकता है) की अनुमति देनी चाहिए।

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

# let hh : 'a -> 'a = function `Foo -> `Bar | `Bar -> `Foo;; 
val hh : [ `Bar | `Foo ] -> [ `Bar | `Foo ] = <fun> 

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

मैं पढ़ने और काम करने की सलाह देता हूं (यानी अपूर्ण में उदाहरणों को दोबारा टाइप करें, सुनिश्चित करें कि आप प्रत्येक चरण को समझें) polymorphic variant tutorial in the Ocaml manual

+0

मुझे इस विषय पर और अधिक सोचना होगा, क्योंकि यह बहुत उन्नत लगता है - लेकिन विस्तृत उत्तर के लिए धन्यवाद। –

11

आप जैक्स Garrigue के पढ़ने के लिए "कोड बहुरूपी वेरिएंट के साथ पुन: उपयोग" की जरूरत है:

http://www.math.nagoya-u.ac.jp/~garrigue/papers/fose2000.html

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

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

+0

धन्यवाद; अब पेपर पढ़ना –

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