Scala:对阅读器内部的守护有全面的理解

时间:2019-03-27 09:42:06

标签: scala composition scala-cats for-comprehension reader-monad

这是代码示例:

  type FailFast[A] = Either[List[String], A]
  import cats.instances.either._
  def f1:ReaderT[FailFast, Map[String,String], Boolean] = ReaderT(_ => Right(true))
  def f2:ReaderT[FailFast, Map[String,String], Boolean] = ReaderT(_ => Right(true))

  def fc:ReaderT[FailFast, Map[String,String], Boolean] =
    for {
      b1 <- f1
      if (b1)
      b2 <- f2
    } yield b2

错误是:

  

错误:withFilter的(17,13)值不是的成员   cats.data.ReaderT [TestQ.this.FailFast,Map [String,String],Boolean]         b1 <-f1

如何将f1与f2组成。仅当f1返回Right(true)时才应用f2。我是通过以下方式解决的:

  def fc2:ReaderT[FailFast, Map[String,String], Boolean] =
    f1.flatMap( b1 => {
      if (b1)
        f2
      else ReaderT(_ => Right(true))
    })

但是我希望有一个更优雅的解决方案。

1 个答案:

答案 0 :(得分:1)

  1. 巨大的ReaderT[FailFast, Map[String, String], Boolean]类型令人讨厌。我将其替换为ConfFF-快捷方式(“映射配置的快速失败”);您可能会为此找到一个更好的名字。
  2. 如果需要,您仍然可以使用for理解语法。
  3. 无需每次都写出所有_ =>Right(...),只需使用pure中合适的applicative

因此,您的fc2变为:

  def fc3: ConfFF[Boolean] =
    for {
      b1 <- f1
      b2 <- if (b1) f2 else true.pure[ConfFF]
    } yield b2

完整代码:

import scala.util.{Either, Left, Right}
import cats.instances.either._
import cats.data.ReaderT
import cats.syntax.applicative._

object ReaderTEitherListExample {

  type FailFast[A] = Either[List[String], A]
  /** Shortcut "configured fail-fast" */
  type ConfFF[A] = ReaderT[FailFast, Map[String, String], A]

  def f1: ConfFF[Boolean] = ReaderT(_ => Right(true))
  def f2: ConfFF[Boolean] = ReaderT(_ => Right(true))

  def fc3: ConfFF[Boolean] =
    for {
      b1 <- f1
      b2 <- if (b1) f2 else true.pure[ConfFF]
    } yield b2
}