3
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.Cats required:com .savdev.Cats } 产生猫

你能解释一下,为什么猫不是com.savdev.Cats?以及为什么在错误中,它说它被扩展为具有返回方法的函数[Cats],而不是机器人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)
...
4

1 回答 1

6

toReaderEnvFF((_: Env)._3)incats <- toReaderEnvFF((_: Env)._3)实际上是toReaderEnvFF[A]((_: Env)._3)针对某种类型的A。现在是什么A?因为(_: Env)._3(aka inputin toReaderEnvFF) 是类型Env => Cats,所以类型AEnv => Cats. 所以toReaderEnvFF((_: Env)._3)是 type ReaderEnvFF[Env => Cats]catsincats <- toReaderEnvFF((_: Env)._3)是 type Env => Cats

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

ReaderT((_: Service1).s1f)在你的第二个例子中是 typeReaderT[Option, Service1, Int]所以r2inr2 <- ReaderT((_: Service1).s1f)是 type Int。但是在你的第一个例子toReaderEnvFF((_: Env)._3)中是类型ReaderEnvFF[Env => Cats]akaReaderT[FailFast, Env, Env => Cats]所以catsincats <- toReaderEnvFF((_: Env)._3)是类型Env => Cats。这就是区别。

如果你想与之合作,ReaderEnvFF[Cats]那么你应该改变cats <- toReaderEnvFF(???). 例如

def c:ReaderEnvFF[Cats] =
  for {
    cats <- toReaderEnvFF(Cats("aaa"))
  } yield cats 
于 2019-04-08T06:54:10.620 回答