簡體   English   中英

以理解單子構成的理解示例

[英]For Comprehension Example to Understand Composing Monads

J.亞伯拉罕森(J. Abrahamson)對我的“ monads-v-applicative-functors”問題作了深入解答。

我獲得了一些直覺,但我不完全理解他的有益回答。

鑒於以下Either

scala> x
res0: Either[String,Int] = Right(100)

scala> err
res1: Either[Boolean,Int] = Left(false)

我試圖將它們鏈接在一起:

scala> for {
     |   xx <- x.right
     |   yy <- err.right
     | } yield xx + yy
res3: scala.util.Either[Any,Int] = Left(false)

但是,我當然不想要Either[Any, Int] 但是我們得到Any ,因為據我了解, Either[String, Int]Either[Boolean, Int]的父代是Either[Any, Int]

在構建理解時,通常的方法是找到結束類型,即Either[String, Int] ,然后使每個flatMap調用具有該類型嗎?

如果您是說要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)

Monad的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 left類型(因此, ?Boolean?變成Any ),否則它甚至無法工作。 在回答您的問題時,這里的flatMap不能具有AA = Boolean ,因為A已經至少是String ,並且如第一個示例所示,實際上可以是String

而且,順便說一句,在此示例中沒有monad組成r可能只是一個函子。 更重要的是,您在這里將RightProjectionRightProjection組合RightProjection ,以便它們自動進行通勤。

推斷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)

然后,您當然不能放字符串,這是完全正確的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM