斯卡拉猫:读者组成

时间:2019-04-08 06:37:18

标签: scala scala-cats for-comprehension reader-monad

import cats.data.ReaderT
import cats.instances.either._

trait Service1
trait Service2
case class Cats(name:String)

type FailFast[A] = Either[List[String], A]
type Env = (Service1, Service2, Cats)
type ReaderEnvFF[A] = ReaderT[FailFast, Env, A]

def toReaderEnvFF[A](input:A):ReaderEnvFF[A] =
  ReaderT((_:Env) => Right(input))

def c:ReaderEnvFF[Cats] =
  for {
    cats <- toReaderEnvFF((_:Env)._3)
  } yield cats   // This line is 26

错误:

  

错误:(26,11)类型不匹配;找到:T1.this.Env =>   com.savdev.Cats       (扩展为)((com.savdev.Service1,com.savdev.Service2,com.savdev.Cats))=> com.savdev。需要的猫:com.savdev.Cats}   养猫

请您解释一下,为什么猫不是com.savdev.Cats?以及为什么会出现错误,它表示将其扩展为具有返回方法[Cats]的功能,而不是bot FailFast[Cats]

我尝试应用与此处完全相同的逻辑:

trait Service1 { def s1f = Option(10) }
trait Service2 {
  type ReaderS1[A] = ReaderT[Option,Service1,A]
  import cats.syntax.applicative._
  import cats.instances.option._
  def s2f:ReaderS1[Int] =
    for {
      r2 <- ReaderT((_: Service1).s1f)
      r1 <- 1.pure[ReaderS1]
    } yield r1 + r2
}

在此示例中,我可以将Service1.s1f函数转换为其结果r2,并且可以正常工作。为什么我不能这样写例如:

for {
 cats <- ReaderT((_:Env)._3)
...

1 个答案:

答案 0 :(得分:5)

对于某些类型toReaderEnvFF((_: Env)._3)cats <- toReaderEnvFF((_: Env)._3)中的

toReaderEnvFF[A]((_: Env)._3)实际上是AA现在是什么?由于(_: Env)._3(在input中又名toReaderEnvFF)的类型为Env => Cats,因此类型AEnv => Cats。因此toReaderEnvFF((_: Env)._3)的类型为ReaderEnvFF[Env => Cats]cats中的cats <- toReaderEnvFF((_: Env)._3)的类型为Env => Cats

x <- SomeMonad[T]中,变量x的类型为T(现在SomeMonadReaderEnvFFTEnv => Cats)。

在第二个示例中,

ReaderT((_: Service1).s1f)的类型为ReaderT[Option, Service1, Int],因此r2中的r2 <- ReaderT((_: Service1).s1f)的类型为Int。但是在您的第一个示例中,toReaderEnvFF((_: Env)._3)的类型为ReaderEnvFF[Env => Cats],又名ReaderT[FailFast, Env, Env => Cats],因此cats中的cats <- toReaderEnvFF((_: Env)._3)的类型为Env => Cats。就是这样。

如果您想使用ReaderEnvFF[Cats],则应该更改cats <- toReaderEnvFF(???)。例如

def c:ReaderEnvFF[Cats] =
  for {
    cats <- toReaderEnvFF(Cats("aaa"))
  } yield cats