如何链接返回 Validated、Option、Either 的函数? (单子变压器)

How to chain functions returning Validated, Option, Either? (Monad Transformer)

我有简单的三个函数返回 arrow-kt 数据类型

fun validate(input): Validated<Error, Input> = ...
fun fetch(input): Option<Error, InputEntity> = ...
fun performAction(inputEntity): Either<Error, Output> = ...

并且想要链接这样的东西(可以使用任何可用的函数而不是 map

validate(input)
  .map{fetch(it)}
  .map{performAction(it)} 

我唯一能想到的解决方案是用 Either 替换 ValidatedOption,并使用 flatMap 链接。有没有更好的 functional 方法让它在不更新现有功能的情况下工作?

您正在寻找的是 Monad Transformer。在 Arrow 中,您可能已经看到它们,它们以 T 结尾。喜欢 OptionTEitherT.

这里有一些 EitherT 的好例子:

https://arrow-kt.io/docs/0.10/arrow/mtl/eithert/

这里是 OptionT:

https://arrow-kt.io/docs/0.10/arrow/mtl/optiont/

想法是选择最终值(假设是 Either)并使用 FX 块,然后您可以使用 EitherT 将其他类型转换为 Either。

@pablisco 描述的是正确的,但您可以使用我们提供的一些语法扩展来简化它,以将其从一种类型转换为另一种类型。请注意,这两个选项都是正确的,但 Monad Transformers 可能有点复杂且功能过于强大,一旦我们最终完全弄清楚我们的定界延续样式,它们也很容易很快从 Arrow 中删除。但这超出了这里的范围。以下是使用我提到的扩展程序解决问题的方法:

import arrow.core.*
import arrow.core.extensions.fx

sealed class Error {
  object Error1 : Error()
  object Error2 : Error()
}

data class InputEntity(val input: String)
data class Output(val input: InputEntity)

fun validate(input: String): Validated<Error, InputEntity> = InputEntity(input).valid()
fun fetch(input: String): Option<InputEntity> = InputEntity(input).some()
fun performAction(inputModel: InputEntity): Either<Error, Output> = Output(inputModel).right()

fun main() {
  val input = "Some input"

  Either.fx<Error, Output> {
    val validatedInput = !validate(input).toEither()
    val fetched = !fetch(validatedInput.input).toEither { Error.Error1 /* map errors here */ }
    !performAction(fetched)
  }
}

希望有用