如何在Haskell中覆盖左侧的错误消息?

huangapple go评论73阅读模式
英文:

How do I override error message on Left in Haskell?

问题

我想从文件中读取,并正在使用左/右模式匹配来判断所说的文件是否存在,如下所示:

tehfile <- readIniFile "somefile_that_does_not_exist.ini"

s <- case tehfile of
    Left a -> print "woot"
    Right b -> ...

我收到的错误是由Data.Ini库生成的:"openFile: 文件不存在(没有该文件或目录)"。
理想情况下,我想要完全覆盖该文本,或者至少在库生成的文本之后添加我的超级有用的 "woot" 字符串。我该如何做,为什么现在的代码中没有发生这种情况?

英文:

I want to read from file and am using pattern matching on Left/Right to tell is said file exists like so:

tehfile &lt;- readIniFile &quot;somefile_that_does_not_exist.ini&quot;

s &lt;- case tehfile of
    Left a -&gt; print &quot;woot&quot;
    Right b -&gt; ...

The error I'm getting is the one generated by Data.Ini library: "openFile: does not exist (No such file or directory)".
Ideally, I'd like to override that text entirely or at least append my super useful "woot" string after the one produced by the library. How can I do that and why doesn't it happen in the code I have now?

答案1

得分: 1

如果您查看 readIniFile 的实现,它只是:

readIniFile :: FilePath -> IO (Either String Ini)
readIniFile = fmap parseIni . T.readFile

首先,它尝试打开并读取文件,然后尝试将内容解析为 INI 配置。如果文件不存在,第一部分将失败并引发异常,第二部分将返回一个 Left。要打印您自己的消息并继续计算,而不是在 Left 情况下进行模式匹配,您将想要使用 catch 处理异常。

λ> import Control.Exception
λ> handler :: IOException -> IO (Either String Ini); handler _ = putStrLn "woot" >> pure (Left "woot")
λ> tehfile <- readIniFile "somefile_that_does_not_exist.ini" `catch` handler
woot

或者,您可以抛出带有您自己消息的错误,以结束计算:

λ> handler :: IOException -> IO (Either String Ini); handler _ = error "woot"
λ> tehfile <- readIniFile "somefile_that_does_not_exist.ini" `catch` handler
*** Exception: woot
CallStack (from HasCallStack):
  error, called at <interactive>...

或编写自己的异常并抛出:

λ> data Woot = Woot deriving (Show)
λ> instance Exception Woot
λ> handler :: IOException -> IO (Either String Ini); handler _ = throwIO Woot
λ> tehfile <- readIniFile "somefile_that_does_not_exist.ini" `catch` handler
*** Exception: Woot

只提供翻译的部分,没有其他内容。

英文:

If you look at the implementation for readIniFile, it's just

readIniFile :: FilePath -&gt; IO (Either String Ini)
readIniFile = fmap parseIni . T.readFile

First it tries to open and read the file, then it tries to parse the contents as an INI config. That first part would fail with an exception if the file doesn't exist, and the second fails with a Left. To print your own message and resume the computation, instead of pattern matching on the Left case you'll want to catch the exception.

λ&gt; import Control.Exception
λ&gt; handler :: IOException -&gt; IO (Either String Ini); handler _ = putStrLn &quot;woot&quot; &gt;&gt; pure (Left &quot;woot&quot;)
λ&gt; tehfile &lt;- readIniFile &quot;somefile_that_does_not_exist.ini&quot; `catch` handler
woot

Or you can throw an error with your own message, to end the computation

λ&gt; handler :: IOException -&gt; IO (Either String Ini); handler _ = error &quot;woot&quot;
λ&gt; tehfile &lt;- readIniFile &quot;somefile_that_does_not_exist.ini&quot; `catch` handler
*** Exception: woot
CallStack (from HasCallStack):
  error, called at &lt;interactive&gt;...

Or write your own exception and throw that

λ&gt; data Woot = Woot deriving (Show)
λ&gt; instance Exception Woot
λ&gt; handler :: IOException -&gt; IO (Either String Ini); handler _ = throwIO Woot
λ&gt; tehfile &lt;- readIniFile &quot;somefile_that_does_not_exist.ini&quot; `catch` handler
*** Exception: Woot

huangapple
  • 本文由 发表于 2020年1月3日 18:48:46
  • 转载请务必保留本文链接:https://go.coder-hub.com/59577203.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定