es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

¿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.

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    La razón por la que funPoly no puede aceptar el valor de tipo existencialmente cuantificado outersFromInnersEx es porque funPoly tiene parámetros de tipo I, E y O, los cuales requieren que se provean tipos concretos para cada parámetro. Como outersFromInnersEx tiene tipos comodín (_) para cada parámetro, no coincide con los tipos concretos esperados para funPoly, 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 de OuterCaseClass, incluyendo aquellos con tipos comodín.

    Para que funPoly acepte outersFromInnersEx, necesitaríamos proveer tipos concretos para I, E y O. Por ejemplo, si sabemos que I es Float, E es String y O es Double, podríamos llamar a funPoly de esta manera:

    val u1 = funPoly[Float, String, Double](outersFromInnersEx)
    

Comments are closed.