Quiero definir una clase Functor en Java. Esto funciona:Genéricos de Java: cómo codificar una interfaz de Functor en Java?
//a Function
public interface F<A,R> {
public R apply(A a);
}
public interface Functor<A> {
public <B> Functor<B> fmap(F<A,B> f);
}
Sin embargo, el valor de retorno de fmap no debería haber Functor
, pero la subclase apropiada. Por lo general, esto se puede codificar con el CRTP, pero aquí parece que toco una pared debido al parámetro adicional A
. P.ej. los siguientes y similares codificaciones no funcionan ("parámetro de tipo finst no está dentro de sus límites"):
public interface Functor<A, FInst extends Functor<A,FInst>> {
public <B, I extends Functor<B,FInst>> I fmap(F<A,B> f);
}
[Aclaración]
Con "subclase apropiada" I significa que el tipo de la clase siendo llamado a sí mismo. P.ej. Las listas son funtores, por lo que me gustaría escribir algo como
public class ListFunctor<A> implements ??? {
final private List<A> list;
public ListFunctor(List<A> list) {
this.list = list;
}
@Override
<B> ListFunctor<B> fmap(F<A,B> f) {
List<B> result = new ArrayList<B>();
for(A a: list) result.add(f.apply(a));
return new ListFunctor<B>(result);
}
}
Soy consciente de que podría escribir esto incluso con la primera definición que di (porque los tipos de retorno covariantes están permitidos), pero yo quiero que el retorno tipo "ListFunctor" es cumplir por el sistema de tipos (por lo que no puedo devolver un FooFunctor en su lugar), lo que significa que la interfaz Functor tiene que devolver el "tipo de auto" (al menos por lo que se le llama en otros idiomas)
[Resultados]
por lo que parece lo que quiero es imposible. Aquí es un relacionado el blog post: http://blog.tmorris.net/higher-order-polymorphism-for-pseudo-java/
Probablemente es una mala forma tener más de 3 parámetros de tipo, especialmente los que incluyen al otro, ya que la declaración se convierte en un gran desastre y nadie sabe qué está pasando. –
Existe una diferencia con respecto al lado del "escritor de la biblioteca" y el lado del uso. Y a menudo puede "ocultar" genéricos, incluso con la inferencia de tipo limitada de Java (por ejemplo, mediante el uso de métodos estáticos). – Landei