हास्केल में अपवाद कैसे काम करते हैं?


86

GHCi में:

Prelude> error (error "")
*** Exception: 
Prelude> (error . error) ""
*** Exception: *** Exception: 

पहले एक नेस्टेड अपवाद क्यों नहीं है?


9
यह एक परिवर्तन है जिसे GHC बनाने की अनुमति है: "मैं वह कंपाइलर हूं जो खुद से काम करता है, और सभी _ | _s मेरे लिए समान हैं"। क्या आप उन कार्यान्वयन विवरणों के लिए पूछ रहे हैं जो उन दो पंक्तियों को अलग-अलग रूप से संकलित करते हैं?
शाचफ

3
errorविशेष है और वास्तव में अपवाद तंत्र नहीं है। असली, देखने योग्य अपवादों में मोनाड दिखाई देता है Error
कैट प्लस प्लस

1
ध्यान दें, उदाहरण के लिए, वह (\f g x -> f (g x)) error error ""अलग (.) error error ""कार्य करता है, भले ही वह फ़ंक्शन के बराबर हो (.)। हो सकता है कि यह उन अनुकूलन झंडों के साथ हो, जिन्हें प्रिल्यूड ने संकलित किया था।
शाचफ

5
इसके अलावा iterate error "" !! nऔर भयानक fix error
विट्टस

9
मैं हमेशा यही दिखावा करता हूं error = errorऔर उसी के अनुसार कार्यक्रम करता हूं ।
गेब्रियल गोंजालेज

जवाबों:


101

इसका उत्तर यह है कि यह (कुछ आश्चर्य की बात) आवेग अपवादों का शब्दार्थ है

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

उन्नत Haskellers के लिए एक सामयिक गोचा एक मामला है जैसे:

 case x of
   1 -> error "One"
   _ -> error "Not one"

चूंकि कोड अपवादों के एक सेट का मूल्यांकन करता है, जीएचसी एक लेने के लिए स्वतंत्र है। अनुकूलन के साथ, आप अच्छी तरह से यह हमेशा "नहीं" का मूल्यांकन कर सकते हैं।

हम ऐसा क्यों करते हैं? क्योंकि अन्यथा हम भाषा के मूल्यांकन क्रम पर अत्यधिक दबाव डालते हैं, उदाहरण के लिए हमें इसके लिए एक निर्धारक परिणाम तय करना होगा:

 f (error "a") (error "b")

उदाहरण के लिए, यह आवश्यक है कि त्रुटि मान मौजूद होने पर इसे बाएं से दाएं मूल्यांकन किया जाए। बहुत अन-हास्केली!

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

आम तौर पर, आप परवाह नहीं करते हैं - एक अपवाद एक अपवाद है - जब तक आप अपवाद के अंदर स्ट्रिंग के बारे में परवाह नहीं करते हैं, जिसमें errorडीबग का उपयोग करने का मामला अत्यधिक भ्रामक है।


संदर्भ: अभेद्य अपवादों के लिए एक शब्दार्थ , साइमन पेटन जोन्स, एलेस्टेयर रीड, टोनी होरे, साइमन मार्लो, फर्गस हेंडरसन। प्रोक प्रोग्रामिंग लैंग्वेज डिजाइन एंड इम्प्लीमेंटेशन (PLDI'99), अटलांटा। ( पीडीएफ )


2
मैं समझता हूं कि GHC में से किसी एक अपवाद को चुनना जो सामना किया जा सकता है। लेकिन आपके "केस" उदाहरण में, "1 नहीं" अपवाद 1 के इनपुट के लिए सामना नहीं किया जा सकता है, इसलिए मैं अभी भी इसे बग के रूप में वर्गीकृत करूंगा।
पीकर

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

1
@lpsmith: मुझे लगता है कि सभी अपवाद प्रकार imprecise हैं (जब उपयोग करके फेंका जाता है throw) और आप निर्धारित कर सकते हैं कि आप इसके साथ अपवाद को फेंक सकते हैं throwIO
फनकार्सलाड

4
@ पीकर मुझे लगता है कि आप सही हैं। मुझे नहीं लगता कि अगर इस नियम को अपवाद के रूप में निर्धारित किया जाता है तो ghc को इस अभिव्यक्ति का अनुकूलन करना चाहिए।
अगस्त

3
अपवादात्मक अपवाद कागज़ के बारे में यह कहना प्रतीत होता है कि यदि मामले की जांच एक त्रुटि मान है, तो शाखाओं से त्रुटि मान वापस आ सकते हैं। तो case error "banana" of (x:xs) -> error "bonobo"आपको दे सकते हैं * Exception: bonobo
बेन मिलवुड
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.