简体   繁体   English

以理解单子构成的理解示例

[英]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. 更重要的是,您在这里将RightProjectionRightProjection组合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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM