我会跟着类型走。
val start: OptionT[IO, Int] = OptionT.some[IO](12345)
val thenMap: OptionT[IO, Int] = start.map { value â
println("Mapping over")
value
}
// here it will get off the rails
val thenFlatMapF: OptionT[IO, Int] =
thenMap.flatMapF[Int](_ â IO.raiseError(new RuntimeException("err1")))
val thenToRight: EitherT[IO, FailureMsg, Int] =
thenFlatMapF.toRight(FailureMsg("Code0", None))
val result: IO[Either[FailureMsg, Int]] = thenToRight.value
thenFlatMapF
不会产生
OptionT[IO, Int]
IO.raiseError
是这样的,因为没有
Throwable
为了什么?在折叠结果中会出现异常
.
val thenFlatMapF: OptionT[IO, Int] = thenMap.flatMapF[Int](_ â {
IO.raiseError[Option[Int]](new RuntimeException("err1")).recoverWith {
case err =>
val result: Option[Int] = ???
IO.pure(result)
}
})
如何在不中断的情况下就地处理错误
IO
Option
以便
是生产出来的吗?
flatMapF
如果失败了,需要关于错误的信息,那么最好是
EitherT
作为它的容器,而不是
OptionT
.
一旦完成,可能的解决方案表明,在某一点上
leftMap
或者应该做方差来映射
可抛出
FailureMsg
. 原因之一是
可抛出
. 不能混为一谈
和
可抛出
. 任何一个继承都是必需的,以便
属于类型
Throwable/Exception
,或应在适当位置绘制错误。
我的大致解决方案是:
val fff: IO[Either[FailureMsg, Int]] = OptionT.some[IO](12345)
// ok, let's do some input interpretation
.map { value â
println("Mapping over")
value
}
// if no input, means error
.toRight(FailureMsg("Code0", None))
// if there is interpreted input to process, do it and map the errors
.flatMapF(_ â IO.raiseError[Int](new RuntimeException("err1")).attempt.map(_.leftMap {
case err: RuntimeException if err.getMessage == "err1" => FailureMsg("err1", Some(err))
// just for illustration, that if you have temptation to map on error,
// most likely there won't be only exception
case t: Throwable => FailureMsg("unexpected", Some(t))
}))
.value
但是,通常
平面地图
将是包含错误处理的单独函数或效果。像这样:
val doJob: Int => IO[Either[FailureMsg, Int]] = arg =>
IO.raiseError[Int](new RuntimeException("err1")).attempt.map(_.leftMap {
case err: RuntimeException if err.getMessage == "err1" => FailureMsg("err1", Some(err))
case t: Throwable => FailureMsg("unexpected", Some(t))
})
val fff: IO[Either[FailureMsg, Int]] = OptionT.some[IO](12345)
.map { value â
println("Mapping over")
value
}
.toRight(FailureMsg("Code0", None))
.flatMapF(arg â doJob(arg))
.value