将不同结果类型的多个“Try”实例组合为应用程序
Combining multiple `Try` instances of different result types as applicatives
是否有一个 api 用于在 Vavr 中组合 Try
个实例,类似于 Scalaz 应用运算符 |@|
的工作方式?
具体来说,如果我有两个以上的 Try
实例,例如 Try<X>
、Try<Y>
和 Try<Z>
,我想将这些实例组合成一个使用 3-arg 函数的应用时尚。
我正在寻找类似于以下内容的函数签名:
static <X, Y, Z, R> Try<R> combine(Try<X> x, Try<Y> y, Try<Z> z, Function3<X,Y,Z,R> func
据我所知,它不直接支持该用法。但是,您可以使用 flatMap 实现它:
static <X, Y, Z, R> Try<R> combine(Try<X> tx, Try<Y> ty, Try<Z> tz, Function3<X,Y,Z,R> func) {
return tx.flatMap(x -> ty.flatMap(y -> tz.map(z -> func.apply(x, y, z))));
}
如果每个 Try 值包含相同的类型,那么您可以使用 sequence
操作:
public static void main(String[] args) {
List<Try<String>> lt = List.of(Try.success("A"), Try.success("B"), Try.success("C"));
Try<List<String>> tl = sequence(lt);
System.out.println(tl);
}
static <T> Try<List<T>> sequence(List<Try<T>> lt) {
return lt.foldRight(
Try.success(List.empty()),
(tt, tl) -> tt.flatMap(t -> tl.flatMap(l -> Try.success(l.prepend(t))))
);
}
如果比较输入和输出类型,您会发现这实质上交换了 Try
和 List
容器的位置。这对于 monad 来说是相当惯用的,尽管通常您会使用应用映射操作而不是 flatMap 来实现它。
或者,使用 Validation,它被设计用于应用风格(通过 Validation.combine
)。
正如您提到的,vavr 上没有类似的方法,但是您可以采取一些解决方法:
使用元组:
Try.success(authorizationHeader)
.map(mapper::hcpFrom)
.map(hcp -> Tuple.of(hcp, mapper.toSaveNoteRequest(noteId, patientId, requestBody, clock)))
.map(t2 -> saveNoteUseCase.execute(t2._1(), t2._2()))
.map(mapper::toHcpNoteResponse)
.map(response -> accepted().body(response))
.get();
使用 For 产生:
For(Try.success(authorizationHeader).map(mapper::hcpFrom), Try.success(mapper.toSaveNoteRequest(noteId, patientId, requestBody, clock)))
.yield(saveNoteUseCase::execute)
.map(mapper::toHcpNoteResponse)
.map(response -> accepted().body(response))
.get();
在 flatMap 中使用代码:
Try.success(authorizationHeader)
.map(mapper::hcpFrom)
.flatMap(hcp-> Try.of(() -> mapper.toSaveNoteRequest(noteId, patientId, requestBody, clock)).map(saveNoteRequest -> saveNoteUseCase.execute(hcp, saveNoteRequest)))
.map(mapper::toHcpNoteResponse)
.map(response -> accepted().body(response))
.get();
最后使用 futures(如 api,但不推荐)
Try.success(authorizationHeader).map(mapper::hcpFrom).toCompletableFuture()
.thenCombine(Try.success(mapper.toSaveNoteRequest(noteId, patientId, requestBody, clock)).toCompletableFuture(), saveNoteUseCase::execute)
.thenApply(mapper::toHcpNoteResponse)
.thenApply(response -> accepted().body(response))
.join();
亲切的问候。
是否有一个 api 用于在 Vavr 中组合 Try
个实例,类似于 Scalaz 应用运算符 |@|
的工作方式?
具体来说,如果我有两个以上的 Try
实例,例如 Try<X>
、Try<Y>
和 Try<Z>
,我想将这些实例组合成一个使用 3-arg 函数的应用时尚。
我正在寻找类似于以下内容的函数签名:
static <X, Y, Z, R> Try<R> combine(Try<X> x, Try<Y> y, Try<Z> z, Function3<X,Y,Z,R> func
据我所知,它不直接支持该用法。但是,您可以使用 flatMap 实现它:
static <X, Y, Z, R> Try<R> combine(Try<X> tx, Try<Y> ty, Try<Z> tz, Function3<X,Y,Z,R> func) {
return tx.flatMap(x -> ty.flatMap(y -> tz.map(z -> func.apply(x, y, z))));
}
如果每个 Try 值包含相同的类型,那么您可以使用 sequence
操作:
public static void main(String[] args) {
List<Try<String>> lt = List.of(Try.success("A"), Try.success("B"), Try.success("C"));
Try<List<String>> tl = sequence(lt);
System.out.println(tl);
}
static <T> Try<List<T>> sequence(List<Try<T>> lt) {
return lt.foldRight(
Try.success(List.empty()),
(tt, tl) -> tt.flatMap(t -> tl.flatMap(l -> Try.success(l.prepend(t))))
);
}
如果比较输入和输出类型,您会发现这实质上交换了 Try
和 List
容器的位置。这对于 monad 来说是相当惯用的,尽管通常您会使用应用映射操作而不是 flatMap 来实现它。
或者,使用 Validation,它被设计用于应用风格(通过 Validation.combine
)。
正如您提到的,vavr 上没有类似的方法,但是您可以采取一些解决方法:
使用元组:
Try.success(authorizationHeader)
.map(mapper::hcpFrom)
.map(hcp -> Tuple.of(hcp, mapper.toSaveNoteRequest(noteId, patientId, requestBody, clock)))
.map(t2 -> saveNoteUseCase.execute(t2._1(), t2._2()))
.map(mapper::toHcpNoteResponse)
.map(response -> accepted().body(response))
.get();
使用 For 产生:
For(Try.success(authorizationHeader).map(mapper::hcpFrom), Try.success(mapper.toSaveNoteRequest(noteId, patientId, requestBody, clock)))
.yield(saveNoteUseCase::execute)
.map(mapper::toHcpNoteResponse)
.map(response -> accepted().body(response))
.get();
在 flatMap 中使用代码:
Try.success(authorizationHeader)
.map(mapper::hcpFrom)
.flatMap(hcp-> Try.of(() -> mapper.toSaveNoteRequest(noteId, patientId, requestBody, clock)).map(saveNoteRequest -> saveNoteUseCase.execute(hcp, saveNoteRequest)))
.map(mapper::toHcpNoteResponse)
.map(response -> accepted().body(response))
.get();
最后使用 futures(如 api,但不推荐)
Try.success(authorizationHeader).map(mapper::hcpFrom).toCompletableFuture()
.thenCombine(Try.success(mapper.toSaveNoteRequest(noteId, patientId, requestBody, clock)).toCompletableFuture(), saveNoteUseCase::execute)
.thenApply(mapper::toHcpNoteResponse)
.thenApply(response -> accepted().body(response))
.join();
亲切的问候。