package bjc.utils.data; import java.util.function.BiConsumer; import java.util.function.BiFunction; import java.util.function.Function; import bjc.utils.funcdata.theory.Bifunctor; /** * Represents a pair of values * * @author ben * @param * The type of the left side of the pair * @param * The type of the right side of the pair * */ public interface IPair extends Bifunctor { /** * Bind a function across the values in this pair * * @param * The type of the bound left * @param * The type of the bound right * @param binder * The function to bind with * @return The bound pair */ public IPair bind( BiFunction> binder); /** * Bind a function to the left value in this pair * * @param * The type of the bound value * @param leftBinder * The function to use to bind * @return A pair with the left type bound */ public IPair bindLeft( Function> leftBinder); /** * Bind a function to the right value in this pair * * @param * The type of the bound value * @param rightBinder * The function to use to bind * @return A pair with the right type bound */ public IPair bindRight( Function> rightBinder); /** * Pairwise combine two pairs together * * @param * The left type of the other pair * @param * The right type of the other pair * @param otherPair * The pair to combine with * @return The pairs, pairwise combined together */ public default IPair, IPair> combine( final IPair otherPair) { return combine(otherPair, Pair::new, Pair::new); } /** * Combine the contents of two pairs together * * @param * The type of the left value of the other pair * @param * The type of the right value of the other pair * @param * The type of the left value of the combined pair * @param * The type of the right value of the combined pair * @param otherPair * The other pair to combine with * @param leftCombiner * @param rightCombiner * @return A pair with its values combined */ public IPair combine( IPair otherPair, BiFunction leftCombiner, BiFunction rightCombiner); /** * Immediately perfom the specified action with the contents of this * pair * * @param consumer * The action to perform on the pair */ public default void doWith(final BiConsumer consumer) { merge((leftValue, rightValue) -> { consumer.accept(leftValue, rightValue); return null; }); } @Override default LeftBifunctorMap fmapLeft( final Function func) { return argumentPair -> { if (!(argumentPair instanceof IPair)) { final String msg = "This function can only be applied to instances of IPair"; throw new IllegalArgumentException(msg); } final IPair argPair = (IPair) argumentPair; return argPair.mapLeft(func); }; } @Override default RightBifunctorMap fmapRight(final Function func) { return argumentPair -> { if (!(argumentPair instanceof IPair)) { final String msg = "This function can only be applied to instances of IPair"; throw new IllegalArgumentException(msg); } final IPair argPair = (IPair) argumentPair; return argPair.mapRight(func); }; } /** * Get the value on the left side of the pair * * @return The value on the left side of the pair */ @Override public default LeftType getLeft() { return merge((leftValue, rightValue) -> leftValue); } /** * Get the value on the right side of the pair * * @return The value on the right side of the pair */ @Override public default RightType getRight() { return merge((leftValue, rightValue) -> rightValue); } /** * Transform the value on the left side of the pair. Doesn't modify the * pair * * @param * The new type of the left part of the pair * @param mapper * The function to use to transform the left part of the * pair * @return The pair, with its left part transformed */ public IPair mapLeft(Function mapper); /** * Transform the value on the right side of the pair. Doesn't modify the * pair * * @param * The new type of the right part of the pair * @param mapper * The function to use to transform the right part of the * pair * @return The pair, with its right part transformed */ public IPair mapRight(Function mapper); /** * Merge the two values in this pair into a single value * * @param * The type of the single value * @param merger * The function to use for merging * @return The pair, merged into a single value */ public MergedType merge(BiFunction merger); }