在字符串解析期间捕获错误

时间:2012-01-13 12:03:47

标签: haskell

我想解析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
}

我不知道怎么用你的答案来做...

1 个答案:

答案 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}},了解如何执行此操作。