要回答標題問題:是的,第一個生成器「爲整個表達式設置心情」。請注意,像上面那樣的表達式是脫鉤轉換爲調用flatMap
s和最後map
(加上護士的withFilter
)。
在你的情況下,第一換表達脫糖入下式:
List(1, 2).flatMap(n => "ABC".map(c => s"$c$n"))
這可以工作,因爲Predef
(其在每Scala的程序隱式地導入)提供的一個的隱式轉換String
至Seq[Char]
。
val implicitlyConverted: Seq[Char] = "ABC"
因此,它按照計劃檢查運行。
現在讓我們來給看看在第二的表達式是如何脫:
List(None, Some(1), None, None, Some(2), None).flatMap(opt => opt.flatMap(n => "ABC".map(c => s"$c$n")))
再次,我們有相同類型的錯誤如上,如果我們打破錶達成幾行,我們可能會看到這個問題好一點點:
List(None, Some(1), None, None, Some(2), None).flatMap {
opt =>
opt.flatMap {
n =>
"ABC".map {
c =>
s"$c$n"
}
}
}
這爲我們提供了以下錯誤:
<console>:12: error: type mismatch;
found : scala.collection.immutable.IndexedSeq[String]
required: Option[?]
"ABC".map {
^
第二個flatMap
因此期望Option[_]
,而("ABC".map(...)
)中的map
返回IndexedSeq[String]
。
所以,這是原因。我們如何解決這個問題?最簡單的解決方案可能涉及使用保護和Option
內強行提取值,就像這樣:
for {
n <- List(None, Some(1), None, None, Some(2), None)
c <- "ABC" if n.isDefined
} yield s"$c${n.get}"
解決這個特定的問題更普遍的方式包括單子變壓器,因爲這個問題的根源在於單子做不寫;這個問題是非常廣泛和複雜的,也許this reply可能會給你一個更一般的答案。
在這種情況下是的,因爲第二個提取器就像一個'flatMap',所以你需要返回一個選項。 爲了清楚起見,您可以在第一種情況下通過隱式轉換提取「ABC」,以便事物成爲列表並編譯,在第二種情況下,「ABC」不會隱式轉換爲選項。 –