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

fj.control.parallel.Callables Maven / Gradle / Ivy

Go to download

Functional Java is an open source library that supports closures for the Java programming language

There is a newer version: 5.0
Show newest version
package fj.control.parallel;

import fj.*;

import static fj.Function.curry;

import fj.data.Either;
import static fj.data.Either.left;
import static fj.data.Either.right;
import fj.data.List;
import fj.data.Option;
import static fj.data.Option.none;
import static fj.data.Option.some;

import java.util.concurrent.Callable;

/**
 * Monadic functions and conversion methods for java.util.concurrent.Callable.
 *
 * @version %build.number%
 */
public final class Callables {
  private Callables() {
  }

  /**
   * Returns a callable that completely preserves the argument. The unit function for Callables.
   *
   * @param a A value to preserve in a Callable
   * @return A Callable that yields the argument when called.
   */
  public static  Callable callable(final A a) {
    return () -> a;
  }

  /**
   * Returns a callable that throws the given exception. The unit function for Callables.
   *
   * @param e The exception to throw when the Callable is called.
   * @return A callable that always throws the given exception.
   */
  public static  Callable callable(final Exception e) {
    return () -> {
      throw e;
    };
  }

  /**
   * Provides a transformation from a value to a Callable that completely preserves that value.
   *
   * @return A function from a value to a Callable that completely preserves that value.
   */
  public static  F> callable() {
    return Callables::callable;
  }

  /**
   * Wraps a given function's return value in a Callable.
   * The Kleisli arrow for Callables.
   *
   * @param f The function whose return value to wrap in a Callable.
   * @return The equivalent function whose return value is wrapped in a Callable.
   */
  public static  F> callable(final F f) {
    return a -> () -> f.f(a);
  }

  /**
   * Provides a transformation from a function to a Callable-valued function that is equivalent to it.
   * The first-class Kleisli arrow for Callables.
   *
   * @return A transformation from a function to the equivalent Callable-valued function.
   */
  public static  F, F>> arrow() {
    return Callables::callable;
  }

  /**
   * Binds the given function to the value in a Callable with a final join.
   *
   * @param a A value in a Callable to which to apply a function.
   * @param f A function to apply to the value in a Callable.
   * @return The result of applying the function in the second argument to the value of the Callable in the first.
   */
  public static  Callable bind(final Callable a, final F> f) {
    return () -> f.f(a.call()).call();
  }

  /**
   * Lifts any function to a function on Callables.
   *
   * @param f A function to lift to a function on Callables.
   * @return That function lifted to a function on Callables.
   */
  public static  F, Callable> fmap(final F f) {
    return a -> bind(a, callable(f));
  }

  /**
   * Performs function application within a callable (applicative functor pattern).
   *
   * @param ca The callable to which to apply a function.
   * @param cf The callable function to apply.
   * @return A new callable after applying the given callable function to the first argument.
   */
  public static  Callable apply(final Callable ca, final Callable> cf) {
    return bind(cf, f -> fmap(f).f(ca));
  }

  /**
   * Binds the given function to the values in the given callables with a final join.
   *
   * @param ca A given callable to bind the given function with.
   * @param cb A given callable to bind the given function with.
   * @param f  The function to apply to the values in the given callables.
   * @return A new callable after performing the map, then final join.
   */
  public static  Callable bind(final Callable ca, final Callable cb, final F> f) {
    return apply(cb, fmap(f).f(ca));
  }

  /**
   * Joins a Callable of a Callable with a bind operation.
   *
   * @param a The Callable of a Callable to join.
   * @return A new Callable that is the join of the given Callable.
   */
  public static  Callable join(final Callable> a) {
    return bind(a, Function.identity());
  }

  /**
   * Promotes a function of arity-2 to a function on callables.
   *
   * @param f The function to promote.
   * @return A function of arity-2 promoted to map over callables.
   */
  public static  F, F, Callable>> liftM2(final F> f) {
    return curry((ca, cb) -> bind(ca, cb, f));
  }

  /**
   * Turns a List of Callables into a single Callable of a List.
   *
   * @param as The list of callables to transform.
   * @return A single callable for the given List.
   */
  public static  Callable> sequence(final List> as) {
    return as.foldRight(Callables.liftM2(List.cons()), callable(List.nil()));
  }

  /**
   * A first-class version of the sequence method.
   *
   * @return A function from a List of Callables to a single Callable of a List.
   */
  public static  F>, Callable>> sequence_() {
    return Callables::sequence;
  }

  /**
   * Turns the given Callable into an optional value.
   *
   * @param a The callable to convert to an optional value.
   * @return An optional value that yields the value in the Callable, or None if the Callable fails.
   */
  public static  P1> option(final Callable a) {
    return P.lazy(() -> {
        try {
          return some(a.call());
        } catch (Exception e) {
          return none();
        }
    });
  }

  /**
   * Returns a transformation from a Callable to an optional value.
   *
   * @return a function that turns a Callable into an optional value.
   */
  public static  F, P1>> option() {
    return Callables::option;
  }

  /**
   * Turns the given Callable into either an exception or the value in the Callable.
   *
   * @param a The callable to convert to an Either value.
   * @return Either the value in the given Callable, or the Exception with which the Callable fails.
   */
  public static  P1> either(final Callable a) {
    return P.lazy(() -> {
        try {
            return right(a.call());
        } catch (Exception e) {
            return left(e);
        }
    });
  }

  /**
   * Returns a transformation from a Callable to an Either.
   *
   * @return a function that turns a Callable into an Either.
   */
  public static  F, P1>> either() {
    return Callables::either;
  }

  /**
   * Turns a given Either value into the equivalent Callable.
   *
   * @param e Either an exception or a value to wrap in a Callable
   * @return A Callable equivalent to the given Either value.
   */
  public static  Callable fromEither(final F0> e) {
    return () -> {
      final Either e1 = e.f();
      if (e1.isLeft())
        throw e1.left().value();
      else
        return e1.right().value();
    };
  }

  /**
   * Returns a transformation from an Either to a Callable.
   *
   * @return a function that turns an Either into a Callable.
   */
  public static  F>, Callable> fromEither() {
    return Callables::fromEither;
  }

  /**
   * Turns an optional value into a Callable.
   *
   * @param o An optional value to turn into a Callable.
   * @return A Callable that yields some value or throws an exception in the case of no value.
   */
  public static  Callable fromOption(final F0> o) {
    return () -> {
      final Option o1 = o.f();
      if (o1.isSome())
        return o1.some();
      else
        throw new Exception("No value.");
    };
  }

  /**
   * Returns a transformation from an optional value to a Callable
   *
   * @return A function that turns an optional value into a Callable that yields some value
   *         or throws an exception in the case of no value.
   */
  public static  F>, Callable> fromOption() {
    return Callables::fromOption;
  }

  /**
   * Normalises the given Callable by calling it and wrapping the result in a new Callable.
   * If the given Callable throws an Exception, the resulting Callable will throw that same Exception.
   *
   * @param a The callable to evaluate.
   * @return A normalised callable that just returns the result of calling the given callable.
   */
  public static  Callable normalise(final Callable a) {
    try {
      return callable(a.call());
    } catch (Exception e) {
      return callable(e);
    }
  }

  /**
   * A first-class version of the normalise function.
   *
   * @return A function that normalises the given Callable by calling it and wrapping the result in a new Callable.
   */
  public static  F, Callable> normalise() {
    return Callables::normalise;
  }

}