I want to define a Functor class in Java. This works:
//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);
}
However the return value of fmap should be not Functor
, but the appropriate subclass. Usually this can be encoded with the CRTP, but here I seem to hit a wall because of the additional parameter A
. E.g. the following and similar encodings don't work ("type parameter FInst is not within its bounds"):
public interface Functor<A, FInst extends Functor<A,FInst>> {
public <B, I extends Functor<B,FInst>> I fmap(F<A,B> f);
}
[Clarification]
With "appropriate subclass" I mean the type of the class being called itself. E.g. Lists are functors, so I would like to write something like
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);
}
}
I'm aware that I could write this even with the first definition I gave (because covariant return types are allowed), but I want that the return type "ListFunctor" is enforced by the type system (so that I can't return a FooFunctor instead), which means that the Functor interface needs to return the "self-type" (at least it is called so in other languages).
[Result]
So it seems what I want is impossible. Here is a related blog-post: http://blog.tmorris.net/higher-order-polymorphism-for-pseudo-java/
[Aftermath]
I stumbled over this age-old question of mine, and realized that this was the starting point of the amazing journey with my library highJ, containing much more than a simple Functor
. I would have never imagine that people would use this crazy stuff for anything serious, but it happened, and that makes me very happy.