Eug*_*Loy 6 haskell exception-handling exception
我正在播放haskell中的异常,偶然发现了一件我无法理解的事情.
在GHCi我做:
Prelude Control.Exception> let thrower = (read "A") :: Int
Prelude Control.Exception> :{
Prelude Control.Exception| let main = do
Prelude Control.Exception| x <- (try $ return thrower) :: IO (Either SomeException Int)
Prelude Control.Exception| print x
Prelude Control.Exception| :}
Prelude Control.Exception> main
Run Code Online (Sandbox Code Playgroud)
这定义了thrower我的测试表达式,它会因异常而失败.
然后我定义main将表达式try包装进(将其包装到IO第一个,因为try接受IO)然后将其从IO(由...生成try)和print它展开.
到目前为止,一切看起来都很棒 - main在repl中进行评估会将异常包含在以下内容中:
Right *** Exception: Prelude.read: no parse
Run Code Online (Sandbox Code Playgroud)
但是,如果我尝试编译并执行与应用程序相同的代码:
module Main where
import Control.Exception
thrower = (read "A") :: Int
main = do
x <- (try $ return thrower) :: IO (Either SomeException Int)
print x
Run Code Online (Sandbox Code Playgroud)
...它被异常崩溃:
haskelltest.exe: Prelude.read: no parse
Run Code Online (Sandbox Code Playgroud)
好像异常滑倒了try.
我在这里缺少什么,处理这个问题的正确方法是什么?
好吧,基本上(正如Sebastian Redl先前指出的那样)这是一个严格的问题.return thrower不以任何方式评估thrower,所以try 成功.的内容只有当Either SomeException Int打印,即Right thrower,没有read真正尝试解析"A",而失败......但在这一点上,try已经结束了.
防止这种情况的方法是将解析结果严格地注入IOmonad中
main = do
x <- try $ evaluate thrower :: IO (Either SomeException Int)
print x
Run Code Online (Sandbox Code Playgroud)
为什么try在GHCi中你的代码失败我不知道; 我敢说它不应该.啊哈:正如里德所说,它实际上并没有失败!
可以说,这是为什么在Haskell中通常应该避免异常的一个例子.使用合适的monad变换器来明确可能发生的错误,并获得对错误检查的可靠评估.
你遗漏的部分原因是当你在ghci中运行你的代码时,try也没有捕获到的错误read "A" :: Int.你不期待Left <something>结果吗?请参阅leftaroundabout的答案,了解其原因.
这里ghci和ghc的区别可能是由于输出缓冲:输出到stdout(如此"Right "处)在ghci中是无缓冲的,但默认情况下在编译的程序中缓冲行.
| 归档时间: |
|
| 查看次数: |
184 次 |
| 最近记录: |