斯卡拉猫,用ReaderT组成Reader

时间:2019-03-27 10:35:44

标签: scala composition monad-transformers scala-cats reader-monad

这是一小部分函数,​​所有函数都返回ReaderT

  type FailFast[A] = Either[List[String], A]

  def f1:ReaderT[FailFast, Map[String,String], Boolean] = ReaderT(_ => Right(true))
  def f2:ReaderT[FailFast, Map[String,String], Boolean] = ReaderT(_ => Left(List("d")))
  def f3:ReaderT[FailFast, Map[String,String], Boolean] = ReaderT(_ => Right(true))
  def f4:ReaderT[FailFast, Map[String,String], Boolean] = ReaderT(_ => Right(true))

  def fc:ReaderT[FailFast, Map[String,String], Boolean] =
    f1.flatMap( b1 => {
      if (b1)
        for {
          b2 <- f2
          b3 <- f3
          b4 <- f4
        } yield b4
      else ReaderT(_ => Right(true))
    })

fc返回f1而不返回Reader的情况下如何实现ReaderT

def f1:Reader[Map[String,String], Boolean] = Reader(_ => true)

现在我必须编写Reader,与ReaderT[Id, ...]恰好是Reader[FailFast, ...]

1 个答案:

答案 0 :(得分:2)

正如您提到的,Reader[A, B]只是ReaderT[Id, A, B](它本身只是Kleisli[Id, A, B]的类型别名)。

由于您使用的是猫,因此有一种名为mapK的方法会映射到ReaderT的第一个类型参数上,您只需要提供一个FunctionK/~>实例即可进行转换。因此,在您的情况下,它看起来像这样:

val Id2FailFast = new (Id ~> FailFast) {
  def apply[T](f: Id[T]): FailFast[T] = Right(f) 
}

f1.mapK(Id2FailFast).flatMap( b1 => {
  if (b1)
    for {
      b2 <- f2
      b3 <- f3
      b4 <- f4
    } yield b4
  else ReaderT(_ => Right(true))
})

可能还有其他一些重构可以进一步清理它,例如使用EitherT,但是由于这似乎是一个人为的示例,因此我将其留给读者练习。