¿Por qué una función polimórfica no puede aceptar tipos wildcard (existenciales) en Scala?
En el ejemplo siguiente, me pregunto por qué funPoly
no puede aceptar el valor de tipo cuantificado existencialmente outersFromInnersEx
, aunque funEx
puede.
case class InnerCassClass[I, E, O](i: I, e: E, o: O)
case class OuterCaseClass[I, E, O](inner: InnerCassClass[I, E, O])
val inner1 = InnerCassClass(5, "foo", 3.3f)
val inner2 = InnerCassClass(4.4f, 6, "bar")
// No funciona como se espera debido a la invariancia de los parámetros de tipo I, E, O (pero confirmar)
// val outersFromInnersAny: List[OuterCaseClass[Any, Any, Any]] = List(inner1, inner2).map(OuterCaseClass.apply)
val outersFromInnersEx: List[OuterCaseClass[_, _, _]] = List(inner1, inner2).map(OuterCaseClass.apply)
def funPoly[I, E, O](occ: List[OuterCaseClass[I, E, O]]): Unit = ()
def funEx(occ: List[OuterCaseClass[_, _, _]]): Unit = ()
// Esto no funciona, pero ¿por qué?
val u1 = funPoly(outersFromInnersEx)
val u2 = funEx(outersFromInnersEx)
Tenga en cuenta que esto se probó en Scala 3 (pruébalo en línea), pero en gran medida el problema es el mismo en Scala 2, aunque este ejemplo en particular tiene otros problemas en Scala 2.
davy.ai
La razón por la que
funPoly
no puede aceptar el valor de tipo existencialmente cuantificadooutersFromInnersEx
es porquefunPoly
tiene parámetros de tipoI
,E
yO
, los cuales requieren que se provean tipos concretos para cada parámetro. ComooutersFromInnersEx
tiene tipos comodín (_
) para cada parámetro, no coincide con los tipos concretos esperados parafunPoly
, y por lo tanto no puede ser aceptado como parámetro.Por otro lado,
funEx
no tiene parámetros de tipo, por lo que puede aceptar cualquier tipo deOuterCaseClass
, incluyendo aquellos con tipos comodín.Para que
funPoly
acepteoutersFromInnersEx
, necesitaríamos proveer tipos concretos paraI
,E
yO
. Por ejemplo, si sabemos queI
esFloat
,E
esString
yO
esDouble
, podríamos llamar afunPoly
de esta manera: