#java #functional-programming #functional-java
#java #функциональное программирование #функциональный-java
Вопрос:
Я понимаю базовый синтаксис привязки для Option с функциональной java как
Option.some(2).bind(new F<Integer,Option<Integer>>(){
public Option<Integer>f(Integer i){
return Option.some(i/2);
}
};
Это хорошо работает для отдельных функций ввода, но я не могу понять, как использовать несколько функций ввода (например, F2, F3 и т.д.).
ie:
new F2<Integer,Integer,Option<Integer>>(){
public Option<Integer>f(Integer a,Integer b){
return Option.some(a/b);
}
}
Я знаю, что чего-то не хватает, но документации немного мало.
Идеи?
Ответ №1:
Я не уверен, о чем вы спрашиваете, но если вы пытаетесь привязать функцию с двумя арностями к Option
, вам следует частично применить функцию с двумя арностями перед ее привязкой. Таким образом, это приведет к унарной функции с фиксированным первым параметром:
(new F2<...>{ ... }).f(5)
(привязывает первый параметр к 5
, возвращая новую унарную функцию).
Я искал и не нашел частичного аппликатора для второго параметра. Это странно.
Комментарии:
1. В реальных функциональных языках программирования вы делаете это с помощью
flip f b a = f a b
, а затемflip myfunc b
Ответ №2:
Прорыв,
Хитрость в том, что вам нужно распаковать функцию arity и привязать ее к продукту ваших опций.
Итак, в примере:
реализация arity-5
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());
}
};
}
}
использование:
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());
Ответ №3:
Ваше решение работает, используя кортеж (один параметр) вместо двух параметров и работая с ними. Альтернативным, возможно лучшим, подходом было бы (я поддерживаю Диего в этом вопросе) работать с частичными функциями и curry. Например, вы могли бы сделать что-то вроде:
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);
}
И затем передает вашу теперь 1-arity функцию в bind. Взгляните на функциональный класс Java fj.Function
, он содержит функции для извлечения и частичного применения ваших функций n-arity. Я согласен, что документация не самая лучшая.