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

cyclops.companion.vavr.Queues Maven / Gradle / Ivy

The newest version!
package cyclops.companion.vavr;

import cyclops.monads.VavrWitness.tryType;
import io.vavr.Lazy;
import io.vavr.collection.*;
import io.vavr.concurrent.Future;
import io.vavr.control.*;
import com.aol.cyclops.vavr.hkt.*;
import cyclops.companion.CompletableFutures;
import cyclops.companion.Optionals;
import cyclops.control.Eval;
import cyclops.control.Maybe;
import cyclops.control.Reader;
import cyclops.control.Xor;
import cyclops.conversion.vavr.FromCyclopsReact;
import cyclops.monads.*;
import cyclops.monads.VavrWitness.*;
import com.aol.cyclops2.hkt.Higher;
import com.aol.cyclops2.types.anyM.AnyMSeq;
import cyclops.function.Fn3;
import cyclops.function.Fn4;
import cyclops.function.Monoid;
import cyclops.monads.Witness.*;
import cyclops.stream.ReactiveSeq;
import cyclops.typeclasses.*;
import com.aol.cyclops.vavr.hkt.ListKind;
import cyclops.monads.VavrWitness;
import cyclops.monads.VavrWitness.queue;
import com.aol.cyclops.vavr.hkt.QueueKind;
import cyclops.monads.AnyM;
import cyclops.monads.WitnessType;
import cyclops.monads.XorM;
import cyclops.typeclasses.comonad.Comonad;
import cyclops.typeclasses.foldable.Foldable;
import cyclops.typeclasses.foldable.Unfoldable;
import cyclops.typeclasses.functor.Functor;
import cyclops.typeclasses.instances.General;
import cyclops.typeclasses.monad.*;
import io.vavr.collection.List;
import io.vavr.collection.Queue;
import lombok.experimental.UtilityClass;
import org.jooq.lambda.tuple.Tuple2;

import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.function.BiFunction;
import java.util.function.BinaryOperator;
import java.util.function.Function;

import static com.aol.cyclops.vavr.hkt.QueueKind.widen;


public class Queues {

    public static   Coproduct coproduct(Queue type, InstanceDefinitions def1){
        return Coproduct.of(Xor.primary(widen(type)),def1, Instances.definitions());
    }
    public static   Coproduct coproduct(InstanceDefinitions def1,T... values){
        return  coproduct(Queue.of(values),def1);
    }
    public static  ,T> XorM xorM(Queue type){
        return XorM.right(anyM(type));
    }
    public static  ,T> XorM xorM(T... values){
        return xorM(Queue.of(values));
    }

    public static  AnyMSeq anyM(Queue option) {
        return AnyM.ofSeq(option, queue.INSTANCE);
    }
    /**
     * Perform a For Comprehension over a Queue, accepting 3 generating functions.
     * This results in a four level nested internal iteration over the provided Publishers.
     *
     *  
     * {@code
     *
     *   import static cyclops.Queues.forEach4;
     *
    forEach4(IntQueue.range(1,10).boxed(),
    a-> Queue.iterate(a,i->i+1).limit(10),
    (a,b) -> Queue.of(a+b),
    (a,b,c) -> Queue.just(a+b+c),
    Tuple::tuple)
     *
     * }
     * 
* * @param value1 top level Queue * @param value2 Nested Queue * @param value3 Nested Queue * @param value4 Nested Queue * @param yieldingFunction Generates a result per combination * @return Queue with an element per combination of nested publishers generated by the yielding function */ public static Queue forEach4(Queue value1, Function> value2, BiFunction> value3, Fn3> value4, Fn4 yieldingFunction) { return value1.flatMap(in -> { Queue a = value2.apply(in); return a.flatMap(ina -> { Queue b = value3.apply(in,ina); return b.flatMap(inb -> { Queue c = value4.apply(in,ina,inb); return c.map(in2 -> yieldingFunction.apply(in, ina, inb, in2)); }); }); }); } /** * Perform a For Comprehension over a Queue, accepting 3 generating function. * This results in a four level nested internal iteration over the provided Publishers. *
     * {@code
     *
     *  import static com.aol.cyclops2.reactor.Queuees.forEach4;
     *
     *  forEach4(IntQueue.range(1,10).boxed(),
    a-> Queue.iterate(a,i->i+1).limit(10),
    (a,b) -> Queue.just(a+b),
    (a,b,c) -> Queue.just(a+b+c),
    (a,b,c,d) -> a+b+c+d <100,
    Tuple::tuple);
     *
     * }
     * 
* * @param value1 top level Queue * @param value2 Nested Queue * @param value3 Nested Queue * @param value4 Nested Queue * @param filterFunction A filtering function, keeps values where the predicate holds * @param yieldingFunction Generates a result per combination * @return Queue with an element per combination of nested publishers generated by the yielding function */ public static Queue forEach4(Queue value1, Function> value2, BiFunction> value3, Fn3> value4, Fn4 filterFunction, Fn4 yieldingFunction) { return value1.flatMap(in -> { Queue a = value2.apply(in); return a.flatMap(ina -> { Queue b = value3.apply(in,ina); return b.flatMap(inb -> { Queue c = value4.apply(in,ina,inb); return c.filter(in2->filterFunction.apply(in,ina,inb,in2)) .map(in2 -> yieldingFunction.apply(in, ina, inb, in2)); }); }); }); } /** * Perform a For Comprehension over a Queue, accepting 2 generating function. * This results in a three level nested internal iteration over the provided Publishers. * *
     * {@code
     *
     * import static Queues.forEach3;
     *
     * forEach(IntQueue.range(1,10).boxed(),
    a-> Queue.iterate(a,i->i+1).limit(10),
    (a,b) -> Queue.of(a+b),
    Tuple::tuple);
     *
     * }
     * 
* * * @param value1 top level Queue * @param value2 Nested Queue * @param value3 Nested Queue * @param yieldingFunction Generates a result per combination * @return Queue with an element per combination of nested publishers generated by the yielding function */ public static Queue forEach3(Queue value1, Function> value2, BiFunction> value3, Fn3 yieldingFunction) { return value1.flatMap(in -> { Queue a = value2.apply(in); return a.flatMap(ina -> { Queue b = value3.apply(in,ina); return b.map(in2 -> yieldingFunction.apply(in, ina, in2)); }); }); } /** * Perform a For Comprehension over a Queue, accepting 2 generating function. * This results in a three level nested internal iteration over the provided Publishers. *
     * {@code
     *
     * import static Queues.forEach;
     *
     * forEach(IntQueue.range(1,10).boxed(),
    a-> Queue.iterate(a,i->i+1).limit(10),
    (a,b) -> Queue.of(a+b),
    (a,b,c) ->a+b+c<10,
    Tuple::tuple)
    .toQueueX();
     * }
     * 
* * @param value1 top level Queue * @param value2 Nested publisher * @param value3 Nested publisher * @param filterFunction A filtering function, keeps values where the predicate holds * @param yieldingFunction Generates a result per combination * @return */ public static Queue forEach3(Queue value1, Function> value2, BiFunction> value3, Fn3 filterFunction, Fn3 yieldingFunction) { return value1.flatMap(in -> { Queue a = value2.apply(in); return a.flatMap(ina -> { Queue b = value3.apply(in,ina); return b.filter(in2->filterFunction.apply(in,ina,in2)) .map(in2 -> yieldingFunction.apply(in, ina, in2)); }); }); } /** * Perform a For Comprehension over a Queue, accepting an additonal generating function. * This results in a two level nested internal iteration over the provided Publishers. * *
     * {@code
     *
     *  import static Queues.forEach2;
     *  forEach(IntQueue.range(1, 10).boxed(),
     *          i -> Queue.range(i, 10), Tuple::tuple)
    .forEach(System.out::println);

    //(1, 1)
    (1, 2)
    (1, 3)
    (1, 4)
    ...
     *
     * }
* * @param value1 top level Queue * @param value2 Nested publisher * @param yieldingFunction Generates a result per combination * @return */ public static Queue forEach2(Queue value1, Function> value2, BiFunction yieldingFunction) { return value1.flatMap(in -> { Queue a = value2.apply(in); return a.map(in2 -> yieldingFunction.apply(in, in2)); }); } /** * *
     * {@code
     *
     *   import static Queues.forEach2;
     *
     *   forEach(IntQueue.range(1, 10).boxed(),
     *           i -> Queue.range(i, 10),
     *           (a,b) -> a>2 && b<10,
     *           Tuple::tuple)
    .forEach(System.out::println);

    //(3, 3)
    (3, 4)
    (3, 5)
    (3, 6)
    (3, 7)
    (3, 8)
    (3, 9)
    ...

     *
     * }
* * * @param value1 top level Queue * @param value2 Nested publisher * @param filterFunction A filtering function, keeps values where the predicate holds * @param yieldingFunction Generates a result per combination * @return */ public static Queue forEach2(Queue value1, Function> value2, BiFunction filterFunction, BiFunction yieldingFunction) { return value1.flatMap(in -> { Queue a = value2.apply(in); return a.filter(in2->filterFunction.apply(in,in2)) .map(in2 -> yieldingFunction.apply(in, in2)); }); } public static Active allTypeclasses(Queue array){ return Active.of(widen(array), Queues.Instances.definitions()); } public static Nested mapM(Queue array, Function> fn, InstanceDefinitions defs){ Queue> e = array.map(fn); QueueKind> lk = widen(e); return Nested.of(lk, Queues.Instances.definitions(), defs); } /** * Companion class for creating Type Class instances for working with Queues * */ @UtilityClass public static class Instances { public static InstanceDefinitions definitions() { return new InstanceDefinitions() { @Override public Functor functor() { return Instances.functor(); } @Override public Pure unit() { return Instances.unit(); } @Override public Applicative applicative() { return Instances.zippingApplicative(); } @Override public Monad monad() { return Instances.monad(); } @Override public Maybe> monadZero() { return Maybe.just(Instances.monadZero()); } @Override public Maybe> monadPlus() { return Maybe.just(Instances.monadPlus()); } @Override public Maybe> monadPlus(Monoid> m) { return Maybe.just(Instances.monadPlus(m)); } @Override public Maybe> traverse() { return Maybe.just(Instances.traverse()); } @Override public Maybe> foldable() { return Maybe.just(Instances.foldable()); } @Override public Maybe> comonad() { return Maybe.none(); } @Override public Maybe> unfoldable() { return Maybe.just(Instances.unfoldable()); } }; } /** * * Transform a list, mulitplying every element by 2 * *
         * {@code
         *  QueueKind list = Queues.functor().map(i->i*2, QueueKind.widen(Arrays.asQueue(1,2,3));
         *
         *  //[2,4,6]
         *
         *
         * }
         * 
* * An example fluent api working with Queues *
         * {@code
         *   QueueKind list = Queues.unit()
        .unit("hello")
        .then(h->Queues.functor().map((String v) ->v.length(), h))
        .convert(QueueKind::narrowK);
         *
         * }
         * 
* * * @return A functor for Queues */ public static Functor functor(){ BiFunction,Function,QueueKind> map = Instances::map; return General.functor(map); } /** *
         * {@code
         * QueueKind list = Queues.unit()
        .unit("hello")
        .convert(QueueKind::narrowK);

        //Arrays.asQueue("hello"))
         *
         * }
         * 
* * * @return A factory for Queues */ public static Pure unit(){ return General.unit(QueueKind::of); } /** * *
         * {@code
         * import static com.aol.cyclops.hkt.jdk.QueueKind.widen;
         * import static com.aol.cyclops.util.function.Lambda.l1;
         * import static java.util.Arrays.asQueue;
         *
        Queues.zippingApplicative()
        .ap(widen(asQueue(l1(this::multiplyByTwo))),widen(asQueue(1,2,3)));
         *
         * //[2,4,6]
         * }
         * 
* * * Example fluent API *
         * {@code
         * QueueKind> listFn =Queues.unit()
         *                                                  .unit(Lambda.l1((Integer i) ->i*2))
         *                                                  .convert(QueueKind::narrowK);

        QueueKind list = Queues.unit()
        .unit("hello")
        .then(h->Queues.functor().map((String v) ->v.length(), h))
        .then(h->Queues.zippingApplicative().ap(listFn, h))
        .convert(QueueKind::narrowK);

        //Arrays.asQueue("hello".length()*2))
         *
         * }
         * 
* * * @return A zipper for Queues */ public static Applicative zippingApplicative(){ BiFunction>,QueueKind,QueueKind> ap = Instances::ap; return General.applicative(functor(), unit(), ap); } /** * *
         * {@code
         * import static com.aol.cyclops.hkt.jdk.QueueKind.widen;
         * QueueKind list  = Queues.monad()
        .flatMap(i->widen(QueueX.range(0,i)), widen(Arrays.asQueue(1,2,3)))
        .convert(QueueKind::narrowK);
         * }
         * 
* * Example fluent API *
         * {@code
         *    QueueKind list = Queues.unit()
        .unit("hello")
        .then(h->Queues.monad().flatMap((String v) ->Queues.unit().unit(v.length()), h))
        .convert(QueueKind::narrowK);

        //Arrays.asQueue("hello".length())
         *
         * }
         * 
* * @return Type class with monad functions for Queues */ public static Monad monad(){ BiFunction,Function>,Higher> flatMap = Instances::flatMap; return General.monad(zippingApplicative(), flatMap); } /** * *
         * {@code
         *  QueueKind list = Queues.unit()
        .unit("hello")
        .then(h->Queues.monadZero().filter((String t)->t.startsWith("he"), h))
        .convert(QueueKind::narrowK);

        //Arrays.asQueue("hello"));
         *
         * }
         * 
* * * @return A filterable monad (with default value) */ public static MonadZero monadZero(){ return General.monadZero(monad(), widen(Queue.empty())); } /** *
         * {@code
         *  QueueKind list = Queues.monadPlus()
        .plus(QueueKind.widen(Arrays.asQueue()), QueueKind.widen(Arrays.asQueue(10)))
        .convert(QueueKind::narrowK);
        //Arrays.asQueue(10))
         *
         * }
         * 
* @return Type class for combining Queues by concatenation */ public static MonadPlus monadPlus(){ Monoid> m = Monoid.of(widen(Queue.empty()), Instances::concat); Monoid> m2= (Monoid)m; return General.monadPlus(monadZero(),m2); } /** * *
         * {@code
         *  Monoid> m = Monoid.of(QueueKind.widen(Arrays.asQueue()), (a,b)->a.isEmpty() ? b : a);
        QueueKind list = Queues.monadPlus(m)
        .plus(QueueKind.widen(Arrays.asQueue(5)), QueueKind.widen(Arrays.asQueue(10)))
        .convert(QueueKind::narrowK);
        //Arrays.asQueue(5))
         *
         * }
         * 
* * @param m Monoid to use for combining Queues * @return Type class for combining Queues */ public static MonadPlus monadPlus(Monoid> m){ Monoid> m2= (Monoid)m; return General.monadPlus(monadZero(),m2); } public static MonadPlus monadPlusK(Monoid> m){ Monoid> m2= (Monoid)m; return General.monadPlus(monadZero(),m2); } /** * @return Type class for traversables with traverse / sequence operations */ public static Traverse traverse(){ BiFunction,QueueKind>,Higher>> sequenceFn = (ap, list) -> { Higher> identity = ap.unit(widen(Queue.empty())); BiFunction>,Higher,Higher>> combineToQueue = (acc, next) -> ap.apBiFn(ap.unit((a, b) -> widen(QueueKind.narrow(a).append(b))), acc,next); BinaryOperator>> combineQueues = (a, b)-> ap.apBiFn(ap.unit((l1, l2)-> widen(QueueKind.narrow(l1).appendAll(l2.narrow()))),a,b); ; return ReactiveSeq.fromIterable(QueueKind.narrow(list)) .reduce(identity, combineToQueue, combineQueues); }; BiFunction,Higher>,Higher>> sequenceNarrow = (a,b) -> QueueKind.widen2(sequenceFn.apply(a, QueueKind.narrowK(b))); return General.traverse(zippingApplicative(), sequenceNarrow); } /** * *
         * {@code
         * int sum  = Queues.foldable()
        .foldLeft(0, (a,b)->a+b, QueueKind.widen(Arrays.asQueue(1,2,3,4)));

        //10
         *
         * }
         * 
* * * @return Type class for folding / reduction operations */ public static Foldable foldable(){ BiFunction,Higher,T> foldRightFn = (m, l)-> ReactiveSeq.fromIterable(QueueKind.narrow(l)).foldRight(m); BiFunction,Higher,T> foldLeftFn = (m, l)-> ReactiveSeq.fromIterable(QueueKind.narrow(l)).reduce(m); return General.foldable(foldRightFn, foldLeftFn); } private static QueueKind concat(QueueKind l1, QueueKind l2){ return widen(l1.appendAll(QueueKind.narrow(l2))); } private static QueueKind ap(QueueKind> lt, QueueKind list){ return widen(FromCyclopsReact.fromStream(ReactiveSeq.fromIterable(lt.narrow()).zip(list.narrow(), (a, b)->a.apply(b))).toQueue()); } private static Higher flatMap(Higher lt, Function> fn){ return widen(QueueKind.narrow(lt).flatMap(fn.andThen(QueueKind::narrow))); } private static QueueKind map(QueueKind lt, Function fn){ return widen(QueueKind.narrow(lt).map(in->fn.apply(in))); } public static Unfoldable unfoldable(){ return new Unfoldable() { @Override public Higher unfold(T b, Function>> fn) { return widen(ReactiveSeq.unfold(b,fn).collect(Queue.collector())); } }; } } public static interface QueueNested{ public static Nested lazy(Queue> type){ return Nested.of(widen(type.map(LazyKind::widen)),Instances.definitions(),Lazys.Instances.definitions()); } public static Nested queueTry(Queue> type){ return Nested.of(widen(type.map(TryKind::widen)),Instances.definitions(),Trys.Instances.definitions()); } public static Nested future(Queue> type){ return Nested.of(widen(type.map(FutureKind::widen)),Instances.definitions(),Futures.Instances.definitions()); } public static Nested queue(Queue> nested){ return Nested.of(widen(nested.map(QueueKind::widen)),Instances.definitions(),Queues.Instances.definitions()); } public static Nested, R> either(Queue> nested){ return Nested.of(widen(nested.map(EitherKind::widen)),Instances.definitions(),Eithers.Instances.definitions()); } public static Nested stream(Queue> nested){ return Nested.of(widen(nested.map(StreamKind::widen)),Instances.definitions(),Streams.Instances.definitions()); } public static Nested list(Queue> nested){ return Nested.of(widen(nested.map(ListKind::widen)), Instances.definitions(),Lists.Instances.definitions()); } public static Nested array(Queue> nested){ return Nested.of(widen(nested.map(ArrayKind::widen)),Instances.definitions(),Arrays.Instances.definitions()); } public static Nested vector(Queue> nested){ return Nested.of(widen(nested.map(VectorKind::widen)),Instances.definitions(),Vectors.Instances.definitions()); } public static Nested set(Queue> nested){ return Nested.of(widen(nested.map(HashSetKind::widen)),Instances.definitions(), HashSets.Instances.definitions()); } public static Nested reactiveSeq(Queue> nested){ QueueKind> x = widen(nested); QueueKind> y = (QueueKind)x; return Nested.of(y,Instances.definitions(),ReactiveSeq.Instances.definitions()); } public static Nested maybe(Queue> nested){ QueueKind> x = widen(nested); QueueKind> y = (QueueKind)x; return Nested.of(y,Instances.definitions(),Maybe.Instances.definitions()); } public static Nested eval(Queue> nested){ QueueKind> x = widen(nested); QueueKind> y = (QueueKind)x; return Nested.of(y,Instances.definitions(),Eval.Instances.definitions()); } public static Nested cyclopsFuture(Queue> nested){ QueueKind> x = widen(nested); QueueKind> y = (QueueKind)x; return Nested.of(y,Instances.definitions(),cyclops.async.Future.Instances.definitions()); } public static Nested, P> xor(Queue> nested){ QueueKind> x = widen(nested); QueueKind, P>> y = (QueueKind)x; return Nested.of(y,Instances.definitions(),Xor.Instances.definitions()); } public static Nested, T> reader(Queue> nested){ QueueKind> x = widen(nested); QueueKind, T>> y = (QueueKind)x; return Nested.of(y,Instances.definitions(),Reader.Instances.definitions()); } public static Nested, P> cyclopsTry(Queue> nested){ QueueKind> x = widen(nested); QueueKind, P>> y = (QueueKind)x; return Nested.of(y,Instances.definitions(),cyclops.control.Try.Instances.definitions()); } public static Nested queueal(Queue> nested){ QueueKind> x = widen(nested); QueueKind> y = (QueueKind)x; return Nested.of(y,Instances.definitions(), Optionals.Instances.definitions()); } public static Nested completableQueue(Queue> nested){ QueueKind> x = widen(nested); QueueKind> y = (QueueKind)x; return Nested.of(y,Instances.definitions(), CompletableFutures.Instances.definitions()); } public static Nested javaStream(Queue> nested){ QueueKind> x = widen(nested); QueueKind> y = (QueueKind)x; return Nested.of(y,Instances.definitions(), cyclops.companion.Streams.Instances.definitions()); } } public static interface NestedQueue{ public static Nested reactiveSeq(ReactiveSeq> nested){ ReactiveSeq> x = nested.map(QueueKind::widenK); return Nested.of(x,ReactiveSeq.Instances.definitions(),Instances.definitions()); } public static Nested maybe(Maybe> nested){ Maybe> x = nested.map(QueueKind::widenK); return Nested.of(x,Maybe.Instances.definitions(),Instances.definitions()); } public static Nested eval(Eval> nested){ Eval> x = nested.map(QueueKind::widenK); return Nested.of(x,Eval.Instances.definitions(),Instances.definitions()); } public static Nested cyclopsFuture(cyclops.async.Future> nested){ cyclops.async.Future> x = nested.map(QueueKind::widenK); return Nested.of(x,cyclops.async.Future.Instances.definitions(),Instances.definitions()); } public static Nested,queue, P> xor(Xor> nested){ Xor> x = nested.map(QueueKind::widenK); return Nested.of(x,Xor.Instances.definitions(),Instances.definitions()); } public static Nested,queue, T> reader(Reader> nested){ Reader> x = nested.map(QueueKind::widenK); return Nested.of(x,Reader.Instances.definitions(),Instances.definitions()); } public static Nested,queue, P> cyclopsTry(cyclops.control.Try, S> nested){ cyclops.control.Try, S> x = nested.map(QueueKind::widenK); return Nested.of(x,cyclops.control.Try.Instances.definitions(),Instances.definitions()); } public static Nested queueal(Optional> nested){ Optional> x = nested.map(QueueKind::widenK); return Nested.of(Optionals.OptionalKind.widen(x), Optionals.Instances.definitions(), Instances.definitions()); } public static Nested completableQueue(CompletableFuture> nested){ CompletableFuture> x = nested.thenApply(QueueKind::widenK); return Nested.of(CompletableFutures.CompletableFutureKind.widen(x), CompletableFutures.Instances.definitions(),Instances.definitions()); } public static Nested javaStream(java.util.stream.Stream> nested){ java.util.stream.Stream> x = nested.map(QueueKind::widenK); return Nested.of(cyclops.companion.Streams.StreamKind.widen(x), cyclops.companion.Streams.Instances.definitions(),Instances.definitions()); } } }