你誤會Int with String
。它不是Int和String的聯合,它是交集,而Int和String則是空的。不是以字符串值爲集合的Int值集合,而是以String爲特徵的具有Int特性的值集合。沒有這樣的價值。您可以使用Either[Int, String]
,並有Map[Left(1) -> 2, Right("Hello") -> 3)
。要麼是不完全是聯盟,而是歧視的聯盟,A + B,而不是A/B。你可以把握區別在於[Int,Int]與Int不同。它實際上與(Int,布爾)同構:你有一個Int,並且你知道它是哪一邊。當A和B不相交時(如Int和String所示)A + B和A U B是同構的。
或者(不是因爲心疼)你可以看看Miles Sabin的a possible encoding of union types。 (我不確定你是否可以在預先存在的Map Map中使用它,甚至不如你應該嘗試的那樣確定,但它仍然是最有意思的閱讀方式)。
編輯:看了你的問題和代碼太快了,對不起
你下界Int with String
相同Nothing
,所以Map[_ >: Int with String, Int]
,相同Map[_ >: Nothing, Int]
並作爲Nothing
下界暗示,這是Map[_, Int]
。您的實際Map
是Map[Any, Int]
。你可以添加一個布爾鍵,它也可以工作,儘管用字符串Int。 A Map[Any, Int]
可以輸入爲Map[_, Int]
,以便您的val聲明有效。但是你的輸入會丟失關於密鑰類型的所有信息。不知道鍵的類型是什麼,你不能從表中添加(也不能檢索)任何東西。
的上界就沒有更好的,因爲那麼有沒有可能的密鑰。即使最初的val聲明也失敗了。
編輯2:關於if (true) Map(1 -> 2) else Map("1" -> 2)
這是不一樣的東西Map(1 -> 2, "1" -> 2)
。這是簡單的,只是一個Map[Any, Int]
,爲Any
是Int
和String
更大的公用超類型。
另一方面,Map(1 -> 2)
是Map[Int, Int]
和Map["1", 2]
a Map[String, Int]
。沒有發現用於Map[Int, Int]
和Map[String, Int]
一個共同的超類型,這是沒有找到的Int
和String
一個共同的超類型的問題。
讓我們的實驗。 Map
在其第二個參數中是協變的。如果您使用Int
和String
的值,而不是鍵:
if (true) Map(1 -> 2) else Map(1 -> "2")
res1: scala.collection.immutable.Map[Int, Any]
協方差,它只是通吃類型參數的公用超類型。
隨着逆變類型:
class L[-T]
object L{def apply[T](t: T) = new L[T])
class A
class B extends A
class C
if (true) L(new A) else L(new C)
res2: L[A with C]
if (true) L(new A) else L(new B)
res3: L[B]
花費的交點A with C.
當B
是A
一個亞型,A
與B
只是B
。
現在,隨着地圖的非變量參數,當兩種類型都與
if (true) Map(new A -> 1) else Map(new B -> 1)
res4: scala.collection.immutable.Map[_ >: B <: A, Int]
這種類型也不是一無是處。您可以使用B
類型的密鑰訪問或添加值。但是您無法訪問密鑰A
的值。由於這是你在實際地圖中的(因爲true
),所以很難運氣。如果您訪問keySet
,將會輸入Set[A]
。您對密鑰類型的信息不完整,您可以執行的操作有限,但由於您對地圖類型的知識有限,因此這是一個必要的限制。使用Int and String
,您獲得的信息極少,下限爲Any
,上限爲Nothing
。 Nothing上限使得不可能調用以鍵爲參數的例程。您仍然可以檢索keySet
,類型爲Set[Any]
,Any
爲下限。
我不認爲這是問題 - '詮釋與String'是關鍵,而不是類型本身的類型束縛。我可以在很多其他情況下使用它作爲綁定。 – Submonoid 2012-01-06 12:36:29
順便說一下,聯合類型的編碼非常棒,但與問題無關 - 特別是,我對賦值爲什麼有效但試圖添加其他任何失敗感興趣。 – Submonoid 2012-01-06 12:46:58
我認爲這是一個完全無用的界限,請參閱補充來回答。 – 2012-01-06 13:49:48