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

fj.data.optic.PSetter 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.data.optic;

import fj.F;
import fj.Function;
import fj.data.Either;

/**
 * A {@link PSetter} is a generalisation of Functor map: - `map: (A => B) => F[A] => F[B]` - `modify: (A => B) => S =>
 * T`
 *
 * {@link PSetter} stands for Polymorphic Setter as it set and modify methods change a type `A` to `B` and `S` to `T`.
 *
 * {@link PTraversal}, {@link POptional}, {@link PPrism}, {@link PLens} and {@link PIso} are valid {@link PSetter}
 *
 * @param  the source of a {@link PSetter}
 * @param  the modified source of a {@link PSetter}
 * @param  the target of a {@link PSetter}
 * @param  the modified target of a {@link PSetter}
 */
public abstract class PSetter {

  PSetter() {
    super();
  }

  /** modify polymorphically the target of a {@link PSetter} with a function */
  public abstract F modify(F f);

  /** set polymorphically the target of a {@link PSetter} with a value */
  public abstract F set(final B b);

  /** join two {@link PSetter} with the same target */
  public final  PSetter, Either, A, B> sum(final PSetter other) {
    return pSetter(f -> e -> e.bimap(modify(f), other.modify(f)));
  }

  /*************************************************************/
  /** Compose methods between a {@link PSetter} and another Optics */
  /*************************************************************/

  /** compose a {@link PSetter} with a {@link PSetter} */
  public final  PSetter composeSetter(final PSetter other) {
    final PSetter self = this;
    return new PSetter() {

      @Override
      public F modify(final F f) {
        return self.modify(other.modify(f));
      }

      @Override
      public F set(final D d) {
        return self.modify(other.set(d));
      }
    };
  }

  /** compose a {@link PSetter} with a {@link PTraversal} */
  public final  PSetter composeTraversal(final PTraversal other) {
    return composeSetter(other.asSetter());
  }

  /** compose a {@link PSetter} with a {@link POptional} */
  public final  PSetter composeOptional(final POptional other) {
    return composeSetter(other.asSetter());
  }

  /** compose a {@link PSetter} with a {@link PPrism} */
  public final  PSetter composePrism(final PPrism other) {
    return composeSetter(other.asSetter());
  }

  /** compose a {@link PSetter} with a {@link PLens} */
  public final  PSetter composeLens(final PLens other) {
    return composeSetter(other.asSetter());
  }

  /** compose a {@link PSetter} with a {@link PIso} */
  public final  PSetter composeIso(final PIso other) {
    return composeSetter(other.asSetter());
  }

  public static  PSetter pId() {
    return PIso. pId().asSetter();
  }

  public static  PSetter, Either, S, T> pCodiagonal() {
    return pSetter(f -> e -> e.bimap(f, f));
  }

  public static  PSetter pSetter(final F, F> modify) {
    return new PSetter() {
      @Override
      public F modify(final F f) {
        return modify.f(f);
      }

      @Override
      public F set(final B b) {
        return modify.f(Function.constant(b));
      }
    };
  }
}