package fj.data.optic;
import fj.F;
import fj.data.Either;
import fj.data.Option;
/**
* {@link PPrism} restricted to monomorphic update
*/
public final class Prism<S, A> extends PPrism<S, S, A, A> {
final PPrism<S, S, A, A> pPrism;
public Prism(final PPrism<S, S, A, A> pPrism) {
this.pPrism = pPrism;
}
@Override
public Either<S, A> getOrModify(final S s) {
return pPrism.getOrModify(s);
}
@Override
public S reverseGet(final A a) {
return pPrism.reverseGet(a);
}
@Override
public Option<A> getOption(final S s) {
return pPrism.getOption(s);
}
/***********************************************************/
/** Compose methods between a {@link Prism} and another Optics */
/***********************************************************/
/** compose a {@link Prism} with a {@link Setter} */
public <C, D> Setter<S, C> composeSetter(final Setter<A, C> other) {
return new Setter<>(pPrism.composeSetter(other.pSetter));
}
/** compose a {@link Prism} with a {@link Traversal} */
public <C, D> Traversal<S, C> composeTraversal(final Traversal<A, C> other) {
return new Traversal<>(pPrism.composeTraversal(other.pTraversal));
}
/** compose a {@link Prism} with a {@link Optional} */
public <C, D> Optional<S, C> composeOptional(final Optional<A, C> other) {
return new Optional<>(pPrism.composeOptional(other.pOptional));
}
/** compose a {@link Prism} with a {@link Lens} */
public <C, D> Optional<S, C> composeLens(final Lens<A, C> other) {
return new Optional<>(pPrism.composeLens(other.pLens));
}
/** compose a {@link Prism} with a {@link Prism} */
public <C> Prism<S, C> composePrism(final Prism<A, C> other) {
return new Prism<>(pPrism.composePrism(other.pPrism));
}
/** compose a {@link Prism} with an {@link Iso} */
public <C, D> Prism<S, C> composeIso(final Iso<A, C> other) {
return new Prism<>(pPrism.composeIso(other.pIso));
}
/*****************************************************************/
/** Transformation methods to view a {@link Prism} as another Optics */
/*****************************************************************/
/** view a {@link Prism} as a {@link Setter} */
@Override
public Setter<S, A> asSetter() {
return new Setter<>(pPrism.asSetter());
}
/** view a {@link Prism} as a {@link Traversal} */
@Override
public Traversal<S, A> asTraversal() {
return new Traversal<>(pPrism.asTraversal());
}
/** view a {@link Prism} as a {@link Optional} */
@Override
public Optional<S, A> asOptional() {
return new Optional<>(pPrism.asOptional());
}
public static <S> Prism<S, S> id() {
return new Prism<>(PPrism.pId());
}
public static <S, A> Prism<S, A> prism(final F<S, Option<A>> getOption, final F<A, S> reverseGet) {
return new Prism<>(new PPrism<S, S, A, A>() {
@Override
public Either<S, A> getOrModify(final S s) {
return getOption.f(s).option(Either.left(s), Either.right_());
}
@Override
public S reverseGet(final A a) {
return reverseGet.f(a);
}
@Override
public Option<A> getOption(final S s) {
return getOption.f(s);
}
});
}
}