将不同结果类型的多个`Try`实例组合为可应用的

时间:2018-11-13 04:10:30

标签: java-8 functional-programming vavr

在Vavr中是否有用于合并Try实例的api,类似于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

1 个答案:

答案 0 :(得分:3)

据我所知,它不直接支持该用法。但是,您可以使用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))))
    );
}

如果比较输入和输出类型,则可以看到这实际上交换了TryList容器的位置。对于monads来说,这是相当习惯的做法,尽管通常您可以通过应用地图操作而不是flatMap来实现它。

或者,使用Validation,它旨在以应用方式使用(通过Validation.combine)。