【发布时间】:2019-08-15 07:55:29
【问题描述】:
因此,当前的实现使用 twitter 的 Future 以及抛出异常来表示无效用例以及 for-comprehensions,如下所示:
def someMethod(a: ...): Future[X] = {
// do something
// if something goes wrong throw exception
throw new Exception("Certificate not issued")
}
// in some other method, where exceptions break the loop and exit
def someOtherMethod(a: ...): Future[Y] = {
for {
x <- someMethod(...)
y <- yetAnotherMethod(...) // which throws another exception
} yield y
}
一般的想法是,当出现问题时,会引发异常,这将导致退出for-comprehension 块。
我想避免抛出异常。解决它的一种方法是返回Either[Error, X],另一种方法是使用sealed trait 返回ADT。因此,您可以返回Left(Error) 或ADT,而不是抛出Exception,例如case object NoCertificate extends CertificateResponse。
问题是:如果我用Either 或ADT 替换当前具有throw Exception 的方法,我能否保持现有for 循环不变?
为了完整起见,下面是我的 Either 和 ADT 编码方式:
sealed trait Error
case object CertificateError extends Error
case object SomeOtherError extends Error
def someMethod(a: ...): Future[Either[Error, CertificateResponse]] = {
// returns Left(CertificateError) or Right(CertificateResponse)
}
或
sealed trait CertificateResponse
case class Certificate(x509) extends CertificateResponse
case object NoCertificate extends CertificateResponse
def someMethod(a: ...): Future[CertificateResponse] = {
// returns NoCertificate or Certificate(X509)
}
这些替代解决方案(抛出异常和破坏引用透明度)中的任何一个都可以与for-comprehensions 一起使用吗?否定响应:Left() 或 NoCertificate 会自动退出for-comprehension 块吗?如果没有,如何制作,以便我可以保持 for-comprehension 块原样?类似于cats EitherT's leftMap 的东西?
请注意:我们不能像EitherT 那样使用cats Monad Transformer(它有leftMap 表示退出条件),因为这不是我们在堆栈中使用的库之一。对不起!
谢谢!
【问题讨论】:
-
Scalaz 还包含一个
EitherT,该库是一个选项吗?因为实际上,您指定的行为是准确地使用 monad 转换器得到的,如果您不能使用库,那么您将不得不手动编写代码。
标签: scala adt for-comprehension either