Скала-кошки, составьте Reader с ReaderT - PullRequest
0 голосов
/ 27 марта 2019

Вот небольшой набор функций, которые возвращают 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 Ответ

2 голосов
/ 27 марта 2019

Как вы упомянули, 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, но так как это выглядит немного надуманным примеромЯ оставлю это как упражнение для читателя.

...