Parámetros de tipo genérico de order superior (¿o recursivo?) En kotlin

Estoy creando prototypes de un código altamente declarativo, y la inferencia de tipo y la security que acompaña a Kotlin son de gran ayuda. Uno de los objectives es hacer que las extensiones (subclasss) de los types primarios sean estúpidamente fáciles de implementar. Para mantener la inferencia y la expresividad de types abundantes, he encontrado cierto éxito en la definición de funciones de extensión genéricas proyectadas contra subclasss. Toda la información de types de subclasss sin ninguna implementación de subclass adicional, es genial.

Así que estoy tratando de escribir una function genérica rica que mantenga tanta información de tipo como sea posible. El problema se arrastra con el hecho de que esta function opera en types generics potencialmente recursivos, y quiero mezclar los parameters generics de tipo.

Esto sería imposible de describir sin un ejemplo. Así que considere:

open class G<in T> class A<in T> : G<T>() class B<in T> : G<T>() class C<in T> : G<T>() val ba = B<A<*>>() val cb = C<B<*>>() 

Queremos una function que efectivamente pueda hacer esto, excepto genéricamente

 fun B<A<*>>.doTransitiveThing(c: C<B<*>>) : C<A<*>> { // implement } val ca = ba.doTransitiveThing(cb) // Returns C<A<*>> 

Criterio de objective:

  • Toma C como parámetro y devuelve C , excepto con un parámetro de tipo genérico diferente
  • Me gustaría generalizar este comportamiento como una function de extensión de todas las subclasss de G
    • Tiene que ser una function de extensión para que al usar types generics podamos tener el tipo de la subclass y asegurar que el argumento tenga un argumento de tipo genérico del tipo de receptor.
    • O en otras palabras, queremos una function de extensión para subclasss de G por lo que el argumento debe ser C<B<*>> lugar de C<G<*>> cuando se invoca en B<A<*>>

Eso describe la esencia del problema. No estoy seguro de que el lenguaje sea capaz de soportar lo que quiero. No estoy seguro de si el borrado de tipo es un factor que hace que esto sea imposible, pero hasta ahora no puedo encontrarlo (tal vez podría usar ayuda si es así).


Lo siguiente está cerca

 fun < TargetGenericType, Arg1Type: G<*>, ReceiverType: G<TargetGenericType>, Arg2Type: G<Arg1Type>, ResultType: G<TargetGenericType> > ReceiverType.doTransitiveThingGeneric(x: Arg2Type): ResultType { //implement } val ca2 = ba.doTransitiveThingGeneric(cb) 

Pero hay algunos problemas

  • Devuelve G<A<*>> lugar de C<A<*>> . Sería bueno si pudiera devolver C y no perder información de tipo (de lo contrario, de todos modos, en realidad no tengo ningún uso para esta function)
  • Técnicamente, no hay garantía de que ReceiverType sea Arg1Type

Pensando en el futuro, si algo como lo siguiente fuera válido para Kotlin, creo que abordaría mi problema

 fun < TargetGenericType, ReceiverBaseType<T>: G<T>, typealias ReceiverType = ReceiverBaseType<TargetGenericType>, ParamBaseType<U>: G<U>, typealias ParamType = ParamBaseType<ReceiverBaseType<*>>, ResultType: ParamBaseType<TargetGenericType> > ReceiverType.doTransitiveThingHigherOrderGeneric(x: ParamType): ResultType { //implement } 

¿Hay alguna razón por la que no se puede hacer? por ejemplo, se agregó como una function en el idioma? Soy comprensivo con los motivos logísticos en contra, pero tengo curiosidad si es incluso posible en principio también.

Últimas notas:

  • Me restring los alias de tipo excepto los parameters de tipo genérico. De hecho, he incluido esa palabra key en el ejemplo en caso de que ayude a digerir. Sin embargo, esa no es la única parte, observe <T> y <U> en la syntax.
  • Casi me restring a las Mónadas también, excepto con las definiciones de las classs en sí mismas si eso tiene sentido en una especie de manera ondulada, intuitiva.
  • Aún no tengo idea de cómo implementar el cuerpo, pero no he llegado tan lejos ya que aún estoy tratando de ver si la firma es posible: p