dur*_*597 6 java monads java-8 vavr
我有一个Try<Option<Foo>>.我想flatMap Foo进入a Bar,使用可能失败的操作使用它.如果我Option<Foo>是一个Option.none()(并且Try是成功的)并且在这种情况下没有任何关系,这不是失败.
所以我有这样的代码,它确实有效:
Try<Option<Bar>> myFlatMappingFunc(Option<Foo> fooOpt) {
return fooOpt.map(foo -> mappingFunc(foo).map(Option::of) /* ew */)
.getOrElse(Try.success(Option.none()); // double ew
}
Try<Bar> mappingFunc(Foo foo) throws IOException {
// do some mapping schtuff
// Note that I can never return null, and a failure here is a legitimate problem.
// FWIW it's Jackson's readValue(String, Class<?>)
}
Run Code Online (Sandbox Code Playgroud)
然后我称之为:
fooOptionTry.flatMap(this::myFlatMappingFunc);
Run Code Online (Sandbox Code Playgroud)
这确实有效,但看起来真的很难看.
Try和Option左右?注1:我主动不想在内部调用Option.get()和捕获它,Try因为它在语义上不正确.我想我可以恢复,NoSuchElementException但这似乎更糟糕,代码方面.
注2(解释标题):天真地,显而易见的事情是:
Option<Try<Bar>> myFlatMappingFunc(Option<Foo> fooOpt) {
return fooOpt.map(foo -> mappingFunc(foo));
}
Run Code Online (Sandbox Code Playgroud)
除了这有错误的签名,并且不允许我映射可能失败的先前操作并且还返回成功的缺乏值.
小智 1
当您使用 monad 时,每种 monad 类型仅与相同类型的 monad 组合。这通常是一个问题,因为代码非常不可读。
在 Scala 世界中,有一些解决方案,例如OptionT或EitherT转换器,但在 Java 中实现这种抽象可能很困难。
简单的解决方案是仅使用一种 monad 类型。
对于这种情况,我可以考虑两种选择:
Try<Foo>使用.toTry()函数式程序员通常更喜欢“Either”,因为异常会产生奇怪的行为,而“Either”通常不会,当您只想知道失败的原因和位置时,两者都适用。
使用 Either 的示例将如下所示:
Either<String, Bar> myFlatMappingFunc(Option<Foo> fooOpt) {
Either<String, Foo> fooE = fooOpt.toEither("Foo not found.");
return fooE.flatMap(foo -> mappingFunc(foo));
}
// Look mom!, not "throws IOException" or any unexpected thing!
Either<String, Bar> mappingFunc(Foo foo) {
return Try.of(() -> /*do something dangerous with Foo and return Bar*/)
.toEither().mapLeft(Throwable::getLocalizedMessage);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
325 次 |
| 最近记录: |