【问题标题】:Scala-cats: reader-compositionScala-cats:阅读器组合
【发布时间】:2019-08-29 06:04:23
【问题描述】:
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)
...

【问题讨论】:

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


    【解决方案1】:

    cats &lt;- toReaderEnvFF((_: Env)._3) 中的toReaderEnvFF((_: Env)._3) 对于某些类型A 实际上是toReaderEnvFF[A]((_: Env)._3)A 现在是什么?因为(_: Env)._3(又名input in toReaderEnvFF)是Env =&gt; Cats 类型,那么A 类型是Env =&gt; Cats。所以toReaderEnvFF((_: Env)._3)ReaderEnvFF[Env =&gt; Cats] 类型,而cats &lt;- toReaderEnvFF((_: Env)._3) 中的catsEnv =&gt; Cats 类型。

    x &lt;- SomeMonad[T] 中,变量xT 类型(现在SomeMonadReaderEnvFFTEnv =&gt; Cats)。

    第二个示例中的ReaderT((_: Service1).s1f)ReaderT[Option, Service1, Int] 类型,所以r2 &lt;- ReaderT((_: Service1).s1f) 中的r2Int 类型。但是在您的第一个示例中,toReaderEnvFF((_: Env)._3) 的类型为ReaderEnvFF[Env =&gt; Cats] 又名ReaderT[FailFast, Env, Env =&gt; Cats],因此cats &lt;- toReaderEnvFF((_: Env)._3) 中的cats 的类型为Env =&gt; Cats。这就是区别。

    如果您想使用ReaderEnvFF[Cats],那么您应该更改cats &lt;- toReaderEnvFF(???)。例如

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

    【讨论】:

    • 但是我可以从依赖中得到猫吗?因为 Cats 是 Env 的一部分
    • @Alexandr 从哪里得到?如果你有ReaderEnvFF[Env](例如Kleisli#tap)你可以得到ReaderEnvFF[Cats](和Kleisli#map(..))。
    • 你知道,现在还不清楚。在r2 &lt;- ReaderT((_: Service1).s1f) 类型中r2 是Int,但在相同/相似的表达式中:cats &lt;- ReaderT((_:Env)._3)cats 是Env =&gt; Cats 类型。对我来说语法是一样的。我仍然看不出有什么不同。 ReaderT 的属性不能影响它吧?能否请您换句话解释一下。
    • @Alexandr (_: Service1).s1fService1 =&gt; Option[Int] 类型,所以ReaderT((_: Service1).s1f)ReaderT[Option,Service1,Int] 类型,所以r2 &lt;- ReaderT((_: Service1).s1f) 中的r2Int 类型。 (_:Env)._3Env =&gt; Cats 类型,所以ReaderT((_:Env)._3)ReaderT[Id,Env,Cats] 类型,所以cats &lt;- ReaderT((_:Env)._3) 中的catsCats 类型。
    • @Alexandr 这不是关于语法,而是关于类型。
    猜你喜欢
    • 1970-01-01
    • 2017-05-03
    • 2021-01-16
    • 2019-05-19
    • 1970-01-01
    • 2019-04-09
    • 2021-02-25
    • 2018-10-08
    • 1970-01-01
    相关资源
    最近更新 更多