2012-05-14 21 views
12

मैं आरडब्ल्यूएच पढ़ रहा हूँ, और मैं अध्याय 9. यह कोड का निम्न भाग का परिचय पर आए हैं:"संभाल" समारोह और असली दुनिया हास्केल

import System.IO 
import Control.Exception 

saferFileSize :: FilePath -> IO (Maybe Integer) 
saferFileSize path = handle (\_ -> return Nothing) $ do 
    h <- openFile path ReadMode 
    size <- hFileSize h 
    hClose h 
    return (Just size) 

हालांकि यह संकलन, दे नहीं होगा निम्न त्रुटि संदेश:

test.hs:5:22: 
    Ambiguous type variable `e0' in the constraint: 
     (Exception e0) arising from a use of `handle' 
    Probable fix: add a type signature that fixes these type variable(s) 
    In the expression: handle (\ _ -> return Nothing) 
    In the expression: 
     handle (\ _ -> return Nothing) 
     $ do { h <- openFile path ReadMode; 
      size <- hFileSize h; 
      hClose h; 
      return (Just size) } 
    In an equation for `saferFileSize': 
     saferFileSize path 
      = handle (\ _ -> return Nothing) 
      $ do { h <- openFile path ReadMode; 
        size <- hFileSize h; 
        hClose h; 
        .... } 

क्या गलत यहाँ चल रहा है? यह संकलन क्यों नहीं करेगा?

उत्तर

25

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

इस का एक परिणाम के रूप में, यह, अपने उदाहरण में से एक की तरह "क्या कुछ नहीं" संचालकों के साथ अस्पष्टता समस्याओं में चलाने के लिए आसान है के बाद से संकलक अनुमान नहीं लगा सकता अपवादों में से आप किस प्रकार पकड़ने की कोशिश कर रहे हैं। इसे ठीक करने का एक आसान तरीका है अपने हैंडलर फ़ंक्शन के लिए एक प्रकार का हस्ताक्षर प्रदान करना।

handle ((\_ -> return Nothing) :: IOException -> IO (Maybe Integer)) $ do ... 

हालांकि, यह कुछ हद तक verbose हो सकता है। एक वैकल्पिक समाधान handle विशेषज्ञ है।

handleIO :: (IOException -> IO a) -> IO a -> IO a 
handleIO = handle 

उसके बाद, आप सिर्फ handleIO उपयोग कर सकते हैं जब भी आप आईओ अपवाद हैंडल करना चाहते हैं, हैंडलर के प्रकार के हस्ताक्षर उल्लेख किए बिना।

saferFileSize path = handleIO (\_ -> return Nothing) $ do ... 

एक तीसरा विकल्प ScopedTypeVariables विस्तार है, जो (अन्य बातों के अलावा) तुम सिर्फ एक समारोह के तर्क के लिए एक प्रकार का एनोटेशन प्रदान करने के लिए, की अनुमति के बाकी अनुमान लगाया जा करने की अनुमति देता का उपयोग करें।

{-# LANGUAGE ScopedTypeVariables #-} 
saferFileSize path = handle (\(_ :: IOException) -> return Nothing) $ do ... 
+0

हास्केल वेबसाइट पर 'handle' समारोह के लिए दस्तावेज़ इस बारे में बहुत स्पष्ट नहीं है (कम से कम प्रवेश स्तर के लोगों के लिए - जो प्रलेखन की आवश्यकता है) https://wiki.haskell.org/Exception बहुत स्पष्ट स्पष्टीकरण के लिए धन्यवाद कि कंपाइलर को हमें संभालने के लिए अपवाद प्रकार निर्दिष्ट करने की आवश्यकता है! – jocull

4

आरडब्ल्यूएच पुराना है। handle जीएचसी 6.10 या तो में फ़ंक्शन हस्ताक्षर बदल गया है।

पुराने संस्करण का उपयोग करने के लिए, Control.Exception` के बजाय Control.OldException आयात करें। आपको बहिष्करण चेतावनियां मिलेंगी लेकिन कार्यक्रम संकलित होगा।

या आप नए इंटरफ़ेस का उपयोग और हैंडलर एक स्पष्ट हस्ताक्षर, दे ताकि तरह कर सकते हैं: जहां प्रकार

((\ _ -> return Nothing) :: IOException -> IO (Maybe Integer)) 
संबंधित मुद्दे