scala - 通过 for-compositional 和 applicative pure 来使用 Either 组合 ReaderT

标签 scala monads composition monad-transformers scala-cats

以下函数返回 ReaderTEither 作为返回类型:

  import cats.data.{ReaderT}
  type FailFast[A] = Either[List[String], A]

  def getValue(name: String):ReaderT[FailFast, Map[String, String], String] =
    ReaderT((map) => map.get(name)
      .toRight(List(s"$name field not specified")))

  def nonNullable(name: String)(data: String): FailFast[String] =
    Right(data).ensure(List(s"$name cannot be nullable"))(_ != null)

  def nonBlank(name: String)(data: String): FailFast[String] =
    Right(data).ensure(List(s"$name cannot be blank"))(_.nonEmpty)

以下是这些功能的组合,可以正常工作:

  def readNotEmptyValue(name: String): ReaderT[FailFast, Map[String, String], String] =
    for {
      value <- getValue(name)
      _ <- ReaderT((_:Map[String, String]) => nonNullable(name)(value))
      res <- ReaderT((_:Map[String, String]) => nonBlank(name)(value))
    } yield res

我想摆脱这个 ReaderT.apply 调用,并通过 applicative pure 编写一些东西:

  type Q[A] = ReaderT[FailFast, Map[String, String], A]
  import cats.syntax.applicative._
  import cats.instances.either._
  def readNotEmptyValue(name: String): ReaderT[FailFast, Map[String, String], String] =
    for {
      value <- getValue(name)
      _ <- nonBlank(name)(value).pure[Q]
      res <- nonBlank(name)(value).pure[Q]
    } yield res.right.get

不幸的是,最后一个解决方案不适用于负面情况。我肯定可以使用match来检查它是Right还是Left

但是有没有一种方法可以纯粹地并最小化手动工作来编写它。如何正确地做到这一点?

最佳答案

您可以使用 EitherOps.liftTo 而不是 Applicative.pure删除 ReaderT.apply 的冗长内容:

def readNotEmptyValue(name: String): ReaderT[FailFast, Map[String, String], String] = 
  for {
    value <- getValue(name)
    _ <- nonBlank(name)(value).liftTo[Q]
    res <- nonBlank(name)(value).liftTo[Q]
  } yield res

否则,您仍在处理 FailFast[String] 的实例,而不是 String,如果您想尝试并提取值超出 FailFast

关于scala - 通过 for-compositional 和 applicative pure 来使用 Either 组合 ReaderT,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55314431/

相关文章:

c++ - 共享库中的 D 指针和组合类

scala - 按键分组时,Spark 内存不足

haskell - 如何使用replicateM解决八皇后问题?

polymorphism - 我可以使用 pa_monad 来确保 η 扩展吗?

haskell - 什么时候变质的组合是变质?

javascript - Array.reduce如何将函数作为函数组合中的参数?

scala - 查找在 scala 中传递的 lambda 参数的名称

Scala Option(null) 预期为 None 但我得到了 Some(0)

scala - Akka 流 - 列出各个元素的 mapAsync

Haskell IO 代码不进行类型检查