2012-05-16 13 views
14

मुझे उपयोगकर्ताओं और समूहों के बीच उपयोगकर्ताओं, समूहों और मैपिंग का एक सेट मिला है। मेरे पास इन कार्यों में हेरफेर करने वाले विभिन्न फ़ंक्शन हैं, हालांकि कोई उपयोगकर्ता को < -> उस उपयोगकर्ता के लिए समूह मैपिंग जोड़ने में सक्षम नहीं होना चाहिए जो मौजूद नहीं है, न ही उस समूह को हटा दें जिसमें अभी भी उपयोगकर्ता के रूप में उपयोगकर्ता हैं।हास्केल "अपवाद"

तो मूल रूप से मैं इन कार्यों को "अपवाद" फेंकना चाहता हूं जिसे स्पष्ट रूप से कॉलर द्वारा निपटाया जाना चाहिए।

मैं पहली बार कुछ इस तरह लौटने के बारे में सोचा:

data Return r e = Success r | Exception e 

और अगर फोन करने वाले Exception के खिलाफ पैटर्न मैच, वे उम्मीद है कि एक संकलक चेतावनी मिल जाएगा करने में विफल रहता है, या कम से कम एक स्पष्ट क्रम है कोई समस्या होने पर त्रुटि।

क्या यह सबसे अच्छा तरीका है, और क्या यह एक पूर्व-पैक समाधान है जो यह करता है? नोट मुझे शुद्ध कोड में "अपवाद" फेंकने और पकड़ने की आवश्यकता है, आईओ मोनाड नहीं।

उत्तर

19

हां, यह एक अच्छा दृष्टिकोण है, और यह मानक पुस्तकालय में है: Return r eEither e r जैसा ही है। आप कोड भी लिख सकते हैं जैसे आप IO में अपवादों का उपयोग करेंगे (यानी पैटर्न मिलान के साथ प्रत्येक चरण में त्रुटियों को स्पष्ट रूप से संभालने के बिना): MonadEither के लिए उदाहरण त्रुटियों को प्रसारित करता है, जैसे Maybe मोनड करता है (लेकिन साथ त्रुटि के मामले में अतिरिक्त e मान)। उदाहरण के लिए:

data MyError 
    = Oops String 
    | VeryBadError Int Int 

mightFail :: T -> Either MyError Int 
mightFail a = ... 

foo :: T -> T -> Int -> Either MyError Int 
foo a b c = do 
    x <- mightFail a 
    y <- mightFail b 
    if x == y 
     then throwError (VeryBadError x y) 
     else return (x + y + c) 

तो mightFail a या mightFail b रिटर्न Left someError, तो foo a b c पर भी लागू होगी; त्रुटियों को स्वचालित रूप से प्रचारित किया जाता है। (यहाँ, throwError सिर्फ Left लेखन, Control.Monad.Error से कार्यों का उपयोग करने का एक अच्छा तरीका है, वहाँ भी catchError इन अपवादों को पकड़ने के लिए है।)

11

Return r e प्रकार है कि आप का वर्णन कर रहे हैं वास्तव में मानक प्रकार

data Either a b = Left a | Right b 
है

आप mtl पैकेज के तथाकथित "error monad" (अधिक उपयुक्त नाम "अपवाद monad") का उपयोग करना चाह सकते हैं। (वैकल्पिक रूप से, यदि आप mtl का उपयोग नहीं करना चाहते हैं तो monadLib पैकेज में ExceptionT है।) यह आपको throwError और catchError का आह्वान करके शुद्ध कोड में त्रुटि प्रबंधन करने की अनुमति देता है। Here आप एक उदाहरण पा सकते हैं जो दिखाता है कि इसका उपयोग कैसे करें।