package fj;
import fj.data.Array;
import fj.data.Either;
import fj.data.List;
import fj.data.Option;
import fj.data.Stream;
import fj.data.Validation;
import java.lang.ref.Reference;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import static fj.P.p;
import static fj.Unit.unit;
//import fj.data.*;
public abstract class P1<A> implements F0<A> {
@Override
public final A f() {
return _1();
}
/**
* Access the first element of the product.
*
* @return The first element of the product.
*/
public abstract A _1();
/**
* Returns a function that returns the first element of a product.
*
* @return A function that returns the first element of a product.
*/
public static <A> F<P1<A>, A> __1() {
return P1::_1;
}
/**
* Promote any function to a transformation between P1s.
*
* @deprecated As of release 4.5, use {@link #map_}
* @param f A function to promote to a transformation between P1s.
* @return A function promoted to operate on P1s.
*/
public static <A, B> F<P1<A>, P1<B>> fmap(final F<A, B> f) {
return map_(f);
}
/**
* Promote any function to a transformation between P1s.
*
* @param f A function to promote to a transformation between P1s.
* @return A function promoted to operate on P1s.
*/
public static <A, B> F<P1<A>, P1<B>> map_(final F<A, B> f) {
return a -> a.map(f);
}
/**
* Binds the given function to the value in a product-1 with a final join.
*
* @param f A function to apply to the value in a product-1.
* @return The result of applying the given function to the value of given product-1.
*/
public final <B> P1<B> bind(final F<A, P1<B>> f) {
P1<A> self = this;
return P.lazy(() -> f.f(self._1())._1());
}
/**
* Promotes the given function so that it returns its value in a P1.
*
* @param f A function to have its result wrapped in a P1.
* @return A function whose result is wrapped in a P1.
*/
public static <A, B> F<A, P1<B>> curry(final F<A, B> f) {
return a -> P.lazy(() -> f.f(a));
}
/**
* Performs function application within a P1 (applicative functor pattern).
*
* @param cf The P1 function to apply.
* @return A new P1 after applying the given P1 function to the first argument.
*/
public final <B> P1<B> apply(final P1<F<A, B>> cf) {
P1<A> self = this;
return cf.bind(f -> map_(f).f(self));
}
/**
* Binds the given function to the values in the given P1s with a final join.
*
* @param cb A given P1 to bind the given function with.
* @param f The function to apply to the values in the given P1s.
* @return A new P1 after performing the map, then final join.
*/
public final <B, C> P1<C> bind(final P1<B> cb, final F<A, F<B, C>> f) {
return cb.apply(map_(f).f(this));
}
/**
* Binds the given function to the values in the given P1s with a final join.
*/
public final <B, C> P1<C> bind(final P1<B> cb, final F2<A, B, C> f) {
return bind(cb, F2W.lift(f).curry());
}
/**
* Joins a P1 of a P1 with a bind operation.
*
* @param a The P1 of a P1 to join.
* @return A new P1 that is the join of the given P1.
*/
public static <A> P1<A> join(final P1<P1<A>> a) {
return a.bind(Function.identity());
}
/**
* Promotes a function of arity-2 to a function on P1s.
*
* @param f The function to promote.
* @return A function of arity-2 promoted to map over P1s.
*/
public static <A, B, C> F<P1<A>, F<P1<B>, P1<C>>> liftM2(final F<A, F<B, C>> f) {
return Function.curry((pa, pb) -> pa.bind(pb, f));
}
public final <B, C> P1<C> liftM2(P1<B> pb, F2<A, B, C> f) {
return P.lazy(() -> f.f(_1(), pb._1()));
}
/**
* Turns a List of P1s into a single P1 of a List.
*
* @param as The list of P1s to transform.
* @return A single P1 for the given List.
*/
public static <A> P1<List<A>> sequence(final List<P1<A>> as) {
return as.foldRight(liftM2(List.cons()), p(List.nil()));
}
/**
* A first-class version of the sequence method for lists of P1s.
*
* @return A function from a List of P1s to a single P1 of a List.
*/
public static <A> F<List<P1<A>>, P1<List<A>>> sequenceList() {
return P1::sequence;
}
/**
* Turns a stream of P1s into a single P1 of a stream.
*
* @param as The stream of P1s to transform.
* @return A single P1 for the given stream.
*/
public static <A> P1<Stream<A>> sequence(final Stream<P1<A>> as) {
return as.foldRight(liftM2(Stream.cons()), p(Stream.nil()));
}
/**
* Turns an optional P1 into a lazy option.
*/
public static <A> P1<Option<A>> sequence(final Option<P1<A>> o) {
return P.lazy(() -> o.map(P1::_1));
}
/**
* Turns an array of P1s into a single P1 of an array.
*
* @param as The array of P1s to transform.
* @return A single P1 for the given array.
*/
public static <A> P1<Array<A>> sequence(final Array<P1<A>> as) {
return P.lazy(() -> as.map(P1.__1()));
}
/**
* Traversable instance of P1 for List
*
* @param f The function that takes A and produces a List<B> (non-deterministic result)
* @return A List of P1<B>
*/
public final <B> List<P1<B>> traverseList(final F<A, List<B>> f){
return f.f(_1()).map(P::p);
}
/**
* Traversable instance of P1 for Either
*
* @param f The function produces Either
* @return An Either of P1<B>
*/
public final <B, X> Either<X, P1<B>> traverseEither(final F<A, Either<X, B>> f){
return f.f(_1()).right().map(P::p);
}
/**
* Traversable instance of P1 for Option
*
* @param f The function that produces Option
* @return An Option of P1<B>
*/
public final <B> Option<P1<B>> traverseOption(final F<A, Option<B>> f){
return f.f(_1()).map(P::p);
}
/**
* Traversable instance of P1 for Validation
*
* @param f The function might produces Validation
* @return An Validation of P1<B>
*/
public final <B, E> Validation<E, P1<B>> traverseValidation(final F<A, Validation<E, B>> f){
return f.f(_1()).map(P::p);
}
/**
* Traversable instance of P1 for Stream
*
* @param f The function that produces Stream
* @return An Stream of P1<B>
*/
public final <B> Stream<P1<B>> traverseStream(final F<A, Stream<B>> f){
return f.f(_1()).map(P::p);
}
/**
* Map the element of the product.
*
* @param f The function to map with.
* @return A product with the given function applied.
*/
public final <B> P1<B> map(final F<A, B> f) {
final P1<A> self = this;
return P.lazy(() -> f.f(self._1()));
}
/**
* @deprecated since 4.7. Use {@link P1#weakMemo()} instead.
*/
@Deprecated
public final P1<A> memo() {
return weakMemo();
}
/**
* Returns a P1 that remembers its value.
*
* @return A P1 that calls this P1 once and remembers the value for subsequent calls.
*/
public P1<A> hardMemo() { return new Memo<>(this); }
/**
* Like <code>memo</code>, but the memoized value is wrapped into a <code>WeakReference</code>
*/
public P1<A> weakMemo() { return new WeakReferenceMemo<>(this); }
/**
* Like <code>memo</code>, but the memoized value is wrapped into a <code>SoftReference</code>
*/
public P1<A> softMemo() { return new SoftReferenceMemo<>(this); }
/**
* @deprecated since 4.7. Use {@link P#weakMemo(F0)} instead.
*/
@Deprecated
public static <A> P1<A> memo(F<Unit, A> f) {
return P.weakMemo(() -> f.f(unit()));
}
/**
* @deprecated since 4.7. Use {@link P#weakMemo(F0)} instead.
*/
@Deprecated
public static <A> P1<A> memo(F0<A> f) {
return P.weakMemo(f);
}
static final class Memo<A> extends P1<A> {
private volatile F0<A> fa;
private A value;
Memo(F0<A> fa) { this.fa = fa; }
@Override public final A _1() {
return (fa == null) ? value : computeValue();
}
private synchronized A computeValue() {
F0<A> fa = this.fa;
if (fa != null) {
value = fa.f();
this.fa = null;
}
return value;
}
@Override public P1<A> hardMemo() { return this; }
@Override public P1<A> softMemo() { return this; }
@Override public P1<A> weakMemo() { return this; }
}
abstract static class ReferenceMemo<A> extends P1<A> {
private final F0<A> fa;
private volatile Reference<P1<A>> v = null;
ReferenceMemo(final F0<A> fa) { this.fa = fa; }
@Override public final A _1() {
Reference<P1<A>> v = this.v;
P1<A> p1 = v != null ? v.get() : null;
return p1 != null ? p1._1() : computeValue();
}
private synchronized A computeValue() {
Reference<P1<A>> v = this.v;
P1<A> p1 = v != null ? v.get() : null;
if (p1 == null) {
A a = fa.f();
this.v = newReference(p(a));
return a;
}
return p1._1();
}
abstract <B> Reference<B> newReference(B ref);
}
static final class WeakReferenceMemo<A> extends ReferenceMemo<A> {
WeakReferenceMemo(F0<A> fa) { super(fa); }
@Override
<B> Reference<B> newReference(final B ref) { return new WeakReference<>(ref); }
@Override public P1<A> weakMemo() { return this; }
}
static final class SoftReferenceMemo<A> extends ReferenceMemo<A> {
SoftReferenceMemo(F0<A> self) { super(self); }
@Override
<B> Reference<B> newReference(final B ref) { return new SoftReference<>(ref); }
@Override public P1<A> softMemo() { return this; }
@Override public P1<A> weakMemo() { return this; }
}
/**
* Returns a constant function that always uses this value.
*
* @return A constant function that always uses this value.
*/
public final <B> F<B, A> constant() { return Function.constant(_1()); }
@Override
public final String toString() {
return Show.p1Show(Show.<A>anyShow()).showS(this);
}
@Override
public final boolean equals(Object other) {
return Equal.equals0(P1.class, this, other, () -> Equal.p1Equal(Equal.anyEqual()));
}
@Override
public final int hashCode() {
return Hash.p1Hash(Hash.<A>anyHash()).hash(this);
}
}