usted no entiende Int with String
. No es la Unión de Int y String, es la intersección, y para Int y String está vacía. No son los conjuntos de valores que son Int con el conjunto de valores que son cadenas, sino el conjunto de valores que tienen las características de Int con las características de Cadena también. No hay tales valores.
Puede usar Either[Int, String]
y tener Map[Left(1) -> 2, Right("Hello") -> 3)
. O bien no es exactamente la Unión, es la unión discriminada, A + B, en lugar de A U B. Puede captar la diferencia en que O bien [Int, Int] no es lo mismo que Int. De hecho, es isomorfo a (Int, Boolean): tienes un Int, y sabes de qué lado está. Cuando A y B son disjuntos (como son Int y String) A + B y A U B son isomorfos.
O (no apto para cardíacos) puede echar un vistazo a a possible encoding of union types de Miles Sabin. (No estoy seguro de que puedas usar eso con un mapa de clase preexistente, y aún menos seguro de lo que deberías intentar, pero de todos modos es una lectura muy interesante).
Editar: Lea la pregunta y forma de código demasiado rápido, lo siento
Su límite inferior Int with String
es lo mismo que Nothing
, por lo Map[_ >: Int with String, Int]
, es el mismo que Map[_ >: Nothing, Int]
y como el Nothing
límite inferior es implicado, esto es Map[_, Int]
. Su actual Map
es un Map[Any, Int]
. Podría haber agregado una clave booleana, también funciona, a pesar del Int con String. Un Map[Any, Int]
se puede escribir como Map[_, Int]
para que su declaración de validación funcione. Pero su mecanografía pierde toda la información sobre el tipo de clave.Sin saber cuál es el tipo de clave, no puede agregar (ni recuperar) nada de la tabla.
Un UpperBound no hubiera sido mejor, ya que entonces no hay una clave posible. Incluso la declaración val inicial falla.
Editar 2: En cuanto a if (true) Map(1 -> 2) else Map("1" -> 2)
Esto no es lo mismo que Map(1 -> 2, "1" -> 2)
. Eso era más simple, simplemente un Map[Any, Int]
, como Any
es el mayor supertipo común de Int
y String
.
Por otro lado, Map(1 -> 2)
es Map[Int, Int]
, y Map["1", 2]
a Map[String, Int]
. Existe el problema de encontrar un supertipo común para Map[Int, Int]
y Map[String, Int]
, que no encuentra un supertipo común de Int
y String
.
Vamos a experimentar. Map
es covariante en su segundo parámetro. Si utiliza Int
y String
como valores en lugar de teclas:
if (true) Map(1 -> 2) else Map(1 -> "2")
res1: scala.collection.immutable.Map[Int, Any]
Con covarianza, simplemente toma el supertipo común de todos los parámetros de tipo.
Con un tipo contravariant:
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]
que toma la intersección A with C.
Cuando B
es un subtipo de A
, A
con B
es sólo B
.
Ahora, con el parámetro de no variante de Mapa cuando los dos tipos están relacionados
if (true) Map(new A -> 1) else Map(new B -> 1)
res4: scala.collection.immutable.Map[_ >: B <: A, Int]
Tal tipo no es inútil. Puede acceder o agregar valores con las claves del tipo B
. Pero no puede acceder a los valores de las claves A
. Como esto es lo que tienes en el mapa real (debido al true
), mala suerte. Si accede al keySet
, se tecleará Set[A]
. Tiene información incompleta sobre el tipo de claves, y lo que puede hacer es limitado, pero esta es una limitación necesaria, dado el conocimiento limitado que tiene sobre el tipo de mapa. Con Int and String
, tiene información mínima, con un límite inferior Any
y un límite superior equivalente a Nothing
. El límite superior Nothing no permite llamar a una rutina que toma una tecla como parámetro. Todavía puede recuperar el keySet
, con el tipo Set[Any]
, Any
siendo el límite inferior.
No creo que este sea el problema - 'Int with String' está sujeto al tipo de clave, no al tipo en sí. Puedo usarlo como un límite en muchas otras situaciones. – Submonoid
Por cierto, la codificación de los tipos de unión es increíble, pero no es especialmente relevante para la pregunta; en particular, me interesa saber por qué la asignación es válida pero si intenta agregar algo más, falla. – Submonoid
Creo que es un límite completamente inútil, ver complemento para responder. –