Функциональная функция Java привязывает arity-2 (F2) к параметрам

#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. Я согласен, что документация не самая лучшая.