代码之家  ›  专栏  ›  技术社区  ›  ps0604

Either在返回子类时引发编译错误

  •  0
  • ps0604  · 技术社区  · 7 年前

    在下面的代码中,我使用的是“猫” 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 回复  |  直到 7 年前
        1
  •  2
  •   Evgeny    7 年前

    如何 yield 作品它被转换为 flatMap (参见 here )。那么,让我们试着用 平面图 对于不可编译版本,使用显式类型:

    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 (或者 Error Is阴性 )