All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.jnape.palatable.lambda.adt.coproduct.CoProduct7 Maven / Gradle / Ivy

There is a newer version: 5.5.0
Show newest version
package com.jnape.palatable.lambda.adt.coproduct;

import com.jnape.palatable.lambda.adt.Maybe;
import com.jnape.palatable.lambda.adt.choice.Choice6;
import com.jnape.palatable.lambda.adt.hlist.Tuple7;
import com.jnape.palatable.lambda.functions.Fn1;

import java.util.function.Function;

import static com.jnape.palatable.lambda.adt.Maybe.just;
import static com.jnape.palatable.lambda.adt.Maybe.nothing;
import static com.jnape.palatable.lambda.adt.hlist.HList.tuple;
import static com.jnape.palatable.lambda.functions.Fn1.fn1;
import static com.jnape.palatable.lambda.functions.builtin.fn1.Constantly.constantly;

/**
 * A generalization of the coproduct of seven types.
 *
 * @param  the first possible type
 * @param  the second possible type
 * @param  the third possible type
 * @param  the fourth possible type
 * @param  the fifth possible type
 * @param  the sixth possible type
 * @param  the seventh possible type
 * @see CoProduct2
 */
@FunctionalInterface
public interface CoProduct7> {

    /**
     * Type-safe convergence requiring a match against all potential types.
     *
     * @param aFn morphism A -> R
     * @param bFn morphism B -> R
     * @param cFn morphism C -> R
     * @param dFn morphism D -> R
     * @param eFn morphism E -> R
     * @param fFn morphism F -> R
     * @param gFn morphism G -> R
     * @param  result type
     * @return the result of applying the appropriate morphism from whichever type is represented by this coproduct to R
     * @see CoProduct2#match(Function, Function)
     */
     R match(Function aFn,
                Function bFn,
                Function cFn,
                Function dFn,
                Function eFn,
                Function fFn,
                Function gFn);

    /**
     * Diverge this coproduct by introducing another possible type that it could represent.
     *
     * @param  the additional possible type of this coproduct
     * @return a Coproduct8<A, B, C, D, E, F, G, H>
     * @see CoProduct2#diverge()
     */
    default  CoProduct8> diverge() {
        return new CoProduct8>() {
            @Override
            public  R match(Function aFn, Function bFn,
                               Function cFn, Function dFn,
                               Function eFn, Function fFn,
                               Function gFn, Function hFn) {
                return CoProduct7.this.match(aFn, bFn, cFn, dFn, eFn, fFn, gFn);
            }
        };
    }

    /**
     * Converge this coproduct down to a lower order coproduct by mapping the last possible type into an earlier
     * possible type.
     *
     * @param convergenceFn morphism G -> {@link CoProduct6}<A, B, C, D, E, F>
     * @return a {@link CoProduct6}<A, B, C, D, E, F>
     */
    default CoProduct6> converge(
            Function> convergenceFn) {
        return match(Choice6::a, Choice6::b, Choice6::c, Choice6::d, Choice6::e, Choice6::f, convergenceFn::apply);
    }

    /**
     * Project this coproduct onto a tuple.
     *
     * @return a tuple of the coproduct projection
     * @see CoProduct2#project()
     */
    default Tuple7, Maybe, Maybe, Maybe, Maybe, Maybe, Maybe> project() {
        return match(a -> tuple(just(a), nothing(), nothing(), nothing(), nothing(), nothing(), nothing()),
                     b -> tuple(nothing(), just(b), nothing(), nothing(), nothing(), nothing(), nothing()),
                     c -> tuple(nothing(), nothing(), just(c), nothing(), nothing(), nothing(), nothing()),
                     d -> tuple(nothing(), nothing(), nothing(), just(d), nothing(), nothing(), nothing()),
                     e -> tuple(nothing(), nothing(), nothing(), nothing(), just(e), nothing(), nothing()),
                     f -> tuple(nothing(), nothing(), nothing(), nothing(), nothing(), just(f), nothing()),
                     g -> tuple(nothing(), nothing(), nothing(), nothing(), nothing(), nothing(), just(g)));
    }

    /**
     * Convenience method for projecting this coproduct onto a tuple and then extracting the first slot value.
     *
     * @return an optional value representing the projection of the "a" type index
     */
    default Maybe projectA() {
        return project()._1();
    }

    /**
     * Convenience method for projecting this coproduct onto a tuple and then extracting the second slot value.
     *
     * @return an optional value representing the projection of the "b" type index
     */
    default Maybe projectB() {
        return project()._2();
    }

    /**
     * Convenience method for projecting this coproduct onto a tuple and then extracting the third slot value.
     *
     * @return an optional value representing the projection of the "c" type index
     */
    default Maybe projectC() {
        return project()._3();
    }

    /**
     * Convenience method for projecting this coproduct onto a tuple and then extracting the fourth slot value.
     *
     * @return an optional value representing the projection of the "d" type index
     */
    default Maybe projectD() {
        return project()._4();
    }

    /**
     * Convenience method for projecting this coproduct onto a tuple and then extracting the fifth slot value.
     *
     * @return an optional value representing the projection of the "e" type index
     */
    default Maybe projectE() {
        return project()._5();
    }

    /**
     * Convenience method for projecting this coproduct onto a tuple and then extracting the sixth slot value.
     *
     * @return an optional value representing the projection of the "f" type index
     */
    default Maybe projectF() {
        return project()._6();
    }

    /**
     * Convenience method for projecting this coproduct onto a tuple and then extracting the seventh slot value.
     *
     * @return an optional value representing the projection of the "g" type index
     */
    default Maybe projectG() {
        return project()._7();
    }

    /**
     * Embed this coproduct inside another value; that is, given morphisms from this coproduct to R, apply
     * the appropriate morphism to this coproduct as a whole. Like {@link CoProduct7#match}, but without unwrapping the
     * value.
     *
     * @param aFn morphism A v B v C v D v E v F v G -> R, applied in the A case
     * @param bFn morphism A v B v C v D v E v F v G -> R, applied in the B case
     * @param cFn morphism A v B v C v D v E v F v G -> R, applied in the C case
     * @param dFn morphism A v B v C v D v E v F v G -> R, applied in the D case
     * @param eFn morphism A v B v C v D v E v F v G -> R, applied in the E case
     * @param fFn morphism A v B v C v D v E v F v G -> R, applied in the F case
     * @param gFn morphism A v B v C v D v E v F v G -> R, applied in the G case
     * @param  result type
     * @return the result of applying the appropriate morphism to this coproduct
     */
    @SuppressWarnings("unchecked")
    default  R embed(Function aFn,
                        Function bFn,
                        Function cFn,
                        Function dFn,
                        Function eFn,
                        Function fFn,
                        Function gFn) {
        return this.>match(constantly(fn1(aFn)),
                                       constantly(fn1(bFn)),
                                       constantly(fn1(cFn)),
                                       constantly(fn1(dFn)),
                                       constantly(fn1(eFn)),
                                       constantly(fn1(fFn)),
                                       constantly(fn1(gFn)))
                .apply((CP7) this);
    }
}