Có tồn tại một thành ngữ đọc bên trong một đơn nguyên:
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 ++ "\""
đó là không an toàn cho IO
đơn nguyên:
> readM "CmdOther" :: IO Cmd
CmdOther
> readM "Cmd?Other" :: IO Cmd
*** Exception: user error (Failed to parse: "Cmd?Other")
vì fail
ném một ngoại lệ IOError
trong trường hợp IO
, trong đó, tuy nhiên , có thể được xử lý:
*Main> (readM "Cmd?Other" :: IO Cmd) `catch` const (return CmdOther)
CmdOther
Và an toàn trong trường hợp Maybe
đơn nguyên:
> readM "CmdOther" :: Maybe Cmd
Just CmdOther
> readM "Cmd?Other" :: Maybe Cmd
Nothing
vì fail
là const Nothing
trong trường hợp này.
Dù sao, nếu bạn muốn có một tổng chức năng guiString2Cmd
với một chữ ký String -> Cmd
bạn có thể viết nó giống như readM
:
guiString2Cmd :: String -> Cmd
guiString2Cmd s | [x] <- [x | (x, "") <- reads s] = x
| otherwise = CmdExit
và sau đó:
> guiString2Cmd "CmdOther"
CmdOther
> guiString2Cmd "Cmd?Other"
CmdExit
cách tiếp cận Hơi chung chung hơn.
Đối *
loại:
class Failable0 t where
fail0 :: t
readG0 :: (Failable0 t, Read t) => String -> t
readG0 s | [x] <- [x | (x, "") <- reads s] = x
| otherwise = fail0
thì:
instance Failable0 Cmd where
fail0 = CmdExit
Đối * -> *
loại:
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 ++ "\""
Sử dụng nội dung đã có thể là một ý tưởng tốt hơn thực sự ... – mbrodersen
Vâng, là tốt nhất cách để xử lý một ngoại lệ thuần túy là không tạo ra nó ngay từ đầu. – dave4420
Đối với hồ sơ, ngoại lệ (bao gồm cả những người được ném bởi 'đọc') chỉ có thể bị bắt trong đơn IO, sử dụng các hàm được cung cấp trong' Control.Exception'. Tôi sẽ không đi vào chi tiết hơn bởi vì 'lần đọc' là một giải pháp tốt hơn. –