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>
h
Foo
और Bar
से निपटने के ही लायक है, इसलिए इनपुट प्रकार अन्य निर्माताओं की अनुमति नहीं कर सकते हैं; लेकिन h
को उस प्रकार पर कॉल करना ठीक है जो केवल Foo
की अनुमति देता है। इसके विपरीत, h
Foo
या 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।
आप पॉलिमॉर्फिक वेरिएंट का उपयोग क्यों करेंगे, इसके लिए यहां भी जवाब देखें: http://stackoverflow.com/questions/1746743/extending-an-existing-type-in-ocaml – aneccodeal