2009-11-25 135 views
2

的問題是,你要flatMap一個List[Option[T]]List[T]類型推斷:如果在使用隱式類型轉換的通用方法

val l = List(Some("Hello"), None, Some("World")) 

獲得:

List(Hello, World) 

但目前還沒有很好的解決方案:

l flatMap(o => o) 
l flatMap identity[Option[String]] 
l flatMap (x => Option.option2Iterable(identity(x))) 
for(x <- l; y <- x) yield y 

使用身份函數d OES不行的,因爲從Option[T]Iterable[T]一個需要的類型轉換:

l flatMap identity 

<console>:6: error: type mismatch; 
found : A 
required: Iterable[?] 
     l flatMap identity 

有沒有解決這個問題的方法嗎?

問題的一部分是爲什麼類型推理器在需要隱式類型轉換時工作不同?

(這個問題上來,當討論this question about the identity function。)

回答

2

有與沒有問題隱式的。如果是列表清單,則無法將identity更改爲mapflatMap。我們來討論map而不是flatMap,因爲它更簡單,所以我可以更好地解釋我認爲正在發生的事情。

identity的類型是(A) => Amap的類型,如果(A) => B,其中A是已知的,因爲它是對象的類型參數(即在List[String]中,它是String)。 identityAmapB都是已知的。

現在,如果我們使用map的類型的左側推斷的identity左側,然後我們可以使用的identity右側推斷map右側。看到一個循環? map的類型爲identity的類型爲map的類型。我很確定類型推理器避免了循環,否則它可能會陷入無限循環。

事實上,人們可以在Odersky等人的Programming in Scala的第355頁看到類型推理器的細節。在方法的應用m(arg),它執行以下操作步驟:

  1. 它檢查是否方法mmap,在我們的例子)有一個已知的類型(不,我們不知道B)。
  2. 它檢查參數arg(在我們的例子中爲identity)是否有已知類型(不,我們不知道A)。
  3. 它救了。

所以,你必須提供一種類型。例如:

l.flatMap[String](identity) 
l.flatten[String] 

在Scala的2.8類型inferencer是一點點聰明,沒有明確地傳遞的類型可以處理第二命令。

2

Option延長Iterable特徵;我不知道他們爲什麼這樣做擺在首位...

注意,例如不與階類型提示工作2.8之一:

scala> val l = List(Some("Hello"), None, Some("World")) 
l: List[Option[java.lang.String]] = List(Some(Hello), None, Some(World)) 

scala> l.flatMap(identity) : List[String] 
<console>:6: error: type mismatch; 
found : A 
required: Traversable[?] 
    l.flatMap(identity) : List[String] 
+0

'l.flatMap(identity):List [String]'在2.7中也不起作用。 '錯誤:類型不匹配;找到:A required:Iterable [String] l.flatMap(identity):List [String]' – 2009-11-26 08:30:43