- 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
- 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
- 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
- 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们。
- 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
- 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
第⼗九章: 错误处理
第⼗九章: 错误处理
⽆论使⽤哪门语⾔,错误处理都是程序员最重要–也是最容易忽视– 的话题之⼀ 在
Haskell 中,你会发现有两类主流的错误处理:“纯”的错误处理和异常
当我们说“纯”的错误处理,我们是指算法不依赖任何IO Monad 我们通常会利⽤
Haskell富于表现⼒的数据类型系统来实现这⼀类错误处理 Haskell也⽀持异常 由于
惰性求值复杂性,Haskell 中任何地⽅都可能抛出异常,但是只会在IO monad 中被捕
获 在这⼀章中,这两类错误处理我们都会考虑
使⽤数据类型进⾏错误处理
让我们从⼀个⾮常简单的函数来开始我们关于错误处理的讨论 假设我们希望对⼀系
列的数字执⾏除法运算 分⼦是常数,但是分母是变化的 可能我们会写出这样⼀个
函数:
-- file: ch19/divby1.hs
divBy :: Integral a = a - [a] - [a]
divBy numerat r = map (numerat r `div`)
⾮常简单,对吧?我们可以在 ghci 中执⾏这些代码:
ghci divBy 50 [1,2,5,8,10]
[50,25,10,6,5]
ghci take 5 (divBy 100 [1..])
[100,50,33,25,20]
这个⾏为跟我们预期的是⼀致的:50 / 1 得到50 ,50 / 2 得到25 ,等等 甚⾄对于⽆穷
的链表 [1..] 它也是可以⼯作的 如果有个0溜进去我们的链表中了,会发⽣什么事
呢?
ghci divBy 50 [1,2,0,8,10]
[50,25,*** Excepti n: divide by zer
是不是很有意思? ghci 开始显⽰输出,然后当它遇到零时发⽣了⼀个异常停⽌了 这
是惰性求值的作⽤–它只按需求值
在这⼀章⾥接下来我们会看到,缺乏⼀个明确的异常处理时,这个异常会使程序崩
溃 这当然不是我们想要的,所以让我们思考⼀下更好的⽅式来表征这个纯函数中的
错误
使⽤Maybe
可以⽴刻想到的⼀个表⽰失败的简单的⽅法是使⽤ Maybe 如果输⼊链表中任何地⽅
包含了零,相对于仅仅返回⼀个链表并在失败的时候抛出异常,我们可以返回
othing ,或者如果没有出现零我们可以返回结果的 Just 下⾯是这个算法的实现:
-- file: ch19/divby2.hs
divBy :: Integral a = a - [a] - Maybe [a]
divBy _ [] = Just []
divBy _ (0:_) = N thing
divBy numerat r (den m:xs) =
case divBy numerat r xs f
N thing - N thing
Just results - Just ((numerat r `div` den m) : results)
如果你在 ghci 中尝试它,你会发现它可以⼯作:
ghci divBy 50 [1,2,5,8,10]
Just [50,25,10,6,5]
ghci divBy 50 [1,2,0,8,10]
N thing
调⽤ divBy 的函数现在可以使⽤ case 语句来观察调⽤成功与否,就像 divBy 调⽤⾃⼰
时所做的那样
Tip
你⼤概注意到,上⾯可以使⽤⼀个monadic的实现,像这样⼦:
-- file: ch19/divby2m.hs
divBy :: Integral a = a - [a] - Maybe [a]
divBy numerat r den minat rs =
mapM (numerat r `safeDiv`) den minat rs
where safeDiv _ 0 = N thing
safeDiv x y = x `div` y
出于简单考虑,在这章中我们会避免使⽤monadic实现,但是会指出有这种做法
[译注:Tip 中那段代码编译不过]
丢失和保存惰性
使⽤ Maybe 很⽅便,但是有代价 divBy 将不能够再处理⽆限的链表输⼊ 由于结果
是⼀个 Maybe[a] ,必须要检查整个输⼊链表,我们才能确认不会因为存在零⽽返回
othing 你可以尝试在之前的例⼦中验证这⼀点:
ghci divBy 100
文档评论(0)