【问题标题】:Chaining functions that return Vavr Either返回 Vavr 的链接函数
【发布时间】:2020-08-23 05:11:33
【问题描述】:

我有一系列函数接收一个 Request 对象并返回一个 Vavr Either。

如果任务完成,Either 将包含一个 Result 对象,如果该任务需要由另一个函数完成,则包含一个修改后的 Request 对象。

当时的想法是,我可以通过以下方式将它们链接在一起:

// Note: The Request object parameter is modified by the function 
// before being returned in the Either.
Function<Request, Either<Request,Result>> function1;
Function<Request, Either<Request,Result>> function2;
Function<Request, Either<Request,Result>> function3;
Function<Request, Result> terminalFunction;

Result result = function1.apply(request)
            .flatMapLeft(function2)
            .flatMapLeft(function3)
            .fold(terminalFunction, r->r);

但显然flatMapLeft 不是一个东西,所以我最终在左侧有一个嵌套的 Eithers。关于如何实现此功能的任何想法?我对替代图书馆持开放态度。

编辑:

Result result = function1.apply(request)
            .fold(function2, Either::right)
            .fold(function3, Either::right)
            .fold(terminalFunction, r->r);

似乎这应该可以代替,但是 Intellij 在第二个折叠线上给出了这个错误:

no instance(s) of type variable(s) exist so that capture of ? extends Object conforms to Request

【问题讨论】:

  • 你需要把其中的一个拿进来和拿出来。
  • 在函数中?我不确定我是否喜欢这样。这里的重点是避免不必要地运行附加功能。
  • flatMapLeft 不是一个东西,因为Either&lt;A, B&gt; 只是B 中的一个monad。
  • 抱歉,Java 中的流就是这样工作的。
  • 如果你想让Either 不偏不倚,它就不能是一个monad,因为monad 需要一个类型参数化的单一类型参数(种类* -&gt; *)。当我们使用Either 作为右偏类型时,它通常表示可能失败的计算,monad 实例用于对几个这样的有效计算进行排序。如果您不需要错误上下文,您可以使用无偏见的Either 以及 Bifoldable 类型类、它的 catamorphism、功能棱镜甚至裸模式匹配来处理它。不幸的是我不知道 Java/Vavr...

标签: java functional-programming monads vavr


【解决方案1】:

Request 一侧需要一元组合,它位于类型签名的左侧,但您的 Either 右侧有一元组合。所以你需要在你的函数定义中交换你的或者你必须通过Either.swap() 使用

Function1.of(SomeType::function1).andThen(Either::swap)

基本上,您的每个function[1-3] 都会变成以下类型:

Function<Request, Either<Result, Request>>

那么你的调用链就变成了:

Result result = function1.apply(request)
        .flatMap(function2)
        .flatMap(function3)
        .swap()
        .getOrElseGet(terminalFunction);

【讨论】:

  • 有趣!我想这种方法的缺点是你最终打破了“左等于失败,右等于成功”的约定,但它可能是更好地使用数据结构的方式。
  • 创建Either 的人可能有类似的想法,但不一定(我不知道历史),并且由此产生的构造不再关心。您可以将 left 视为 early returnshort-circuiting,而将 right 视为候选用于进一步处理,即bind。如果您忘记了 lefterror 并以这些术语思考,那么一切都开始变得更有意义。
【解决方案2】:
Result result = function1.apply(request)
            .fold(function2, Either::<Request, Result>right)
            .fold(function3, Either::<Request, Result>right)
            .fold(terminalFunction, r->r);

这似乎可行,尽管它有点笨拙。这是对图书馆的滥用吗?有兴趣听到一些替代方法。

【讨论】:

  • vavr Either 用于保存结果或错误情况。 OP 将其作为元组滥用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多