如果你的意思是你想要Either[Boolean, Int]
而不是Either[Any, Int]
,那么“你不能总是得到你想要的东西”。相同的(如你的例子)Either
类型(但一些其他值)的组成即使对于右投影返回String
代替Boolean
:
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)
所以,Either[Any,Int]
真的是正确的,并尽可能终端类型,它更小。
脱糖版本:
scala> x.right.flatMap(xx => r.right.map(_ + xx))
res27: scala.util.Either[Any,Int] = Left(aaa)
单子的flatMap
签名:
flatMap[AA >: A, Y](f: (B) ⇒ Either[AA, Y]): Either[AA, Y]
传递类型:
flatMap[Any >: String, Int](f: (Int) ⇒ Either[?Boolean?, Int]): Either[Any, String]
AA >: A
是完全合法的,在这里,因为它允许f = r.right.map(_ + xx)
返回左型比大String
(so ?Boolean?
变成Any
),否则它甚至不能工作。回答你的问题,flatMap
这里不能有AA = Boolean
,因为A
已经至少String
,并且如第一个例子所示,实际上可以是String
。
而顺便说一下,在这个例子中没有monads构成 - r
可能只是一个仿函数。更重要的是,你在这里撰写RightProjection
和RightProjection
,所以他们自动通勤。
到inferr Boolean
的唯一方法是杀死String
型与Nothing
- 你可以做的,只有当你确定x
总是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)
然后,当然你不能把字符串,这是完全正确的。