2011-09-21 43 views
10

我很可能錯過了文檔中正確的東西,但我無法真正理解它 - 我一直在通過試驗和錯誤教自己Scala。處理選項和任一種類型 - 慣用轉換?

鑑於功能f: A => C慣用方式執行以下轉換?

Either[A, B] -> Either[C, B]

Either[B, A] -> Either[B, C]

(如果我有兩個這樣的功能,並希望雙方轉換,我可以做一次全部或者,我應該使用成語連續兩次?)

Option[A] -> Option[C]

(我覺得這應該用for (...) yield莫名其妙;我可能只是空白,當我看到答案時會感到無聊)

什麼究竟是Either的「投影」,無論如何?

+1

從下面的評論看來,你似乎混淆了''或'與'Pair','Tuple2'。情況並非如此:「任一」只能包含_one_值。從某種意義上說,它與C中的'union'類似,除了你知道哪個成員實際存儲了。 –

+0

我意識到了這一點,但我仍然感到困惑,一個預測被投入混合。我沒有清楚地表達這一點。 –

回答

18

你做任何一個:

either.left.map(f) 

或:

either.right.map(f) 

你也可以使用一個換理解:for (x <- either.left) yield f(x)

這裏做的一個關於map的更具體的例子一個Either[Boolean, Int]

scala> val either: Either[Boolean, Int] = Right(5) 
either: Either[Boolean, Int] = Right(5) 

scala> val e2 = either.right.map(_ > 0) 
either: Either[Boolean, Boolean] = Right(true) 

scala> e2.left.map(!_) 
either: Either[Boolean, Boolean] = Right(true) 

編輯:

它是如何工作的?假設你有一個Either[A, B]。調用leftright會創建一個LeftProjectionRightProjection對象,該對象是包含Either[A, B]對象的包裝器。

對於left包裝,隨後map與函數f: A => C應用於變換Either[A, B]Either[C, B]。它通過使用引擎蓋下的模式匹配來檢查Either實際上是否爲Left。如果是,則創建一個新的Left[C, B]。如果不是這樣,它只是改變創建一個新的Right[C, B]具有相同的基礎價值。

反之亦然right包裝。實際上,說either.right.map(f)意味着 - 如果任一(Either[A, B])對象擁有Right值,則映射它。否則,請保持原樣,但改變任一對象的B類型,就好像您已經映射它一樣。

從技術上講,這些預測僅僅是包裝。在語義上,它們是一種說法,假設存儲在Either對象中的值是LeftRight。如果這種假設是錯誤的,映射不做任何事情,但類型參數會相應地改變。

+0

請分解這對我來說如何工作?與預測有什麼關係?很明顯,'.left'和'.right'在其他語言中並不像庫中的「pair」類型,它們只會分別訪問[A]和[B]類型的成員。 –

+0

你可能會看看這個問題:http://stackoverflow.com/q/7131076/754787 –

+0

我已經編輯了答案來解釋一下引擎蓋下發生的一些事情。但是,要麼不是一對,要麼是元組類型,也稱爲交集類型 - 「A x B」。它擁有類型[A]或[B] - 'A V B'的成員。這意味着你不能安全地訪問任何成員,就像你可以在一個元組中一樣,因爲只有一個成員存在。 – axel22

3

鑑於f: A=>BxOpt: Option[A],xOpt map f產生您需要的Option[B]

鑑於f: A=>BxOrY: Either[A, C],xOrY.left.map(f)產生您正在尋找的Either,映射只是第一個組件;同樣你可以處理EitherRightProjection

如果您有兩個功能,您可以爲兩個組件定義映射,xOrY.fold(f, g)

0
val e1:Either[String, Long] = Right(1) 
val e2:Either[Int,Boolean] = e1.left.map(_.size).right.map(_ >1) 
// e2: Either[Int,Boolean] = Right(false) 
相關問題