考虑以下片段。
def foo(x:String): EitherT[F, Throwable, String] = ???
def bar(x:String): EitherT[F, Throwable, String] = ???
我想要以下内容:
在一些输入上 s
,第一次通话 foo(s)
如果 "失败",则返回输出的 bar(s)
否则返回 foo(s)
不鸣则已 bar(s)
. 我想出了以下办法。
def foobar(s:String) = {
val f = foo(s)
// if f is successful return f else return bar(s)
f.biflatMap(_ => bar(s), _ => f)
}
有没有更好的方法来实现我想要的?
是的。recoverWith
:
foo(s).recoverWith { _ =>
bar(s)
}
许多其他错误处理单体也有类似的约定。.recover
将错误类型转化为成功类型,以及将错误类型转化为成功类型。.recoverWith
以错误类型到整体单体类型。有时它们被命名为 handle
和 handleWith
分别。方法无 With
总是采取纯值计算,而带 With
总是采取单项封装类型的计算。
下面是一些实现
import cats.implicits._
import import cats.data.EitherT
foo("").biflatMap(
err => bar(""),
str => EitherT.fromEither[F](str.asRight[Throwable])
)
foo("").biflatMap(
err => bar(""),
str => EitherT.liftF(str.pure[F])
)
foo("").leftFlatMap(
err => bar("")
)
foo("").recoverWith(err => bar(""))
for {
err <- foo("")
x <- bar("")
} yield x
希望对你有所帮助