[英]For Comprehension Example to Understand Composing Monads
J. Abrahamson provided an in-depth answer to my composing-monads-v-applicative-functors question. J.亚伯拉罕森(J. Abrahamson)对我的“ monads-v-applicative-functors”问题作了深入解答。
I gained some intuition, but I do not fully understand his helpful answer. 我获得了一些直觉,但我不完全理解他的有益回答。
Given the following Either
's: 鉴于以下Either
:
scala> x
res0: Either[String,Int] = Right(100)
scala> err
res1: Either[Boolean,Int] = Left(false)
I tried to chain them together: 我试图将它们链接在一起:
scala> for {
| xx <- x.right
| yy <- err.right
| } yield xx + yy
res3: scala.util.Either[Any,Int] = Left(false)
But, of course I don't want an Either[Any, Int]
. 但是,我当然不想要Either[Any, Int]
。 Yet we get Any
since, as I understand, the parent of Either[String, Int]
and Either[Boolean, Int]
is Either[Any, Int]
. 但是我们得到Any
,因为据我了解, Either[String, Int]
和Either[Boolean, Int]
的父代是Either[Any, Int]
。
When building a for-comprehension, is the typical approach to find an end-type, ie Either[String, Int]
, and then make each flatMap
call have that type? 在构建理解时,通常的方法是找到结束类型,即Either[String, Int]
,然后使每个flatMap
调用具有该类型吗?
If you mean that you want Either[Boolean, Int]
instead of Either[Any, Int]
, then "You can't always get what you want". 如果您是说要Either[Boolean, Int]
而不是Either[Any, Int]
,则“您不能总是得到想要的”。 Composition of same (as in your example) Either
types (but some other values) may return String
instead of Boolean
even for right projection: 组成相同(如您的示例中所示)的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)
So, Either[Any,Int]
is really correct and smaller as possible end-type for it. 因此, Either[Any,Int]
确实是正确的,并且它的终端类型尽可能小。
The desugared version: 简化后的版本:
scala> x.right.flatMap(xx => r.right.map(_ + xx))
res27: scala.util.Either[Any,Int] = Left(aaa)
Monad's flatMap
signature: Monad的flatMap
签名:
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. AA >: A
在这里是完全合法的,因为它允许f = r.right.map(_ + xx)
返回大于String
left类型(因此, ?Boolean?
变成Any
),否则它甚至无法工作。 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
. 在回答您的问题时,这里的flatMap
不能具有AA = Boolean
,因为A
已经至少是String
,并且如第一个示例所示,实际上可以是String
。
And, by the way, there is no monads composition in this example - r
could be just a functor. 而且,顺便说一句,在此示例中没有monad组成r
可能只是一个函子。 More than that, you're composing RightProjection
with RightProjection
here, so they commute automatically. 更重要的是,您在这里将RightProjection
与RightProjection
组合RightProjection
,以便它们自动进行通勤。
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
: 推断Boolean
的唯一方法是使用Nothing
杀死String
类型-仅在确保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)
Then, of course you can't put strings, which is totally correct. 然后,您当然不能放字符串,这是完全正确的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.