返回子类时,EitherT抛出编译错误

时间:2018-03-25 22:01:58

标签: scala scala-cats

在下面的代码中我使用了猫'EitherT类。它编译,但我被迫使用Error特征:

def isNeg(i:Int): Future[Either[Error,Int]] = Future {

我的意图是将函数声明为:

def isNeg(i:Int): Future[Either[IsPositive,Int]] = Future {

但是如果我使用IsPositive(函数的Left中返回的类),Scala会抛出编译错误。为什么不用IsPositive编译?

import cats.data.EitherT
import cats.implicits._

trait Error
case class IsNegative() extends Error
case class IsPositive() extends Error

object HelloScala extends App {

    def isPos(i:Int): Future[Either[IsNegative,Int]] = Future {
      if (i>0)
          Right(i)
      else
          Left(IsNegative())
    }

    def isNeg(i:Int): Future[Either[Error,Int]] = Future {
      if (i<0)
          Right(i)
      else
          Left(IsPositive())
    }

    def myFunction (i: Int) = {
       val result = for {
          ret <- EitherT(isPos(i)) // <-- compilation error, if IsPositive is used in isNeg
          ret2 <- EitherT(isNeg(ret))
       } yield ret2
       println(result.value)
    }

}

1 个答案:

答案 0 :(得分:2)

yield如何运作?它被翻译为flatMap(见here)。因此,让我们尝试使用flatMap重写您的案例,并使用非可编译版本的显式类型:

val eithert1: EitherT[Future, IsNegative, Int] = EitherT(isPos(i))
def eithert2(ret: Int): EitherT[Future, IsPositive, Int] = EitherT(isNeg(ret))
eithert1.flatMap(ret => eithert2(ret)).map(ret2 => ret2)

现在你有什么类型:

// What is expected (see `EitherT` type bounds in sources, I copied here)
// flatMap -> EitherT[F[_], A, B].flatMap[AA >: A, D](f: B => EitherT[F, AA, D])
// what you have:
// EitherT[Future, IsNegative, Int].flatMap[IsPositive >: IsNegative, Int](f: Int => EitherT[Future, IsPositive, Int])

你看:IsPositive >: IsNegative,这是错误的。 IsNegative的预期超类型(ErrorIsNegative