因此,通常当我们运行既可以失败又返回值的方法时,我们可以将方法返回类型编码为Either[SomeErrorType, ReturnType]
。但很多时候我们正在为其副作用运行方法,因此返回类型为Unit
。
我当然可以返回Either[SomeErrorType, Unit]
,但这看起来确实很奇怪。
我也可以只返回一个Option[SomeErrorType]
,但它看起来并没有那么好(并打破了与其他Either[SomeErrorType, NonUnitReturnType]
s可能存在的对称性。
在这些情况下你的做法是什么?
def m(): Unit // and implicitly know that exceptions can be thrown?
; def m(): Either[SomeErrorType, Unit] // this is odd
; def m(): Option[SomeErrorType] // this is odd, as it makes it look as the return type of
M()on a successful run is an error code.
由于
答案 0 :(得分:10)
我在这种情况下使用Try[Unit]
。
它编码该方法的结果成功或失败并带有一些Exception
,可以进一步处理。
T => Unit
Try
将错误提升到应用程序级别,在签名中编码可能会出现一些错误,并允许应用程序将其作为值处理。 Option[T]
=>选项只能编码操作具有值Either[SomeErrorType, Unit]
=> Try
使用monadic结构更容易。 我使用过这样的东西来实施支票。 (想象的例子)
for {
entity <- receiveEntity // Try[Entity]
_ <- isRelational(entity)
_ <- isComplete(entity)
_ <- isStable(entity)
} yield entity
每张支票的格式为:Entity => Try[Unit]
如果所有检查都未通过检查失败的第一个错误,则返回entity
。
答案 1 :(得分:2)
尚未提及的另一个选项是来自cats的Validated
。到目前为止提到的所有选项(Try
,Either
,Option
)都是monad,而Validated
是一个应用函子。实际上,这意味着您可以从返回Validated
的多个方法中累积错误,并且可以并行执行多个验证。这可能与您无关,这与原始问题有点正交,但我仍然觉得在这种情况下值得一提。
至于原始问题,使用Unit
返回类型作为副作用函数是完全正常的。当您定义&#34;真实&#34;时,此功能也可以返回错误这一事实不应该妨碍您。 (右,成功等)返回类型。因此,如果我要从原始选项中进行选择,请转到Either[Error, Unit]
。对我来说绝对不奇怪,如果有人发现它有任何缺点,我想知道它们。