Тем не менее, есть способы кодировать более родовые дженерики в Java. Пожалуйста, взгляните на проект с более высоким уровнем развития .
Используя это как библиотеку, вы можете изменить свой код следующим образом:
public class Fix<F extends Type.Constructor> {
Type.App<F, Fix<F>> in;
}
Вам, вероятно, следует добавить аннотацию @GenerateTypeConstructor
к вашему Expr
классу
@GenerateTypeConstructor
public class Expr<S> {
// ...
}
Эта аннотация генерирует класс ExprTypeConstructor.
Теперь вы можете обработать свой Fix of Expr следующим образом:
class Main {
void run() {
runWithTyConstr(ExprTypeConstructor.get);
}
<E extends Type.Constructor> void runWithTyConstr(ExprTypeConstructor.Is<E> tyConstrKnowledge) {
Expr<Fix<E>> one = Expr.lit(1);
Expr<Fix<E>> two = Expr.lit(2);
// convertToTypeApp method is generated by annotation processor
Type.App<E, Fix<E>> oneAsTyApp = tyConstrKnowledge.convertToTypeApp(one);
Type.App<E, Fix<E>> twoAsTyApp = tyConstrKnowledge.convertToTypeApp(two);
Fix<E> oneFix = new Fix<>(oneAsTyApp);
Fix<E> twoFix = new Fix<>(twoAsTyApp);
Expr<Fix<E>> addition = Expr.add(oneFix, twoFix);
process(addition, tyConstrKnowledge);
}
<E extends Type.Constructor> void process(
Fix<E> fixedPoint,
ExprTypeConstructor.Is<E> tyConstrKnowledge) {
Type.App<E, Fix<E>> inTyApp = fixedPoint.getIn();
// convertToExpr method is generated by annotation processor
Expr<Fix<E>> in = tyConstrKnowledge.convertToExpr(inTyApp);
for (Fix<E> subExpr: in.getSubExpressions()) {
process(subExpr, tyConstrKnowledge);
}
}
}