An example showing that you can't seriously do deeply-parameterized types without typedef:
public class NaturalTransformation< XObjects, // type of nodes in the first category (like Alksnis?) XArrows, // type of arrows in the first category YObjects, // type of nodes in the second category YArrows // type of arrows in the second category > extends Morphism< Functor<XObjects, XArrows, YObjects, YArrows>, Functor<XObjects, XArrows, YObjects, YArrows>> { private SetMorphism<XObjects, Set<XObjects>, YArrows, Set<YArrows>> Fx_to_Gx; public NaturalTransformation(Functor<XObjects, XArrows, YObjects, YArrows> F, Functor<XObjects, XArrows, YObjects, YArrows> G, SetMorphism<XObjects, Set<XObjects>, YArrows, Set<YArrows>> Fx_to_Gx) { super(F, G); this.Fx_to_Gx = Fx_to_Gx; } public static <XObjects, XArrows, YObjects, YArrows> NaturalTransformation< XObjects, XArrows, YObjects, YArrows > unit(final Functor<XObjects, XArrows, YObjects, YArrows> F) { return new NaturalTransformation< XObjects, XArrows, YObjects, YArrows>(F, F, new SetMorphism<XObjects, Set<XObjects>, YArrows, Set<YArrows>>( F.domain().objects(), F.codomain().arrows()) { public YArrows apply(XObjects x) { return F.codomain().unit(F.nodesMorphism.apply(x)); } } ); } // TODO: implement it; currently it is just a copy of funit public static <XObjects, XArrows, YObjects, YArrows> NaturalTransformation< XObjects, XArrows, YObjects, YArrows > constant(final Functor<XObjects, XArrows, YObjects, YArrows> F) { return new NaturalTransformation< XObjects, XArrows, YObjects, YArrows>(F, F, new SetMorphism<XObjects, Set<XObjects>, YArrows, Set<YArrows>>( F.domain().objects(), F.codomain().arrows()) { public YArrows apply(XObjects x) { return F.codomain().unit(F.nodesMorphism.apply(x)); } } ); } }