Haskell库引发异常的背后的想法是什么 [英] What's the idea behind Haskell libraries throwing exceptions

查看:85
本文介绍了Haskell库引发异常的背后的想法是什么的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为什么图书馆(例如404上的 wreq )会抛出一个而不是将结果包装到Maybe?

Why would a library (wreq on a 404 for example) throw an exception instead of wrapping the result into something like Maybe?

天真的,我认为Maybe会更好(例如,如果我不处理所有情况,编译器会警告我).为什么我在这里错了?

Naively, I think Maybe would be better (compiler warning me if I'm not handling all the cases for example). Why am I wrong here?

推荐答案

Haskellers竭力避免抛出来自 functions 的异常–函数仅应在真正例外的情况下抛出异常,即这种情况永远不会发生",例如用户传递了文档明确禁止的某些输入.如果纯函数定期抛出异常,那么这将是一个大问题,不仅因为类型没有说明应该准备捕获什么,而且不能也不能捕获纯函数中的异常,而仅仅是在调用该函数的IO代码中.而且即使您原则上可以捕获异常,也可能很难预测在何处,因为惰性评估会延迟实际发生的时间.

Haskellers do strongly strive to avoid throwing exceptions from functions – a function should only throw an exception in truely exceptional cases, i.e. in "this should never happen" situations like the user passing some input that's explicitly forbidden by the documentation. If pure functions regularly threw exceptions, this would be a big problem not only because the type doesn't say what one should be prepared to catch, also one can't catch exceptions within a pure function but only in IO code that calls the function. And even if you can in principle catch the exception, it may be hard to predict where it needs to be done because lazy evaluation can delay the point where it actually happens.

事实上,即使在 Wreq.get 该函数不会引发任何异常.

Prelude Network.Wreq> get "htt:/p/this-isn't even valid URL syntax" `seq` "Ok"
"Ok"

执行时抛出的是 IO动作:

It is the IO action that throws, when you execute it:

Prelude Network.Wreq> get "htt:/p/this-isn't even valid URL syntax" >> pure ()
*** Exception: InvalidUrlException "htt:/p/this-isn't%20even%20valid%20URL%20syntax" "Invalid scheme"

现在使用IO动作,情况有所不同. 动作的很多在不同情况下可能具有非常不同的错误,这些错误可能很难或无法预测,例如硬盘驱动器崩溃.用适合的数据类型为每个操作对所有可能的错误进行分类将是一项艰巨的任务,并且处理每种可能的情况或弄清楚哪些部分继续下去是非常麻烦的.并且简单地将每个IO操作的结果包装在Maybe中将导致与Java中类似的情况,在Java中,每个引用都可能为空.这不会告诉您任何信息,而且人们通常也不会想出处理此问题的明智方法.

Now with an IO action, the situation is a bit different. Lots of IO actions can have potentially very different errors in different situations that may be hard or impossible to predict, like a hard-drive crash. Catalogising all the possible errors in a suitable data type for each action would be a major undertaking, and it would be really quite cumbersome to handle every possible case or figure out which parts just to pass on. And simply wrapping the result of every single IO action in Maybe would just lead to a similar situation as in Java where every reference can possibly null. This doesn't tell you anything, and people often wouldn't come up with sensible ways of handling this either.

这几乎就是为什么首先发明例外的问题,它在程序语言中和在Haskell中一样适用(或更确切地说,它是程序cDSL,即IO).而且由于与纯函数不同,IO在控制流中确实具有明确定义的时间顺序,因此,如果需要捕获某些特殊异常,则也很清楚必须在哪里执行.

This is pretty much the problem why exceptions were invented in the first place, and it holds just as well for procedural languages as it holds for Haskell (or rather, it's procedural eDSL that is IO). And because unlike pure functions, IO does have a well-defined time-sequence in its control flow, it's also pretty clear where you must do it if you need to catch some particular exception.

这并不是说IO动作返回Maybe/Either值(使可能的错误变得明确)永远是没有意义的,但这并不总是值得的.

That's not to say it never makes sense for an IO action to return a Maybe / Either value that makes the possible errors explicit, just this isn't always worthwhile.

这篇关于Haskell库引发异常的背后的想法是什么的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆