Question

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?

Was it helpful?

Solution 2

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());

OTHER TIPS

I'm not sure what you're asking, but if you're trying to bind a two-arity function into the Option, you should partially apply the two-arity function before binding it. Thus, that'll result into a unary function with a fixed first parameter:

(new F2<...>{ ... }).f(5)

(bind the first parameter to 5, returning a new unary function).

I've searched and haven't found a partial applicator for the second parameter. This is weird.

Your solution works, using a tuple (single parameter) instead of two parameters and working with them. An alternative, maybe better, approach would be (I second Diego on this one) to work with partial functions and curry. For instance you could do something like:

public final F2<Integer, Integer, Option<Integer>> sumInteger() {
    return new F2<Integer,Integer,Option<Integer>>() {
        @Override
        public Option<Integer> f(Integer a, Integer b) {
            /* you logic here */
        }
    }; 
}

public final F<Integer, Option<Integer>> partialSumInteger(final F2<Integer, Integer, Option<Integer>> f2, final Integer fixed) {
    return Function.partialApply2(f2.curry(), fixed);
}

And then pass your now 1-arity function to bind. Have a look at the Functional Java's class fj.Function, it contains functions for currying and partially applying your n-arity functions. I agree the documentation is not the best.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top