package fj;
import static fj.P.weakMemo;
/**
* A product-3.
*
* @version %build.number%
*/
public abstract class P3<A, B, C> {
/**
* Access the first element of the product.
*
* @return The first element of the product.
*/
public abstract A _1();
/**
* Access the second element of the product.
*
* @return The second element of the product.
*/
public abstract B _2();
/**
* Access the third element of the product.
*
* @return The third element of the product.
*/
public abstract C _3();
/**
* Map the first element of the product.
*
* @param f The function to map with.
* @return A product with the given function applied.
*/
public final <X> P3<X, B, C> map1(final F<A, X> f) {
return new P3<X, B, C>() {
public X _1() {
return f.f(P3.this._1());
}
public B _2() {
return P3.this._2();
}
public C _3() {
return P3.this._3();
}
};
}
/**
* Map the second element of the product.
*
* @param f The function to map with.
* @return A product with the given function applied.
*/
public final <X> P3<A, X, C> map2(final F<B, X> f) {
return new P3<A, X, C>() {
public A _1() {
return P3.this._1();
}
public X _2() {
return f.f(P3.this._2());
}
public C _3() {
return P3.this._3();
}
};
}
/**
* Map the third element of the product.
*
* @param f The function to map with.
* @return A product with the given function applied.
*/
public final <X> P3<A, B, X> map3(final F<C, X> f) {
return new P3<A, B, X>() {
public A _1() {
return P3.this._1();
}
public B _2() {
return P3.this._2();
}
public X _3() {
return f.f(P3.this._3());
}
};
}
/**
* Returns the 1-product projection over the first element.
*
* @return the 1-product projection over the first element.
*/
public final P1<A> _1_() {
return F1Functions.lazy(P3.<A, B, C>__1()).f(this);
}
/**
* Returns the 1-product projection over the second element.
*
* @return the 1-product projection over the second element.
*/
public final P1<B> _2_() {
return F1Functions.lazy(P3.<A, B, C>__2()).f(this);
}
/**
* Returns the 1-product projection over the third element.
*
* @return the 1-product projection over the third element.
*/
public final P1<C> _3_() {
return F1Functions.lazy(P3.<A, B, C>__3()).f(this);
}
/**
* Provides a memoising P3 that remembers its values.
*
* @return A P3 that calls this P3 once for any given element and remembers the value for subsequent calls.
*/
public final P3<A, B, C> memo() {
P3<A, B, C> self = this;
return new P3<A, B, C>() {
private final P1<A> a = weakMemo(self::_1);
private final P1<B> b = weakMemo(self::_2);
private final P1<C> c = weakMemo(self::_3);
public A _1() {
return a._1();
}
public B _2() {
return b._1();
}
public C _3() {
return c._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, B, C> F<P3<A, B, C>, A> __1() {
return P3::_1;
}
/**
* Returns a function that returns the second element of a product.
*
* @return A function that returns the second element of a product.
*/
public static <A, B, C> F<P3<A, B, C>, B> __2() {
return P3::_2;
}
/**
* Returns a function that returns the third element of a product.
*
* @return A function that returns the third element of a product.
*/
public static <A, B, C> F<P3<A, B, C>, C> __3() {
return P3::_3;
}
@Override
public final String toString() {
return Show.p3Show(Show.<A>anyShow(), Show.<B>anyShow(), Show.<C>anyShow()).showS(this);
}
@Override
public final boolean equals(Object other) {
return Equal.equals0(P3.class, this, other,
() -> Equal.p3Equal(Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual()));
}
@Override
public final int hashCode() {
return Hash.p3Hash(Hash.<A>anyHash(), Hash.<B>anyHash(), Hash.<C>anyHash()).hash(this);
}
}