Scala: композиция ReaderT с различными контекстами и зависимостями - PullRequest
0 голосов
/ 05 апреля 2019

Пример функций s3f1 и s3f2, которые возвращают разные ReaderT:

type FailFast[A] = Either[List[String], A]
trait Service1 { def s1f:Option[Int] = Some(10) }
trait Service2 { def s2f:FailFast[Int] = Right(20) }

import cats.instances.option._

def s3f1: ReaderT[Option, Service1, Int] =
  for {
    r1 <- ReaderT((_: Service1).s1f)
  } yield r1 + 1

import cats.syntax.applicative._
import cats.instances.either._

type ReaderService2FF[A] = ReaderT[FailFast, Service2, A]

def s3f2: ReaderService2FF[Int] =
  for {
    r1 <- ReaderT((_: Service2).s2f)
    r2 <- 2.pure[ReaderService2FF]
  } yield r1 + r2

Я пытаюсь составить эти две функции, которые возвращают читатели с различными F[_] контекстами и зависимостями: ReaderT[Option, Service1, Int] иReaderT[FailFast, Service2, Int]

Мне нужно как-то объединить контекст F[_], что означает объединение FailFast с Option.Я предполагаю, что имеет смысл объединить это с FailFast[Option]:

type Env = (Service1, Service2)
type FFOption[A] = FailFast[Option[A]]
type ReaderEnvFF[A] = ReaderT[FFOption, Env, A]

Как составить s3f1 и s3f2:

def c: ReaderEnvFF[Int] =
  for {
    r1 <- //s3f1
    r2 <- //s3f2
  } yield r1 + r2

1 Ответ

0 голосов
/ 05 апреля 2019

Поскольку вы пытаетесь составить монады FailFast и Option в FFOption, вам следует использовать еще один преобразователь монад, поэтому FFOption[A] должно быть OptionT[FailFast, A], а не просто FailFast[Option[A]].

import cats.instances.option._
import cats.instances.either._
import cats.syntax.applicative._
import cats.syntax.either._
import cats.syntax.option._

type Env = (Service1, Service2)
type FFOption[A] = OptionT[FailFast, A]
type ReaderEnvFF[A] = ReaderT[FFOption, Env, A]

def c: ReaderEnvFF[Int] =
  for {
    r1 <- ReaderT[FFOption, Env, Int](p => OptionT(Either.right(s3f1.run(p._1))))     
    r2 <- ReaderT[FFOption, Env, Int](p => OptionT(s3f2.run(p._2).map(_.some)))                          
  } yield r1 + r2

Это можно переписать с помощью local и mapF:

def c: ReaderEnvFF[Int] =
  for {
    r1 <- s3f1.local[Env](_._1).mapF[FFOption, Int](opt => OptionT(opt.asRight))
    r2 <- s3f2.local[Env](_._2).mapF[FFOption, Int](ff => OptionT(ff.map(_.some)))                      
  } yield r1 + r2
...