Functional Java bind arity-2 Function (F2) to options
-
15-11-2019 - |
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?
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.