2010-09-04 11 views

उत्तर

24

कारणों में से एक denotational semantics of Haskell है। अधिक परिभाषित तर्क पैदावार अधिक परिभाषित मूल्य -

(शुद्ध) हास्केल कार्यों का साफ प्रॉपर्टीज़ में से एक उनके दिष्टता है। यह संपत्ति बहुत महत्वपूर्ण है उदा। पुनरावर्ती कार्यों के बारे में कारण (समझने के लिए लेख पढ़ें) क्यों।

परिभाषा द्वारा अपवाद का नोटेशन नीचे दिया गया है, _|_, दिए गए प्रकार से संबंधित पॉकेट में कम से कम तत्व। इस प्रकार, दिष्टता आवश्यकता को पूरा करने के लिए, निम्न असमानता हास्केल समारोह के किसी भी वाच्यार्थ f के लिए पकड़ करने के लिए की जरूरत है:

f(_|_) <= f(X) 

अब, अगर हम अपवाद पकड़ सकते थे, हम (द्वारा "पहचानने" नीचे इस असमानता को तोड़ सकते थे पकड़ने अपवाद) तथा लौटने अधिक परिभाषित मूल्य:

f x = case catch (seq x True) (\exception -> False) of 
     True -> -- there was no exception 
      undefined 
     False -> -- there was an exception, return defined value 
      42 

यहाँ पूरा काम कर प्रदर्शन है (की आवश्यकता आधार -4 Control.Exception):

import Prelude hiding (catch) 
import System.IO.Unsafe (unsafePerformIO) 
import qualified Control.Exception as E 

catch :: a -> (E.SomeException -> a) -> a 
catch x h = unsafePerformIO $ E.catch (return $! x) (return . h) 

f x = case catch (seq x True) (\exception -> False) of 
     True -> -- there was no exception 
      undefined 
     False -> -- there was an exception, return defined value 
      42 

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

हम यह कैसे करेंगे? निम्नलिखित अभिव्यक्ति पर विचार करें:

let x = x in x 

यह एक गैर-सांत प्रत्यावर्तन है, इसलिए यह कभी नहीं हमें किसी भी जानकारी देता है और इस तरह _|_ द्वारा भी दिखाया जाता है। अगर हम अपवादों को पकड़ने के लिए सक्षम थे, हम समारोह लिख सकता है च जैसे

f undefined = 0 
f (let x = x in x) = _|_ 

(उत्तरार्द्ध हमेशा सख्ती से पालन कार्यों के लिए सच है, क्योंकि हास्केल गैर समाप्त गणना पता लगाने के लिए कोई साधन प्रदान करता है - और सिद्धांत रूप में नहीं कर सकते हैं, Halting problem की वजह से।)

+1

ठीक है। यह हैकेल के पीछे कठिन गणितीय बैकग्राउंड में से एक प्रतीत होता है। आपके संक्षिप्त विवरण के लिए धन्यवाद। – fuz

+1

क्षमा करें, लेकिन यह जवाब पूरी तरह से परेशान है जो मुझे लगता है कि यह एक बहुत ही सरल सवाल है ... लेकिन यह शायद आपके उत्तर के बजाय हास्केल की समझ की कमी पर अधिक दर्शाता है। –

+1

dodgy_coder: मुझे खेद है कि यह आपके लिए उपयोगी नहीं था। ऐसे कई दृष्टिकोण हो सकते हैं जिनसे कोई इस प्रश्न का उत्तर दे सकता है। आप कह सकते हैं कि आप इसे (नहीं) कर सकते हैं क्योंकि संबंधित कार्यों के प्रकार इसे नहीं करते हैं (नहीं)। तो निश्चित रूप से आप पूछ सकते हैं कि वे प्रकार क्यों हैं। जवाब यह है कि "ऐसी चीजों को अनुमति देने के लिए अच्छे कारण नहीं हैं", और मैंने ऊपर दिए गए कारणों की रूपरेखा तैयार करने की कोशिश की। –

14

क्योंकि अपवाद referential transparency तोड़ सकता है।

आप शायद अपवाद है कि वास्तव में इनपुट के प्रत्यक्ष परिणाम हैं के बारे में बात कर रहे हैं। उदाहरण के लिए:

head [] = error "oh no!" -- this type of exception 
head (x:xs) = x 

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

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

+2

क्या आप इस तरह से रेफरेंसियल पारदर्शिता तोड़ने का एक उदाहरण दे सकते हैं? –

+0

तो आप मुझे बताना चाहते हैं कि उत्साह कार्यशील रूप से सोचने का तरीका नहीं है, इसलिए मुझे आम तौर पर उनसे बचने की कोशिश करनी चाहिए? महान! – fuz

+0

रोमन: मेरा क्या मतलब था कि यदि आप शुद्ध कोड में अपवाद प्राप्त कर सकते हैं और उन अपवादों पर अपना परिणाम आधार दे सकते हैं, तो ऐसी कार्रवाई रेफरेंसियल पारदर्शिता को तोड़ देगी। –

1

मैं अपने विवरण में गलत हो सकता है, लेकिन इस तरह मैं यह समझ है।

चूंकि कार्य हास्केल में शुद्ध हैं, इसलिए संकलक को उनके इच्छित किसी भी क्रम में उनका मूल्यांकन करने का अधिकार है और यह अभी भी एक ही परिणाम उत्पन्न करता है। उदाहरण के लिए, दिए गए कार्य:

square :: Int -> Int 
square x = x * x 

अभिव्यक्ति square (square 2) अलग अलग तरीकों से मूल्यांकन किया जा सकता, लेकिन यह हमेशा एक ही परिणाम है जो 16

है अगर हम कहीं और से square कॉल करने के लिए कम कर देता है:

test x = if x == 2 
     then square x 
     else 0 

square x का मूल्यांकन बाद में मूल्यांकन किया जा सकता है, जब test फ़ंक्शन को वास्तव में आवश्यक होने पर "बाहर" किया जा सकता है। उस पल में कॉल स्टैक जावा से कहने की अपेक्षा से बिल्कुल अलग हो सकता है।

तो अगर हम square द्वारा फेंकने वाले संभावित अपवाद को पकड़ना चाहते हैं, तो आपको catch भाग कहां रखना चाहिए?

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