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 * The function to combine the left values with. * * @param rightCombiner * The function to combine the right values with. * * @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); public static IPair pair(T1 left, T2 right) { return new Pair<>(left, right); } }