I'm trying to implement Church Numerals in Java 1.8. My first attempt was:
import java.util.function.UnaryOperator;
@FunctionalInterface
public interface ChurchNumeral {
public static ChurchNumeral valueOf(int n) {
if (n < 0) {
throw new IllegalArgumentException("Argument n must be non-negative.");
}
if (n == 0) {
return (f, arg) -> arg;
}
return (f, arg) -> f(valueOf(n-1).apply(f, arg));
}
<T> T apply(UnaryOperator<T> f, T arg);
}
This fails because the functional method has a type parameter. (Specifically, the lines with lambda expressions give the error: "Illegal lambda expression: Method apply of type ChurchNumeral is generic".)
Based on answers to related questions on the use of generics with functional interfaces, I tried parameterizing the class:
import java.util.function.UnaryOperator;
@FunctionalInterface
public interface ChurchNumeral<T> { // This line changed.
public static ChurchNumeral<?> valueOf(int n) { // This line changed.
if (n < 0) {
throw new IllegalArgumentException("Argument n must be non-negative.");
}
if (n == 0) {
return (f, arg) -> arg;
}
return (f, arg) -> f(valueOf(n-1).apply(f, arg));
}
T apply(UnaryOperator<T> f, T arg); // This line changed.
}
The first lambda expression now compiles, but the second one fails with this error:
The method apply(UnaryOperator, capture#1-of ?) in the type ChurchNumeral is not applicable for the arguments (UnaryOperator, Object)
Additionally, I don't want to have different versions of ChurchNumeral.ZERO for every possible function/argument type.
Any suggestions?