我想解析String以获取Int,我使用它:
string2int :: String -> Int
string2int str = read str::Int
现在我想尽可能地将备用异常/错误视为SIMPLY。 我试过了:
import qualified Control.Exception as E
eVal <- try (print (string2int "a")) :: IO (Either E.SomeException ())
case eVal of
Left e -> do { putStrLn "exception"; }
Right n -> do { putStrLn "good"; }
但是编译器说couldn't match expected type 'E.SomeException()'
with actual type E.IOException
。
我做错了什么?
好的我不知道怎么用它来解决我的问题:我想要这样的事情:
loadfunction = do
{
x <- string2int getLine
if( failed parsing int ) call somefunction
y <- string2int getLine
if( failed parsing int ) call somefunction
otherfunction x y
}
我不知道怎么用你的答案来做...
答案 0 :(得分:7)
您正在使用从旧异常机制导入的try
,但正在尝试使用其结果类型,就像它使用新的可扩展Control.Exception机制一样。请改用E.try
。
理想情况下,您应该像这样导入Control.Exception:
import Prelude hiding (catch)
import Control.Exception
并删除Control.OldException的所有导入。然后你可以直接使用它的功能,而不用担心任何冲突。
顺便说一下,您不必使用IO异常来处理读取错误;您可以改为使用reads
:
reads :: (Read a) => String -> [(a, String)]
以下是我使用reads
编写代码的方式:
case reads "a" of
[(a, "")] -> do
print a
putStrLn "good"
_ -> putStrLn "exception"
reads
返回列表的事实是a little confusing;实际上,您可以将其视为返回Maybe (a, String)
。如果您想要使用Maybe
的版本,可以像这样定义:
readMaybe :: (Read a) => String -> Maybe a
readMaybe s =
case reads s of
[(a, "")] -> Just a
_ -> Nothing
使您的代码成为:
case readMaybe "a" of
Just a -> do
print a
putStrLn "good"
Nothing -> putStrLn "exception"
(您也可以将readMaybe
定义为listToMaybe . map fst . filter (null . snd) . reads
,就像dave4420那样;它们在实践中是等效的,因为没有一个标准Read
实例返回多个元素的列表。)
一般情况下,您应尽可能尝试使用此类纯错误处理方法,并且只有在没有其他选项时才使用IO异常,或者您正在处理特定于IO的代码(如文件/网络处理,等等。)。但是,如果您想坚持使用例外,请使用E.try
来修复错误。
然而,基于您更新的问题,例外可能是正确的方法;像ErrorT这样的东西也可以工作,但是如果你已经在IO中做了所有事情,那么使用异常就没什么坏处。所以我会写这样的例子:
loadfunction = do
line1 <- getLine
x <- string2int line1
line2 <- getLine
y <- string2int line2
otherfunction x y
并使用E.catch
来处理它抛出的异常;请查看catch
{{1}},了解如何执行此操作。