मौजूद है एक इकाई के अंदर पढ़ने का एक मुहावरा:
> readM "CmdOther" :: IO Cmd
CmdOther
> readM "Cmd?Other" :: IO Cmd
*** Exception: user error (Failed to parse: "Cmd?Other")
क्योंकि fail
IO
के मामले की जो कि में एक IOError
अपवाद फेंकता है:
readM :: (Monad m, Read a) => String -> m a
readM s | [x] <- [x | (x, "") <- reads s] = return x
-- or @[x] <- [x | (x, _) <- reads s] = return [email protected]
-- to allow the garbage at the end of parsed string
| otherwise = fail $ "Failed to parse: \"" ++ s ++ "\""
यह IO
इकाई के लिए असुरक्षित है , संभाला जा सकता है:
*Main> (readM "Cmd?Other" :: IO Cmd) `catch` const (return CmdOther)
CmdOther
और Maybe
इकाई के मामले में सुरक्षित:
> readM "CmdOther" :: Maybe Cmd
Just CmdOther
> readM "Cmd?Other" :: Maybe Cmd
Nothing
क्योंकि fail
इस मामले में const Nothing
है।
वैसे भी, अगर आप एक हस्ताक्षर String -> Cmd
साथ कुल समारोह guiString2Cmd
चाहते आप यह सिर्फ readM
तरह लिख सकते हैं:
guiString2Cmd :: String -> Cmd
guiString2Cmd s | [x] <- [x | (x, "") <- reads s] = x
| otherwise = CmdExit
और उसके बाद:
> guiString2Cmd "CmdOther"
CmdOther
> guiString2Cmd "Cmd?Other"
CmdExit
थोड़े अधिक सामान्य दृष्टिकोण।
*
के लिए प्रकार:
class Failable0 t where
fail0 :: t
readG0 :: (Failable0 t, Read t) => String -> t
readG0 s | [x] <- [x | (x, "") <- reads s] = x
| otherwise = fail0
तो:
instance Failable0 Cmd where
fail0 = CmdExit
* -> *
के लिए प्रकार:
class Failable f where
fail :: String -> f a
class Functor f => Pointed f where
pure :: a -> f a
readG :: (Failable f, Pointed f, Read a) => String -> f a
readG s | [x] <- [x | (x, "") <- reads s] = pure x
| otherwise = fail $ "Failed to parse: \"" ++ s ++ "\""
का उपयोग पढ़ने एक बेहतर विचार वास्तव में हो सकती है ... – mbrodersen
हाँ, सबसे अच्छा शुद्ध अपवाद को संभालने का तरीका इसे पहले स्थान पर नहीं बनाना है। – dave4420
रिकॉर्ड के लिए, अपवाद ('read' द्वारा फेंकने सहित) को केवल 'नियंत्रण' अपवाद 'में दिए गए कार्यों का उपयोग करके आईओ मोनैड में पकड़ा जा सकता है। मैं और विस्तार से नहीं जाऊंगा क्योंकि 'पढ़ता है' एक बेहतर समाधान है। –