Scala-Cats: создание монадических с прикладными эффектами

#scala #validation #monads #composition #scala-cats

#scala #проверка #монады #композиция #scala-cats

Вопрос:

Вот определения функций, которые возвращают ReaderT:

   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))
  

Я хочу их объединить. f1 и f2 используются как монадические эффекты. Но результат f3 и f4 должен быть накоплен. Я пытаюсь реализовать что-то, что выглядит как:

   def fc:ReaderT[FailFast, Map[String,String], Boolean] =
    f1.flatMap( b1 => {
      if (b1)
        for {
          b2 <- f2
          b3 <- Semigroupal.tuple2[FailSlow, Boolean, Boolean](
            f3, // how to convert it to validated here without run?
            f4  // how to convert it to validated here without run?
          ).toEither
        } yield b3
      else ReaderT(_ => Right(true))
    })
  

Если существует более одного варианта, пожалуйста, предложите оба

Комментарии:

1. Подходит ли вам мой ответ?

2. @DmytroMitin, извини, чувак, я проверю это чуть позже и дам тебе знать

Ответ №1:

Попробуйте

 import cats.instances.either._
import cats.instances.list._

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

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