क्या प्रोग्रामिंग लैंग्वेज में नीचे टाइप होने का कोई कारण है?


49

एक निचला प्रकार एक प्रकार है जो मुख्य रूप से गणितीय प्रकार के सिद्धांत में दिखाई देता है। इसे खाली प्रकार भी कहा जाता है। यह एक प्रकार है जिसका कोई मूल्य नहीं है, लेकिन सभी प्रकारों का एक उपप्रकार है।

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

एक प्रोग्रामिंग भाषा में इस अजीब प्रकार के होने का क्या मतलब है? यह आम नहीं है, लेकिन यह कुछ में मौजूद है, जैसे कि स्काला और लिस्प।


2
@SgegeBorsch: क्या आप इसके बारे में सुनिश्चित हैं? बेशक सी में कोई भी स्पष्ट रूप से एक voidडेटा को परिभाषित नहीं कर सकता है ...
बेसिल स्टायरनेविच

3
@BasileStarynkevitch प्रकार का कोई मान नहीं है void, और इकाई प्रकार का एक मान होना चाहिए। इसके अलावा, जैसा कि आपने बताया, आप प्रकार के मूल्य की घोषणा भी नहीं कर सकते void, इसका मतलब यह है कि यह भी एक प्रकार नहीं है, बस भाषा में एक विशेष कोने का मामला है।
सर्ज बॉर्श

2
हां, इसमें सी विचित्र है, विशेष रूप से कैसे सूचक और फ़ंक्शन पॉइंटर प्रकार लिखे गए हैं। लेकिन voidजावा में लगभग समान है: वास्तव में एक प्रकार नहीं है और मान नहीं हो सकते हैं।
सर्ज बॉर्श

3
नीचे के प्रकार वाली भाषाओं के शब्दार्थ में, नीचे के प्रकार को कोई मान नहीं माना जाता है, बल्कि एक मान होता है, नीचे का मान, एक अभिकलन का प्रतिनिधित्व करता है जो कभी पूरा नहीं होता (सामान्य रूप से)। चूंकि निचला मूल्य हर प्रकार का एक मूल्य है, इसलिए निचला प्रकार हर प्रकार का एक उपप्रकार हो सकता है।
थियोडोर नॉरवेल

4
@BasileStarynkevitch आम लिस्प में शून्य प्रकार होता है जिसका कोई मूल्य नहीं होता है। इसका भी अशक्त प्रकार है जिसका केवल एक मान है, प्रतीक nil(उर्फ ()), जो एक इकाई प्रकार है।
जोशुआ टेलर

जवाबों:


33

मैं एक साधारण उदाहरण लूंगा: C ++ बनाम जंग।

यहाँ एक फ़ंक्शन C ++ 11 में एक अपवाद फेंकने के लिए उपयोग किया जाता है:

[[noreturn]] void ThrowException(char const* message,
                                 char const* file,
                                 int line,
                                 char const* function);

और यहाँ Rust में बराबर है:

fn formatted_panic(message: &str, file: &str, line: isize, function: &str) -> !;

विशुद्ध रूप से वाक्यात्मक पदार्थ पर, रूस्ट निर्माण अधिक समझदार है। ध्यान दें कि C ++ निर्माण रिटर्न प्रकार निर्दिष्ट करता है, जबकि यह भी निर्दिष्ट करता है कि यह वापस नहीं जा रहा है। यह थोड़ा अजीब है।

एक मानक नोट पर, C ++ सिंटैक्स केवल C ++ 11 (यह शीर्ष पर निपटाया गया था) के साथ दिखाई दिया, लेकिन विभिन्न कंपाइलर कुछ समय के लिए विभिन्न एक्सटेंशन प्रदान कर रहे थे, ताकि विभिन्न तरीकों को पहचानने के लिए थर्ड पार्टी विश्लेषण टूल को प्रोग्राम किया जा सके यह विशेषता लिखी जा सकती है। यह मानकीकृत होने के बाद स्पष्ट रूप से बेहतर है।


अब, लाभ के लिए के रूप में?

तथ्य यह है कि एक समारोह वापस नहीं करता है के लिए उपयोगी हो सकता है:

  • अनुकूलन: कोई भी किसी भी कोड को उसके बाद (यह वापस नहीं करेगा) को प्री्यून कर सकता है, रजिस्टरों को बचाने की कोई आवश्यकता नहीं है (क्योंकि उन्हें पुनर्स्थापित करने के लिए आवश्यक नहीं होगा), ...
  • स्थैतिक विश्लेषण: यह कई संभावित निष्पादन मार्गों को समाप्त करता है
  • स्थिरता: (स्थैतिक विश्लेषण देखें, लेकिन मनुष्यों द्वारा)

6
voidआपके C ++ उदाहरण में फ़ंक्शन के प्रकार को परिभाषित करता है - रिटर्न प्रकार नहीं। यह उस फ़ंक्शन को प्रतिबंधित करता है जिस फ़ंक्शन को अनुमति दी जाती है return; कुछ भी जो शून्य में परिवर्तित हो सकता है (जो कुछ भी नहीं है)। यदि फ़ंक्शन returns है, तो इसे किसी मान द्वारा अनुसरण नहीं किया जाना चाहिए। फ़ंक्शन का पूर्ण प्रकार है void () (char const*, char const*, int, char const *)। :-) के char constबजाय उपयोग करने के लिए + 1const char
स्पष्ट

4
इसका मतलब यह नहीं है कि यह नीचे के प्रकार के लिए अधिक समझ में आता है, बस इतना है कि यह इस बात पर टिप्पणी करने के लिए समझ में आता है कि वे भाषा के हिस्से के रूप में वापस आते हैं या नहीं। दरअसल, चूंकि फ़ंक्शन अलग-अलग कारणों से लौटने में विफल हो सकते हैं, इसलिए कैच-ऑल टर्म का उपयोग करने के बजाय किसी तरह से कारण को एनकोड करना बेहतर प्रतीत होता है, जिस तरह से उनके दुष्प्रभावों के आधार पर एनोटेटिंग फ़ंक्शन की अपेक्षाकृत हालिया अवधारणा की तरह है।
२०:१० पर ग्रेग्रोस

2
असल में, "रिटर्न नहीं करता है" बनाने का एक कारण है और "रिटर्न-एक्स" टाइप है "स्वतंत्र: अपने स्वयं के कोड के लिए बैकवर्ड-संगतता, क्योंकि कॉलिंग-कन्वेंशन रिटर्न-प्रकार पर निर्भर हो सकता है।
Deduplicator

है [[noreturn]] वाक्य रचना या कार्यक्षमता की एक अतिरिक्त के बराबर?
ज़ैबिस

1
[cont।] कुल मिलाकर, मैं सिर्फ इतना कहूंगा कि of के फायदों पर एक चर्चा को परिभाषित करना है कि implementation के कार्यान्वयन के रूप में क्या योग्यता है; और मुझे नहीं लगता कि एक प्रकार की प्रणाली जिसमें ( a → ≤) a ( ab ) नहीं है, type का एक उपयोगी कार्यान्वयन है। तो इस अर्थ में SysV x86-64 C ABI (दूसरों के बीच) सिर्फ sense को लागू करने की अनुमति नहीं देता है।
एलेक्स शापिल्किन

26

कार्ल का जवाब अच्छा है। यहाँ एक अतिरिक्त उपयोग है जो मुझे नहीं लगता कि किसी और ने उल्लेख किया है। के जैसा

if E then A else B

एक प्रकार होना चाहिए जिसमें प्रकार में सभी मान शामिल हैं और प्रकार में सभी मान शामिल Aहैं B। यदि प्रकार Bहै Nothing, तो ifअभिव्यक्ति का प्रकार किस प्रकार का हो सकता है A। मैं अक्सर एक दिनचर्या घोषित करता हूँ

def unreachable( s:String ) : Nothing = throw new AssertionError("Unreachable "+s) 

यह कहना कि कोड पहुंचने की उम्मीद नहीं है। चूंकि इसका प्रकार है Nothing, unreachable(s)अब परिणाम के प्रकार को प्रभावित किए बिना किसी भी if(या अधिक बार) में उपयोग किया जा सकता है switch। उदाहरण के लिए

 val colour : Colour := switch state of
         BLACK_TO_MOVE: BLACK
         WHITE_TO_MOVE: WHITE
         default: unreachable("Bad state")

Scala में ऐसा कुछ नहीं है।

Nothing(कार्ल के उत्तर में उल्लिखित) के लिए एक अन्य उपयोग मामला सूची है [कुछ भी नहीं] प्रत्येक सदस्य के पास कुछ भी नहीं टाइप करने वाली सूचियों का प्रकार है। इस प्रकार यह खाली सूची का प्रकार हो सकता है।

उस की प्रमुख संपत्ति Nothingइन उपयोग मामलों को काम करती है , यह नहीं है कि इसका कोई मूल्य नहीं है - हालांकि, स्काला में, उदाहरण के लिए, इसका कोई मूल्य नहीं है - यह है कि यह हर दूसरे प्रकार का एक उपप्रकार है।

मान लीजिए कि आपके पास एक भाषा है जहाँ हर प्रकार का एक ही मूल्य है - चलो इसे कॉल करें ()। ऐसी भाषा में इकाई प्रकार, जिसका ()एकमात्र मान होता है, हर प्रकार का एक उपप्रकार हो सकता है। यह इस अर्थ में एक निचला प्रकार नहीं बनाता है कि ओपी का मतलब है; ओपी स्पष्ट था कि नीचे के प्रकार में कोई मूल्य नहीं है। हालाँकि, जैसा कि यह एक प्रकार है जो हर प्रकार का एक उपप्रकार है, यह नीचे के प्रकार के रूप में एक ही भूमिका निभा सकता है।

हास्केल चीजों को थोड़ा अलग तरीके से करता है। हास्केल में, एक अभिव्यक्ति जो कभी मूल्य पैदा नहीं करती है, उसके प्रकार की योजना हो सकती है forall a.a। इस प्रकार की योजना का एक उदाहरण किसी अन्य प्रकार के साथ एकीकृत होगा, इसलिए यह प्रभावी रूप से नीचे के प्रकार के रूप में कार्य करता है, भले ही (मानक) हास्केल में उपप्रकार की कोई धारणा नहीं है। उदाहरण के लिए, errorमानक प्रस्तावना से कार्य प्रकार योजना है forall a. [Char] -> a। तो आप लिख सकते हैं

if E then A else error ""

और अभिव्यक्ति का प्रकार Aकिसी भी अभिव्यक्ति के प्रकार के समान होगा A

हास्केल में खाली सूची में टाइप स्कीम है forall a. [a]। यदि Aएक अभिव्यक्ति है जिसका प्रकार एक सूची प्रकार है, तो

if E then A else []

के रूप में एक ही प्रकार के साथ एक अभिव्यक्ति है A


हास्केल में forall a . [a]और प्रकार [a]में क्या अंतर है ? Haskell प्रकार की अभिव्यक्तियों में पहले से ही चर प्रकारों को सार्वभौमिक रूप से निर्धारित नहीं किया गया है?
जियोर्जियो

@ जियोर्जियो हास्केल में सार्वभौमिक परिमाणीकरण निहित है अगर यह स्पष्ट है कि आप एक प्रकार की योजना देख रहे हैं। आप forallमानक हास्केल 2010 में भी नहीं लिख सकते । मैंने परिमाणीकरण को स्पष्ट रूप से लिखा है क्योंकि यह हास्केल मंच नहीं है और कुछ लोग हास्केल के सम्मेलनों से परिचित नहीं हो सकते हैं। तो कोई अंतर नहीं है सिवाय इसके कि forall a . [a]मानक नहीं है जबकि [a]है।
थियोडोर नॉरवेल

19

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

  • नीचे प्रकार (मैं इसे फोन करता हूँ Vacuous) शून्य मान हैं
  • इकाई प्रकार का एक मान होता है। मैं दोनों प्रकार और इसके एकल मान को कॉल करूँगा ()
  • रचना (जो अधिकांश प्रोग्रामिंग लैंग्वेज सीधे रिकॉर्ड / स्ट्रक्चर्स / पब्लिक फील्ड्स के साथ कक्षाओं के माध्यम से समर्थन करती हैं) एक उत्पाद ऑपरेशन है। उदाहरण के लिए, (Bool, Bool)चार संभावित मान, अर्थात् है (False,False), (False,True), (True,False)और (True,True)
    इकाई प्रकार रचना संचालन का पहचान तत्व है। ईजी ((), False)और ((), True)केवल प्रकार के मान हैं ((), Bool), इसलिए यह प्रकार अपने आप में आइसोमॉर्फिक Boolहै।
  • अधिकांश भाषाओं में वैकल्पिक प्रकारों को कुछ हद तक उपेक्षित किया जाता है (OO भाषाएँ उन्हें समर्थन के साथ विरासत में देती हैं), लेकिन वे कम उपयोगी नहीं हैं। दो प्रकारों के बीच एक विकल्प Aऔर Bमूल रूप से सभी मान हैं A, साथ ही सभी प्रकार के मूल्य B, इसलिए राशि प्रकार । उदाहरण के लिए, Either () Boolतीन मान हैं, मैं उन्हें कॉल करूंगा Left (), Right Falseऔर Right True
    : नीचे प्रकार योग की पहचान तत्व है Either Vacuous Aहै केवल प्रपत्र के मूल्यों Right aक्योंकि, Left ...भावना (नहीं है Vacuousकोई मान होते हैं)।

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

अब, वास्तव में आप समस्या के केवल एक पक्ष (कंपोजिशन मोनॉयड) की चिंता से काफी दूर हो सकते हैं, फिर आपको वास्तव में नीचे के प्रकार की स्पष्ट रूप से आवश्यकता नहीं है। उदाहरण के लिए, हास्केल ने भी लंबे समय तक मानक तल प्रकार नहीं किया था। अब यह है, यह कहा जाता है Void

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

बेशक, आप अच्छी तरह से कह सकते हैं कि यह सभी सैद्धांतिक सामान्य बकवास है । एक अच्छा प्रोग्रामर बनने के लिए आपको श्रेणी सिद्धांत के बारे में जानने की आवश्यकता नहीं है, लेकिन जब आप ऐसा करते हैं, तो यह आपको कोड के बारे में तर्क करने के लिए शक्तिशाली और हास्यास्पद सामान्य तरीके देता है, और इनोवेटर प्रोवियर्स।


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


"निचला प्रकार (मैं इसे कॉल करूंगा Void)", जिसे मूल्य के साथ भ्रमित नहीं होना है bottom, जो हास्केल में किसी भी प्रकार का सदस्य है ।
mb21

18

शायद यह हमेशा के लिए बंद हो जाता है, या शायद यह एक अपवाद फेंकता है।

उन स्थितियों में होने के लिए एक उपयोगी प्रकार की तरह लगता है, दुर्लभ हालांकि वे हो सकते हैं।

इसके अलावा, भले ही Nothing(नीचे के प्रकार के लिए स्काला का नाम) कोई मूल्य नहीं हो सकता है, List[Nothing]इसमें वह प्रतिबंध नहीं है, जो इसे खाली सूची के प्रकार के रूप में उपयोगी बनाता है। अधिकांश भाषाएं इसे पूर्णांक की एक खाली सूची की तुलना में एक अलग प्रकार के तारों की एक खाली सूची बनाकर प्राप्त करती हैं, जो इस प्रकार की समझ में आता है, लेकिन एक खाली सूची को लिखने के लिए अधिक क्रिया करता है, जो सूची-उन्मुख भाषा में एक बड़ी खामी है।


12
"हास्केल की खाली सूची एक प्रकार की रचना है": निश्चित रूप से इसके बारे में प्रासंगिक बात यहाँ अधिक है कि यह बहुरूपता है, या अतिभारित है - अर्थात, विभिन्न प्रकारों से खाली सूचियाँ अलग-अलग मूल्य हैं, लेकिन []उन सभी का प्रतिनिधित्व करती है, और उनका वर्गीकरण किया जाएगा। आवश्यक के रूप में विशिष्ट प्रकार।
पीटर LeFanu Lumsdaine

दिलचस्प है: यदि आप हास्केल दुभाषिया में एक खाली सरणी बनाने की कोशिश करते हैं, तो आपको बहुत अनिश्चित प्रकार के साथ एक निश्चित मूल्य मिलता है [a]:। इसी तरह, :t Left 1पैदावार Num a => Either a b। वास्तव में अभिव्यक्ति का मूल्यांकन करने के प्रकार पर बल देता है a, लेकिन नहीं b:Either Integer b
जॉन ड्वोरक

5
खाली सूची एक मूल्य निर्माता है। थोड़ा भ्रमित होने पर, प्रकार के निर्माणकर्ता का नाम समान होता है, लेकिन खाली सूची अपने आप में एक मूल्य है न कि एक प्रकार (अच्छी तरह से, टाइप स्तरीय सूचियां भी हैं, लेकिन यह एक संपूर्ण विषय है)। हिस्सा किसी भी प्रकार के लिए सूची खाली सूची काम करता है कि निहित है forall, अपने प्रकार में forall a. [a]। सोचने के कुछ अच्छे तरीके हैं forall, लेकिन वास्तव में यह पता लगाने में कुछ समय लगता है।
डेविड

@PeterLeFanuLumsdaine जो वास्तव में एक प्रकार का निर्माणकर्ता है। यह सिर्फ इसका मतलब है कि यह एक प्रकार से अलग है *
ग्रेग्रोस

2
हास्केल []में एक प्रकार का कंस्ट्रक्टर है और []एक खाली सूची का प्रतिनिधित्व करने वाला एक अभिव्यक्ति है। लेकिन इसका मतलब यह नहीं है कि "हास्केल की खाली सूची एक प्रकार की रचना है"। संदर्भ यह स्पष्ट करता []है कि क्या एक प्रकार के रूप में या एक अभिव्यक्ति के रूप में उपयोग किया जा रहा है। तुम घोषित करो data Foo x = Foo | Bar x (Foo x); अब आप Fooएक प्रकार के कंस्ट्रक्टर के रूप में या एक मूल्य के रूप में उपयोग कर सकते हैं , लेकिन यह सिर्फ ऐसा होता है कि आपने दोनों के लिए एक ही नाम का चयन किया है।
थियोडोर नॉरवेल

3

यह इस तथ्य का दस्तावेजीकरण करने के लिए स्थैतिक विश्लेषण के लिए उपयोगी है कि एक विशेष कोड पथ उपलब्ध नहीं है। उदाहरण के लिए यदि आप C # में निम्नलिखित लिखते हैं:

int F(int arg) {
 if (arg != 0)
  return arg + 1; //some computation
 else
  Assert(false); //this throws but the compiler does not know that
}
void Assert(bool cond) { if (!cond) throw ...; }

कंपाइलर शिकायत करेगा कि Fकम से कम एक कोड पथ में कुछ भी वापस नहीं आता है। यदि Assertगैर-रिटर्न के रूप में चिह्नित किया जाना है तो संकलक को चेतावनी देने की आवश्यकता नहीं होगी।


2

कुछ भाषाओं में, nullनीचे का प्रकार होता है, क्योंकि सभी प्रकारों के उपप्रकार यह अच्छी तरह से परिभाषित करते हैं कि कौन सी भाषा के लिए अशक्त का उपयोग करते हैं ( nullस्वयं होने के एक हल्के विरोधाभास के बावजूद और खुद को वापस करने वाले एक फ़ंक्शन, क्यों बिना botकिसी कारण के सामान्य तर्क से बचना चाहिए)।

यह any -> botप्रेषण प्रकार को पकड़ने के लिए सभी प्रकार के फ़ंक्शन प्रकारों के रूप में भी उपयोग किया जा सकता है।

और कुछ भाषाएं आपको वास्तव botमें एक त्रुटि के रूप में हल करने की अनुमति देती हैं , जिसका उपयोग कस्टम कंपाइलर त्रुटियों को प्रदान करने के लिए किया जा सकता है।


11
नहीं, एक निचला प्रकार इकाई प्रकार नहीं है। एक नीचे के प्रकार का कोई मूल्य नहीं है, इसलिए नीचे के प्रकार को लौटाने वाले फ़ंक्शन को वापस नहीं लौटना चाहिए (यानी एक अपवाद या लूप को अनिश्चित काल के लिए फेंक दें)
बसाइल स्टायरनेविच

@BasileStarynkevitch - मैं यूनिट प्रकार के बारे में बात नहीं कर रहा हूँ। voidआम भाषाओं में इकाई प्रकार के नक्शे (समान उपयोग के लिए थोड़ा अलग शब्दार्थ के साथ), नहीं null। हालाँकि आप सही भी हैं कि अधिकांश भाषाएं नीचे के प्रकार के रूप में अशक्त नहीं हैं।
तेलस्तीन

3
@ TheodoreNorvell - स्पर्शरेखा के शुरुआती संस्करणों ने कहा कि - हालांकि मैं इसका लेखक हूं, इसलिए यह शायद धोखा है। मेरे पास दूसरों के लिए लिंक सहेजे नहीं गए हैं, और जब से मैंने उस शोध को किया है, तब तक कुछ समय हो चुका है।
तेलस्तीन

1
@Martijn लेकिन आप एक बूलियन परिणाम प्राप्त nullकरने के लिए एक सूचक की तुलना करते हैं , जैसे आप उपयोग कर सकते हैं null। मुझे लगता है कि उत्तर दिखा रहे हैं कि नीचे दो अलग-अलग प्रकार हैं। (ए) भाषाएँ (उदाहरण के लिए) जहां प्रकार जो कि हर प्रकार का एक उपप्रकार है संगणना का प्रतिनिधित्व करता है जो कोई परिणाम नहीं देता है। अनिवार्य रूप से यह एक खाली प्रकार है, हालांकि तकनीकी रूप से अक्सर गैर-समाप्ति का प्रतिनिधित्व करने वाले बेकार नीचे मूल्य से आबादी होती है। (b) स्पर्शरेखा जैसी भाषाएँ, जिनमें नीचे का प्रकार हर दूसरे प्रकार का सबसेट होता है क्योंकि इसमें एक उपयोगी मूल्य होता है जो हर दूसरे प्रकार में भी पाया जाता है - अशक्त।
थियोडोर नॉरवेल

4
यह दिलचस्प है कि कुछ भाषा में एक प्रकार के साथ एक मूल्य होता है जिसे आप घोषित नहीं कर सकते (सामान्य शाब्दिक के लिए), और अन्य के पास एक ऐसा प्रकार है जिसे आप घोषित कर सकते हैं लेकिन कोई मान नहीं है (एक पारंपरिक निचला प्रकार), और यह कि वे कुछ तुलनीय भूमिकाएं भरते हैं ।
मार्टिअन

1

हाँ यह एक काफी उपयोगी प्रकार है; हालांकि इसकी भूमिका ज्यादातर प्रकार की प्रणाली के लिए आंतरिक होगी, कुछ अवसर ऐसे होते हैं, जहां नीचे का प्रकार खुलकर सामने आता है।

एक वैधानिक रूप से टाइप की गई भाषा पर विचार करें, जिसमें स्थितियाँ अभिव्यक्तियाँ हैं (इसलिए यदि तत्कालीन निर्माण सी और दोस्तों के टर्नरी ऑपरेटर के रूप में दोगुना हो जाता है , और एक समान मल्टी-वे केस स्टेटमेंट हो सकता है)। कार्यात्मक प्रोग्रामिंग भाषा में यह है, लेकिन यह कुछ अनिवार्य भाषाओं में भी होता है (जब से ALGOL 60)। फिर सभी शाखा अभिव्यक्तियों को अंततः संपूर्ण सशर्त अभिव्यक्ति के प्रकार का उत्पादन करना चाहिए। किसी को बस अपने प्रकार की आवश्यकता हो सकती है बराबर (और मुझे लगता है कि यह सी में सहायक ऑपरेटर के लिए मामला है) लेकिन यह विशेष रूप से प्रतिबंधात्मक है जब सशर्त भी सशर्त बयान (किसी उपयोगी मूल्य को वापस नहीं) के रूप में इस्तेमाल किया जा सकता है। सामान्य तौर पर प्रत्येक व्यक्ति चाहता है कि प्रत्येक शाखा अभिव्यक्ति (स्पष्ट रूप से) परिवर्तनीय हो एक सामान्य प्रकार जो पूर्ण अभिव्यक्ति का प्रकार होगा (संभवतः अधिक या कम जटिल प्रतिबंधों के साथ अनुमति देने के लिए कि सामान्य प्रकार को प्रभावी रूप से संगीन, cf. C ++ द्वारा पाया जा सकता है, लेकिन मैं यहां उन विवरणों में नहीं जाऊंगा)।

दो प्रकार की परिस्थितियां हैं जहां एक सामान्य प्रकार का रूपांतरण ऐसे सशर्त अभिव्यक्तियों के आवश्यक लचीलेपन की अनुमति देगा। एक पहले से ही उल्लेख किया गया है, जहां परिणाम प्रकार इकाई प्रकार हैvoid; यह स्वाभाविक रूप से अन्य सभी प्रकारों का एक सुपर-प्रकार है, और किसी भी प्रकार को इसे (तुच्छ रूप से) परिवर्तित करने की अनुमति देना सशर्त अभिव्यक्ति को सशर्त कथन के रूप में उपयोग करना संभव बनाता है। दूसरे में ऐसे मामले शामिल हैं जहां अभिव्यक्ति एक उपयोगी मूल्य लौटाती है, लेकिन एक या अधिक शाखाएं एक उत्पादन करने में असमर्थ हैं। वे आम तौर पर एक अपवाद को शामिल करेंगे या एक कूद शामिल करेंगे, और उन्हें (भी) पूरे अभिव्यक्ति के प्रकार के मूल्य का उत्पादन करना होगा (एक अगम्य बिंदु से) व्यर्थ होगा। यह इस तरह की स्थिति है जिसे अपवाद रूप से उठाने वाले क्लॉज, जंपर्स और कॉल के द्वारा सुशोभित किया जा सकता है, जिसमें ऐसा प्रभाव होगा, नीचे का प्रकार, एक प्रकार जो (तुच्छ रूप से) किसी अन्य प्रकार में परिवर्तित हो सकता है।

मैं इस तरह के नीचे के रूप में लिखने *का सुझाव दूंगा ताकि मनमानी प्रकार को इसकी परिवर्तनीयता का सुझाव दिया जा सके। यह आंतरिक रूप से अन्य उपयोगी उद्देश्यों की पूर्ति कर सकता है, उदाहरण के लिए, जब एक पुनरावर्ती फ़ंक्शन के लिए परिणाम प्रकार को कम करने की कोशिश की जाती है जो किसी भी घोषित नहीं करता है, तो टाइप *-इन-इंस्पेक्टर चिकन और अंडे की स्थिति से बचने के लिए किसी भी पुनरावर्ती कॉल को टाइप असाइन कर सकता है; वास्तविक प्रकार गैर-पुनरावर्ती शाखाओं द्वारा निर्धारित किया जाएगा, और पुनरावर्ती लोगों को गैर-पुनरावर्ती लोगों के सामान्य प्रकार में परिवर्तित किया जाएगा। यदि कोई गैर-पुनरावर्ती शाखाएं नहीं हैं , तो प्रकार रहेगा *, और सही ढंग से इंगित करता है कि फ़ंक्शन के पास पुनरावृत्ति से वापस लौटने का कोई संभावित तरीका नहीं है। इसके अलावा और परिणाम फेंकने वाले कार्यों के प्रकार के अलावा, कोई भी उपयोग कर सकता है*रिक्त सूची के उदाहरण के लिए, लंबाई 0 के घटक प्रकार के रूप में; फिर से यदि कभी किसी तत्व को प्रकार की अभिव्यक्ति [*](आवश्यक रूप से रिक्त सूची) से चुना जाता है, तो परिणामी प्रकार *को सही ढंग से इंगित किया जाएगा कि यह कभी भी त्रुटि के बिना वापस नहीं आ सकता है।


तो विचार है कि है var foo = someCondition() ? functionReturningBar() : functionThatAlwaysThrows()के प्रकार का अनुमान लगा सकता है fooके रूप में Bar, के बाद से अभिव्यक्ति कुछ और उपज नहीं कर सकता था?
सुपरकैट

1
आपने केवल इकाई प्रकार का वर्णन किया है- कम से कम अपने उत्तर के पहले भाग में। एक समारोह जो इकाई प्रकार देता है एक जो लौटने के रूप में घोषित किया जाता है के रूप में ही है voidसी में अपने जवाब है, जहां आप एक समारोह है जो कभी नहीं देता है के लिए एक प्रकार, या कोई तत्व के साथ एक सूची के बारे में बात का दूसरा हिस्सा है कि है वास्तव में नीचे प्रकार! (यह अक्सर के _|_बजाय के रूप में लिखा है *। निश्चित रूप से क्यों नहीं। शायद क्योंकि यह एक (मानव) नीचे की तरह लग रहा है :)
andrewf

2
संदेह से बचने के लिए: 'कुछ भी उपयोगी नहीं लौटता है' 'वापस नहीं आता' से अलग है; पहला यूनिट प्रकार द्वारा दर्शाया गया है; नीचे के प्रकार से दूसरा।
andrewf

@andrewf: हाँ मैं भेद समझता हूँ। मेरा उत्तर थोड़ा लंबा है, लेकिन मैं जो बिंदु बनाना चाहता था वह यह है कि इकाई प्रकार और निचला प्रकार दोनों ही (अलग लेकिन) दोनों प्रकार की भूमिकाओं को कुछ अभिव्यक्तियों को अधिक लचीले ढंग से (लेकिन अभी भी सुरक्षित रूप से) उपयोग करने की अनुमति देता है।
मार्क वैन लीउवेन

@ सुपरकैट: हाँ, यह विचार है। वर्तमान में C ++, जो अवैध है, हालांकि यह मान्य हो सकता है अगर functionThatAlwaysThrows()एक स्पष्ट द्वारा प्रतिस्थापित किया गया throwस्टैंडर्ड में विशेष भाषा की वजह से,। ऐसा करने वाला एक प्रकार का सुधार होगा।
मार्क वैन लीउवेन

0

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

कई भाषाओं में, एक फ़ंक्शन "शून्य" वापस कर सकता है। वास्तव में इसका क्या अर्थ है यह भाषा पर निर्भर करता है। C में इसका मतलब है कि फ़ंक्शन कुछ भी नहीं लौटाता है। स्विफ्ट में, इसका मतलब है कि फ़ंक्शन केवल एक संभावित मान के साथ एक वस्तु लौटाता है, और चूंकि केवल एक संभव मूल्य है जो मान शून्य बिट्स लेता है और वास्तव में किसी भी कोड की आवश्यकता नहीं होती है। किसी भी मामले में, यह "नीचे" के समान नहीं है।

"नीचे" एक प्रकार होगा जिसमें कोई संभावित मान नहीं होगा। यह कभी मौजूद नहीं हो सकता। यदि कोई फ़ंक्शन "नीचे" देता है, तो यह वास्तव में वापस नहीं आ सकता है, क्योंकि "नीचे" प्रकार का कोई मूल्य नहीं है कि वह वापस आ सके।

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

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.