cat中的预期行为 - 对.delay`或`.map`中引发的异常的影响

bet*_*ess 6 scala scala-cats cats-effect

在PR审查期间,我被要求替换Sync[F].delay,Sync[F].catchNonFatal因为可能会抛出异常.

这确实有效:

scala> Sync[IO].delay(throw new Exception).recover{ case t: Throwable => 42 }.unsafeRunSync
res10: Int = 42
Run Code Online (Sandbox Code Playgroud)

不确定这种行为是否具体IO,我也能找到相应的法律说它实际上是预期的,但我在主要的cat-effect文档中找不到关于API中异常的自动处理的提及.

有谁知道的理由和预期的行为,然后猫效应WRT异常抛出.delay.map.flatMap

Dae*_*yth 0

正如您所发现的,它受到捕获异常的法律的保证delay- 这是 API 的重要组成部分,如果不是这样,它将很难使用。

至于mapflatMap,没有基于法律的保证在这些方法中捕获异常 - 这些方法是在 和Functor类型FlatMap类中定义的,而不是 cats-effect 中。他们期望纯函数,并且捕获抛出的异常不是引用透明的。

然而在实践中,IO具体而言,异常捕获为IO类型契约的一部分。但依赖它来实现通用代码从来都不是理想的选择。

所以,不要写这样的代码

IO(blah).map(a => mightThrow(a))
Run Code Online (Sandbox Code Playgroud)

而是写

IO(blah).flatMap(a => Either.catchNonFatal(mightThrow(a)).liftTo[IO])
Run Code Online (Sandbox Code Playgroud)

理想情况下,如果没有副作用,该mightThrow方法将返回而不是抛出Either