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

spike.RecursiveResult Maven / Gradle / Ivy

There is a newer version: 5.5.0
Show newest version
package spike;

import com.jnape.palatable.lambda.adt.coproduct.CoProduct2;
import com.jnape.palatable.lambda.functor.Applicative;
import com.jnape.palatable.lambda.functor.Bifunctor;
import com.jnape.palatable.lambda.monad.Monad;
import com.jnape.palatable.lambda.traversable.Traversable;

import java.util.Objects;
import java.util.function.Function;

/**
 * Specialized {@link CoProduct2} representing the possible results of a primitive recursive function.
 * Used by {@link Trampoline} to cheat around {@link CoProduct2#match} and quickly unpack values via
 * instanceof checks to package private inner subtypes.
 *
 * @param  the recursive function's input type
 * @param  the recursive function's output type
 * @see Trampoline
 */
public abstract class RecursiveResult implements CoProduct2>, Bifunctor>, Monad>, Traversable> {

    private RecursiveResult() {
    }

    @Override
    @SuppressWarnings("unchecked")
    public  RecursiveResult biMapL(Function fn) {
        return (RecursiveResult) Bifunctor.super.biMapL(fn);
    }

    @Override
    @SuppressWarnings("unchecked")
    public  RecursiveResult biMapR(Function fn) {
        return (RecursiveResult) Bifunctor.super.biMapR(fn);
    }

    @Override
    public  RecursiveResult biMap(Function lFn,
                                              Function rFn) {
        return match(a -> recurse(lFn.apply(a)), b -> terminate(rFn.apply(b)));
    }

    @Override
    public  RecursiveResult flatMap(
            Function>> f) {
        return match(RecursiveResult::recurse, b -> f.apply(b).coerce());
    }

    @Override
    public  RecursiveResult pure(C c) {
        return terminate(c);
    }

    @Override
    public  RecursiveResult fmap(Function fn) {
        return Monad.super.fmap(fn).coerce();
    }

    @Override
    public  RecursiveResult zip(
            Applicative, RecursiveResult> appFn) {
        return Monad.super.zip(appFn).coerce();
    }

    @Override
    public  RecursiveResult discardL(Applicative> appB) {
        return Monad.super.discardL(appB).coerce();
    }

    @Override
    public  RecursiveResult discardR(Applicative> appB) {
        return Monad.super.discardR(appB).coerce();
    }

    @Override
    @SuppressWarnings("unchecked")
    public  Applicative, App> traverse(
            Function> fn,
            Function>, ? extends Applicative>, App>> pure) {
        return match(__ -> pure.apply(coerce()).fmap(x -> (RecursiveResult) x),
                     b -> fn.apply(b).fmap(this::pure));
    }

    public static  RecursiveResult recurse(A a) {
        return new Recurse<>(a);
    }

    public static  RecursiveResult terminate(B b) {
        return new Terminate<>(b);
    }

    static final class Recurse extends RecursiveResult {
        final A a;

        private Recurse(A a) {
            this.a = a;
        }

        @Override
        public  R match(Function aFn, Function bFn) {
            return aFn.apply(a);
        }

        @Override
        public boolean equals(Object other) {
            return other instanceof Recurse && Objects.equals(a, ((Recurse) other).a);
        }

        @Override
        public int hashCode() {
            return Objects.hash(a);
        }

        @Override
        public String toString() {
            return "Recurse{" +
                    "a=" + a +
                    '}';
        }
    }

    static final class Terminate extends RecursiveResult {
        final B b;

        private Terminate(B b) {
            this.b = b;
        }

        @Override
        public  R match(Function aFn, Function bFn) {
            return bFn.apply(b);
        }

        @Override
        public boolean equals(Object other) {
            return other instanceof Terminate && Objects.equals(b, ((Terminate) other).b);
        }

        @Override
        public int hashCode() {
            return Objects.hash(b);
        }

        @Override
        public String toString() {
            return "Terminate{" +
                    "b=" + b +
                    '}';
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy