Composing Functions for Dependency Injection with Guice

It is really tedious creating a class whose sole purpose is to compose two functions for a single purpose. Thankfully there is a better way to do this.

The heart of the technique is creating a generic class that represents function composition.  This class will have three type parameters: the input type A , the intermediate type  B , and the output type  C .  The result will be a  Module configuration for Guice that allows you to inject a A -> C  function by binding a specific A -> B function, another specific  B -> C function, and a generic binding for  A -> C .

First we create ComposedFunction.java:

import com.google.common.base.Function;
import com.google.common.base.Functions;

import javax.inject.Inject;

public class ComposedFunction<A, B, C> implements Function<A, C> {
    private final Function<A, C> composed;

    @Inject
    public ComposedFunction(Function<B, C> g, Function<A, B> f) {
        composed = Functions.compose(g, f);
    }

    @Override
    public C apply(A p) {
        return composed.apply(p);
    }
}

Then we test it with ComposedFunctionTest.java

import com.google.common.base.Function;
import com.google.inject.Binder;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.Module;
import com.google.inject.TypeLiteral;
import org.junit.Test;

import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.MatcherAssert.assertThat;

public final class ComposedFunctionTest {
    @Test
    public void supportsGenericInjection() {
        Injector injector = Guice.createInjector(new ComposedFunctionModule());
        Function<Double, String> composed = injector.getInstance(
                new Key<Function<Double, String>>(){}
        );
        assertThat(composed.apply(1.25), is("3ff4000000000000"));
    }

    private static final class ComposedFunctionModule implements Module {
        @Override
        public void configure(Binder binder) {
            binder.bind(new TypeLiteral<Function<Double, Long>>(){}).
                    to(DoubleToLong.class);
            binder.bind(new TypeLiteral<Function<Long, String>>(){}).
                    to(LongToString.class);
            binder.bind(new TypeLiteral<Function<Double, String>>(){}).
                    to(new TypeLiteral<ComposedFunction<Double, Long, String>>(){});
        }
    }

    private static final class DoubleToLong implements Function<Double, Long> {
        @Override
        public Long apply(Double x) {
            return Double.doubleToLongBits(x);
        }
    }

    private static final class LongToString implements Function<Long, String> {
        @Override
        public String apply(Long x) {
            return Long.toHexString(x);
        }
    }
}

Why bother? This technique is handy when you have lots of common code for going from A to B in many dependencies. It lets you pull that piece out and use it something like an implicit conversion.