Search code examples
javafunctional-programmingfunctional-java

Functional Java bind arity-2 Function (F2) to options


I understand the basic bind syntax for Option with functional java as

Option.some(2).bind(new F<Integer,Option<Integer>>(){
    public Option<Integer>f(Integer i){
        return Option.some(i/2);
    }
};

That works well for single input functions but I can't figure out how to use multiple input functions (like F2, F3, etc).

ie:

new F2<Integer,Integer,Option<Integer>>(){
    public Option<Integer>f(Integer a,Integer b){
        return Option.some(a/b);
    }
} 

I know I'm missing something, but documentation is a bit sparse. Ideas?


Solution

  • Breakthrough,

    The trick is you need to uncurry the arity function and bind it to the product of your options.

    So in example:

    arity-5 implementation

    import fj.F;
    import fj.F5;
    import fj.P5;
    
    public abstract class F5Optional<At, Bt, Ct, Dt, Et, Ft> extends F5<At, Bt, Ct, Dt, Et, Ft> {
    
        public final F<P5<At, Bt, Ct, Dt, Et>, Ft> tupleize() {
            return new F<P5<At, Bt, Ct, Dt, Et>, Ft>() {
    
                @Override
                public Ft f(final P5<At, Bt, Ct, Dt, Et> p) {
                    return F5Optional.this.f(p._1(), p._2(), p._3(), p._4(), p._5());
                }
            };
        }
    
    }
    

    usage:

        F5Optional<Integer, Integer, Integer, Integer, Integer, Option<Integer>> f5 = new F5Optional<Integer, Integer, Integer, Integer, Integer, Option<Integer>>() {
    
            @Override
            public Option<Integer> f(Integer a, Integer b, Integer c, Integer d, Integer e) {
                return Option.some(a + b + c + d + e);
            }
        };
        Option<Integer> test2 = b.bindProduct(Option.some(1), Option.some(1), Option.some(1), Option.some(1)).bind(f5.tupleize());
        Assert.assertTrue(new Integer(8).equals(test2.toNull()));
    
        Option<Integer> nullInteger = Option.none();
        Option<Integer> test3 = b.bindProduct(nullInteger, Option.some(1), Option.some(1), Option.some(1)).bind(f5.tupleize());
        Assert.assertTrue(test3.isNone());