The first problem is that andThen takes the return value of one function and makes the parameter type of the next function, so you need, as @LouisWasserman explains, combine them at the end with the output type, one of which corresponds to the input type of the following:
static <T1, T2, T3> Transformer<T1, T3> combine2(Transformer<T1, T2> first, Transformer<T2, T3> second) {
The second problem, he explains, is that Function.andThen , which you call, returns Function , not Transformer . Please note, however, that Function and Transformer have the same shape - one input, one output. Because of this, you can use one and then adapt it to another using a method reference as follows:
static <T1, T2, T3> Transformer<T1, T3> combine(Transformer<T1, T2> first, Transformer<T2, T3> second) { return first.andThen(second)::apply; }
You do not need to create a function for this. You can use the same method calling Function.andThen() directly:
Transformer<String,Integer> t1 = ... Transformer<Integer,Double> t2 = ... Transformer<Double,String> t3 = ... Transformer<String,String> t123 = t1.andThen(t2).andThen(t3)::apply;