16

मुझे आश्चर्य है कि मुझे कहीं भी इसका जवाब नहीं मिला।त्रुटि फ़ंक्शन पर कॉल को कैसे पकड़ें (और अनदेखा करें)?

मैं एक roguelike लिख रहा हूँ और मैं हैकेज से ncurses पुस्तकालय का उपयोग कर रहा हूँ, जो ncurses पुस्तकालय के चारों ओर एक बहुत अच्छा रैपर है। अब ncurses में यह quirk है, जहां आप निचले दाएं चरित्र को लिखने का प्रयास करते हैं, ऐसा करता है, तो यह कर्सर को अगले चरित्र पर ले जाने की कोशिश करता है, तो यह विफल हो जाता है क्योंकि इसे स्थानांतरित करने के लिए कहीं भी नहीं है। यह एक त्रुटि मान देता है जिसे आप केवल अनदेखा कर सकते हैं।

मेरी समस्या यह है कि हैकेल ncurses लाइब्रेरी लेखक सभी कॉल पर किसी भी त्रुटि के लिए कर्तव्यपूर्वक जांच करता है, और जब कोई होता है, तो वह कॉल करता है: त्रुटि "drawText: आदि इत्यादि"।

अन्य भाषाओं में, सी या पायथन जैसे, इस के आसपास पाने के लिए आपको त्रुटि को अनदेखा करने या पकड़ने और अपवाद को अनदेखा करने के लिए मजबूर होना पड़ता है, लेकिन मेरे जीवन के लिए मैं यह नहीं समझ सकता कि इसे हैकेल में कैसे किया जाए। त्रुटि त्रुटि अप्राप्य है?

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

+0

"पकड़ो" के लिए होगल [1]। दूसरा लिंक नीचे। [1] http://haskell.org/hoogle/?hoogle=catch –

+0

दुर्भाग्य से प्रश्न में त्रुटि IO monad में नहीं है। वैसे यह आईओ में शुरू होता है, फिर आप रनकर्स जाते हैं, जो शापित मोनड है, फिर अपडेट विन्डो, जो अद्यतन मोनड है। इसलिए मुझे नहीं लगता कि पॉल का जवाब काम करेगा। लेकिन लुक्की के दिखने की संभावना है और जब मैं घर आऊंगा तो मैं कोशिश करूँगा। –

+0

ncurses को देखकर मुझे लगता है कि यह काम नहीं करेगा। 'drawText' 'त्रुटि' को कॉल नहीं करता है, यह सीधे सी समारोह में प्रतिनिधि करता है। और यह 'अपडेट' मोनैड में लौटाता है, जो 'रीडर टी विंडो आईओ ए' = 'विंडो -> आईओ ए' है, इसलिए 'असुरक्षित क्लेनअप' केवल काम करने जा रहा है अगर यह * फ़ंक्शन * उत्पन्न करते समय त्रुटियों पर न हो, न कि जब कार्रवाई चलाना (असंभव)। मुझे लगता है कि आपके विकल्प हैं: शीर्ष स्तर पर आईओ में त्रुटि को पकड़ें, या शाप स्रोत को खोलें ताकि आपको अधिक स्थानीय 'पकड़' फ़ंक्शन इंजेक्ट किया जा सके। (यह आसानी से किया जा सकता है, बस encapsulation तोड़ता है) – luqui

उत्तर

12

error को अनंत लूप के रूप में देखा जा सकता है। आप IO में केवल error पकड़ सकते हैं, जो कहने पर है "हाँ यदि आप जादू जानते हैं तो आप कर सकते हैं"। लेकिन हास्केल, शुद्ध कोड के वास्तव में अच्छे हिस्से से, यह अप्राप्य है, और इस प्रकार आपके कोड में उपयोग करने के लिए को दृढ़ता से सलाह दी जाती है, जितना आप कभी भी अनंत कोड को एक त्रुटि कोड के रूप में उपयोग करेंगे।

ncurses कठोर हो रहा है और इसे सही करने के लिए आपको जादू कर रहा है। मैं कहूंगा कि unsafePerformIO इसे साफ़ करने के लिए जरूरी होगा। इसके अलावा, यह काफी हद तक पॉल के जवाब के समान ही है।

import qualified Control.Exception as Exc 

{-# NOINLINE unsafeCleanup #-} 
unsafeCleanup :: a -> Maybe a 
unsafeCleanup x = unsafePerformIO $ Exc.catch (x `seq` return (Just x)) handler 
    where 
    handler exc = return Nothing `const` (exc :: Exc.ErrorCall) 

तो किसी भी मूल्य है कि यह एक Maybe में बदलने के लिए एक त्रुटि के मूल्यांकन करेगा चारों ओर unsafeCleanup लपेट दें।

+0

बीटीडब्ल्यू है, 'एक्सा।पकड़ो (Exc.evaluate (बस $! x)) हैंडलर 'थोड़ा क्लीनर imho – hvr

+1

एफडब्ल्यूआईडब्ल्यू होगा अब यह [चम्मच] (http://hackage.haskell.org/package/spoon) लाइब्रेरी में लागू किया गया है। – luqui

+0

चम्मच भी 'ए -> शायद एक' के बजाय 'ए - स्ट्रिंग ए' कर सकता है ताकि मैं पकड़े गए त्रुटि का संदेश देख सकूं? या क्या यह contraindicated होगा? –

15

आप से catch का उपयोग कर ऐसा कर सकते हैं। नोट, हालांकि, ऐसा करने के लिए आपको IO मोनैड में होना चाहिए।

import qualified Control.Exception as Exc 

divide :: Float -> Float -> Float 
divide x 0 = error "Division by 0." 
divide x y = x/y 

main :: IO() 
main = Exc.catch (print $ divide 5 0) handler 
    where 
     handler :: Exc.ErrorCall -> IO() 
     handler _ = putStrLn $ "You divided by 0!" 
+0

मुझे लगता है कि putStrLn में '$' char को xD हटाया जा सकता है। लेकिन यह स्वीकार्य उत्तर होना चाहिए, क्योंकि यह क्लीनर – dani24

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