If you mean that you want Either[Boolean, Int] instead of Either[Any, Int], then "You can't always get what you want". Composition of same (as in your example) Either types (but some other values) may return String instead of Boolean even for right projection:
scala> val x: Either[String,Int] = Left("aaa")
x: Either[String,Int] = Left(aaa)
scala> val r: Either[Boolean,Int] = Right(100)
r: Either[Boolean,Int] = Right(100)
scala> for {
| xx <- x.right
| yy <- r.right //you may swap xx and yy - it doesn't matter for this example, which means that flatMap could be called on any of it
| } yield yy + xx
res21: scala.util.Either[Any,Int] = Left(aaa)
So, Either[Any,Int] is really correct and smaller as possible end-type for it.
The desugared version:
scala> x.right.flatMap(xx => r.right.map(_ + xx))
res27: scala.util.Either[Any,Int] = Left(aaa)
Monad's flatMap signature:
flatMap[AA >: A, Y](f: (B) ⇒ Either[AA, Y]): Either[AA, Y]
Passed types:
flatMap[Any >: String, Int](f: (Int) ⇒ Either[?Boolean?, Int]): Either[Any, String]
AA >: A is completely legal here as it allows f = r.right.map(_ + xx) return left type bigger than String (so ?Boolean? becomes Any), otherwise it wouldn't even work. Answering your question, flatMap can't have AA = Boolean here, because A is already at least String, and as shown in first example can actually be a String.
And, by the way, there is no monads composition in this example - r could be just a functor. More than that, you're composing RightProjection with RightProjection here, so they commute automatically.
The only way to inferr Boolean is to kill String type with Nothing - you can do that only if you sure that x is always Right:
scala> val x: Either[Nothing,Int] = Right(100)
x: Either[Nothing,Int] = Right(100)
scala> val r: Either[Boolean,Int] = Left(false)
r: Either[Boolean,Int] = Left(false)
scala> for {
| yy <- r.right
| xx <- x.right
|
| } yield yy + xx
res24: scala.util.Either[Boolean,Int] = Left(false)
Then, of course you can't put strings, which is totally correct.