Functions { public static <R, S, T> Function<R, T> compose(Function<S, T> f, Function<R, S> g) { return x -> f.apply(g.apply(x)); } private  Functions(); static Function<R, T> compose(Function<S, T> f, Function<R, S> g); static Function<List<F>, T> curryLeft(Function<List<F>, T> f, List<F> args); static Function<F, T> curryLeft(BiFunction<E, F, T> f, E x); static Function<E, T> curryRight(BiFunction<E, F, T> f, F y); static Function<List<F>, T> curryRight(Function<List<F>, T> f, List<F> args);  }
@Test public void testCompose() { Function<Pair<String, Integer>, Integer> f = Pair::getSecond; Function<Integer, Integer> g = x -> 2 * x; Function<Pair<String, Integer>, Integer> h = compose(g, f); Pair<String, Integer> p = new Pair<>("hello", 7); int s = h.apply(p); assertEquals(14, s); }