通过for-comprehension和applicative pure来构建ReaderT

问题描述 投票:1回答:1

以下是将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来检查,天气它是RightLeft

但是有没有办法用纯粹的手工作法来组合它。怎么做正确?

scala monads composition monad-transformers scala-cats
1个回答
2
投票

而不是Applicative.pure,你可以使用EitherOps.liftTo来删除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中提取值,那么就无法解决它。

© www.soinside.com 2019 - 2024. All rights reserved.