在 Vavr 中结合两者?

Joh*_*han 6 java functional-programming vavr

我有一对夫妇的Vavr 无论是的,我想调用函数与Right每个这些要么价值。例如:

Either<MyError, String> either1 = ..
Either<MyError, String> either2 = ..
Either<MyError, String> either3 = ..

Either<MyError, String>> methodRequiringAllInputs(String, String, String) { 
..
}
Run Code Online (Sandbox Code Playgroud)

我当然可以做这样的事情:

either1.flatMap { value1 ->
    either2.flatMap { value2 ->
        either3.flatMap { value3 ->
            methodRequiringAllInputs(value1, value2, value3);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

但这是非常丑陋的。在其他语言中,您可以仅使用诸如 do-notation 或推导之类的东西来使结构变平。我知道 Vavr 有一个Validation的概念,它是一个应用函子,允许您执行以下操作:

Validation<MyError, String> validation1 = ..
Validation<MyError, String> validation2 = ..
Validation<MyError, String> validation3 = ..

Validation.combine(validation1, validation2, validation3)
          .ap((validationValue1,validationValue2,validationValue3) -> .. );  
Run Code Online (Sandbox Code Playgroud)

这是更好的。

我的问题是,Vavr 中是否存在类似的东西,可以避免嵌套flatMap结构?请注意,我想要转换Either的到Validation的。

Nán*_*ete 8

vavr 中有一个for comprehension构造,您可以将其用于您的用例。它可以帮助您将多个IterableOptionTryFuture或者List实例到另一个IteratorOptionTryFutureList分别例如,通过组合它们(作为它们的笛卡尔乘积的行)到结果值。

在你的情况下,Either作为一个Iterable正确的值,可以使用For构建Iterables到构造Tuple3了的String正确的价值观,并迭代产生Iterator通过调用您的副作用的代码,或映射/在你想要的任何方式改造他们。您将拥有丰富的vavr Iterator,因此它比简单的 JDK 灵活得多Iterator

import static io.vavr.API.For;

For(either1, either2, either3)
    .yield(Tuple::of)
    .forEach(t -> methodRequiringAllInputs(t._1, t._2, t._3));
Run Code Online (Sandbox Code Playgroud)

不过有一点要注意:在上述情况下, 的结果yield是一个懒惰的评估Iterator。这意味着您最终需要对其进行迭代才能执行效果,因此该forEach部分至关重要。您不能将产生副作用的代码移入yield部分并跳过forEach,因为yield只有Iterator在迭代结果时才会(懒惰地)执行该部分。