【问题标题】:Scala-cats, compose Reader with ReaderTScala-cats,用 ReaderT 编写 Reader
【发布时间】:2019-08-17 21:32:25
【问题描述】:

这是一个小的函数组合,所有这些函数都返回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, ...]

【问题讨论】:

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


    【解决方案1】:

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

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

    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,但由于这似乎是一个人为的例子,我将把它留给读者作为练习。

    【讨论】:

    • 谢谢。我尝试使用这种方法,但出现了一些错误,使用了 mapF 而不是 mapK,并且没有 Id2FailFast 辅助函数无法正确转换它。我必须应用于您的解决方案的唯一更改是将 f 类型从 Id 更改为 Id[T]。没有它我得到一个错误:类型 Id 采用类型参数 def apply[T](f: Id): FailFast[T] = Right(f)
    猜你喜欢
    • 2019-08-27
    • 1970-01-01
    • 2019-05-19
    • 2021-02-25
    • 2019-04-09
    • 2018-10-08
    • 2019-12-24
    • 1970-01-01
    • 2022-01-22
    相关资源
    最近更新 更多