No tengo la respuesta 100% completa, pero tengo un puntero que podría ser suficiente para ti.
El compilador Scala trata los GADT (tipos de datos algebraicos generalizados) de una manera muy particular. Algunos casos se resuelven con un manejo especial, algunos casos no se resuelven. Dotty está tratando de llenar la mayoría de los agujeros, y ya ha resuelto muchos problemas relacionados, sin embargo, todavía hay bastantes abiertos .
El ejemplo típico de manejo especial de GADT en el compilador Scala 2 está muy relacionado con su caso de uso. Si echamos un vistazo a:
def method[A](arg: Base[A]) = {
arg match {
case Derived(_) => 42
}
}
y declaramos explícitamente que el tipo de retorno es A
:
def method[A](arg: Base[A]): A
se compilará muy bien. Su IDE puede quejarse, pero el compilador lo dejará pasar. El método dice que devuelve un A
, pero el caso de coincidencia de patrón se evalúa en un Int
, que en teoría no debería compilarse. Sin embargo, el manejo especial de los GADT en el compilador dice que está bien, porque en esa rama de coincidencia de patrones en particular A
se ha "arreglado" para que sea un Int
(porque coincidimos en Derived
cuál es un Base[Int]
).
El parámetro de tipo genérico para GADT (en nuestro caso A
) debe declararse en alguna parte. Y aquí está la parte interesante: el manejo especial del compilador solo funciona cuando se declara como parámetro de tipo del método de inclusión . Si proviene de un miembro de tipo o un parámetro de tipo del rasgo / clase adjunto, no se compila, como lo observó usted mismo.
Es por eso que dije que no es una respuesta 100% completa: no puedo señalar un lugar concreto (como las especificaciones oficiales) que documente esto correctamente. Fuentes en el manejo de GADTs en Scala descendido a un par de entradas del blog , que son grandes por cierto, pero si quieres más de que va a tener que excavar en el código de compilador de sí mismo. Intenté hacer exactamente eso, y creo que todo se reduce a este método , pero si realmente quieres profundizar, es posible que quieras hacer ping a alguien más experimentado con la base de código del compilador Scala.