Home > Enterprise >  Why can't a polymorphic function accept wildcard (existential) types in Scala?
Why can't a polymorphic function accept wildcard (existential) types in Scala?

Time:12-02

In the example below, I'm wondering why funPoly can't accept the existentially quantified type value outersFromInnersEx, even though funEx can.

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")


// Doesn't work as expected due to invariance of type paramemters I, E, O (but confirm)
// 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 = ()


// This doesn't work, but why?
val u1 = funPoly(outersFromInnersEx)

val u2 = funEx(outersFromInnersEx)

Note, I test this in Scala 3 (try online), but largely the problem is the same in Scala 2, though this particular example has other issues in Scala 2.

CodePudding user response:

It about type variances, you can make funPoly works by change

case class InnerCassClass[I, E, O](i: I, e: E, o: O)
case class OuterCaseClass[I, E, O](inner: InnerCassClass[I, E, O])

to

case class InnerCassClass[ I,  E,  O](i: I, e: E, o: O)
case class OuterCaseClass[ I,  E,  O](inner: InnerCassClass[I, E, O])
  • Related