All Downloads are FREE. Search and download functionalities are using the official Maven repository.

jio.BiLambda Maven / Gradle / Ivy

The newest version!
package jio;

import static java.util.Objects.requireNonNull;

import java.util.function.BiFunction;
import java.util.function.BiPredicate;

/**
 * Represents a function that takes two inputs of types 'A' and 'B' and produces an 'IO' effect with a result of type
 * 'O'.
 *
 * @param   the type of the first input
 * @param  the type of the second input
 * @param       the type of the effect's result
 */
public interface BiLambda extends BiFunction> {

  /**
   * Transforms a 'BiPredicate' into a 'BiLambda' for producing boolean 'IO' effects.
   *
   * @param predicate the predicate to transform
   * @param        the type of the first parameter of the predicate
   * @param        the type of the second parameter of the predicate
   * @return a 'BiLambda' that produces boolean 'IO' effects
   */
  static  BiLambda liftPredicate(final BiPredicate predicate) {
    requireNonNull(predicate);
    return (a,
            b) -> {
      try {
        return IO.succeed(predicate.test(a,
                                         b));
      } catch (Exception e) {
        return IO.fail(e);
      }
    };
  }

  /**
   * Transforms a 'BiFunction' into a 'BiLambda' for producing 'IO' effects with a custom result type 'O'.
   *
   * @param fn  the function to transform
   * @param  the type of the first parameter of the function
   * @param  the type of the second parameter of the function
   * @param  the type of the result produced by the function
   * @return a 'BiLambda' that produces 'IO' effects with a result of type 'O'
   */
  static  BiLambda liftFunction(final BiFunction fn) {
    requireNonNull(fn);
    return (a,
            b) -> {
      try {
        return IO.succeed(fn.apply(a,
                                   b));
      } catch (Exception e) {
        return IO.fail(e);
      }
    };
  }

  /**
   * Partially applies the first parameter (A) and returns a 'Lambda' with the second parameter (B) as the input.
   *
   * @param firstInput The first parameter to partially apply.
   * @return a 'Lambda' with the second parameter (B) as the input.
   */
  default Lambda partialWithFirst(final FirstInput firstInput) {
    return i -> apply(firstInput,
                      i);
  }

  /**
   * Partially applies the second parameter (B) and returns a 'Lambda' with the first parameter (A) as the input.
   *
   * @param secondInput The second parameter to partially apply.
   * @return a 'Lambda' with the first parameter (A) as the input.
   */
  default Lambda partialWithSecond(final SecondInput secondInput) {
    return i -> apply(i,
                      secondInput);
  }
}