[英]What is and when to use Scala's forSome keyword?
List[T] forSome {type T}
和List[T forSome {type T}]
什么List[T forSome {type T}]
? 我如何用“英語”閱讀它們? 我應該如何神交 forSome
關鍵字? forSome
一些實際用途是forSome
? 什么是有用的實用和復雜的簡單T forSome {type T}
用法?
這里有很多問題,其中大部分已經在上面評論中鏈接的答案中得到了相當徹底的解決,所以我會回答你更具體的第一個問題。
List[T] forSome { type T }
和List[T forSome { type T }]
之間沒有真正有意義的區別,但我們可以看到以下兩種類型之間的區別:
class Foo[A]
type Outer = List[Foo[T]] forSome { type T }
type Inner = List[Foo[T] forSome { type T }]
我們可以將第一個讀作“ T
的foos列表,對於某些類型T
”。 整個列表中只有一個T
第二,在另一方面,可以理解為“FOOS的列表,其中每個foo是的T
一些T
”。
換句話說,如果我們有一個outer: Outer
列表outer: Outer
,我們可以說“存在一些類型T
,使得outer
是T
的foos列表”,其中對於Inner
類型的列表,我們只能說“對於列表的每個元素,存在一些T
,使得該元素是T
的foo”。 后者較弱 - 它告訴我們較少的清單。
因此,例如,如果我們有以下兩個列表:
val inner: Inner = List(new Foo[Char], new Foo[Int])
val outer: Outer = List(new Foo[Char], new Foo[Int])
第一個將編譯得很好 - 列表中的每個元素對於某些T
來說都是Foo[T]
。 第二個不會編譯,因為沒有一些T
這樣列表中的每個元素都是Foo[T]
。
注意:( 更新2016-12-08 )根據Martin Odersky關於ScalaX 2016的討論,forSome關鍵字很可能會與Scala 2.13或2.14一起消失。用路徑依賴類型或匿名類型屬性替換它( A[_]
)。 在大多數情況下這是可能的。 如果您的邊緣情況不可能,請重構您的代碼或放寬您的類型限制。
通常當您使用通用API時,API會保證您可以使用您提供的任何類型(最多一些給定的約束)。 因此,當您使用List[T]
,List API會保證它可以與您提供的任何類型T
使用 。
對於forSome
(所謂的存在量化類型參數),它是相反的。 API將提供一種類型(不是你),它保證你,它將使用它提供給你的這種類型。 語義是,具體對象會給你一些類型為T
東西。 同一個對象也會接受它為您提供的內容。 但沒有其他對象可以使用這些T
s,沒有其他對象可以為您提供T
類型的東西。
“存在量化”的概念是:存在(至少)一種類型T
(在實現中)以履行API的合同。 但我不會告訴你它是哪種類型。
forSome
可以讀取類似:對於某些類型的T
的API合同成立。 但對於所有類型的T
都不一定如此。 因此,當您提供某種類型的T
(而不是在API的實現中隱藏的類型)時,編譯器無法保證您獲得了正確的T
所以它會拋出一個類型錯誤。
因此,當您在API中看到List[T] forSome {type T}
時,您可以這樣閱讀:API將為您提供一些未知類型T
的List
。 它很樂意接受這個列表,它將與它一起使用。 但它不會告訴你, T
是什么。 但至少你知道,列表中的所有元素都是相同的類型T
第二個有點棘手。 API再次為您提供一個List
。 它會使用某種類型的T
而不是告訴你T
是什么。 但是可以自由地為每個元素選擇不同的類型。 真實世界的API會為T
建立一些約束,因此它實際上可以使用列表的元素。
當您編寫API時, forSome
很有用,其中每個對象代表API的實現。 每個實現都將為您提供一些對象,並將接受這些對象。 但是你既不能混合不同實現的對象,也不能自己創建對象。 相反,您必須始終使用相應的API函數來獲取可與該API一起使用的一些對象。 forSome
可以實現非常嚴格的封裝。 您可以閱讀forSome
通過以下方式:
對於某些類型,API合約折疊為true。 但你不知道它適用於哪種類型。 因此,您無法提供自己的類型,也無法創建自己的對象。 您必須使用通過使用
forSome
的API提供的那些。
這非常非正式,在某些極端情況下甚至可能是錯誤的。 但它應該幫助你理解這個概念。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.